C++ MFC 功能包 -->在 CDialog 上创建多个 CDockablePanes
我尝试在 CDialog 上创建一个区域,我可以在其中放置一些 CDockablePanes。这些应该可以完美地停靠到固定的对话框内容。
Codejock 对话框窗格示例正是我想要的,但通过 MFC 功能包类实现: http:// /codejock.com/downloads/samples/dockingpane.asp
目前我得到了一个从CFrameWndEx继承的类,它嵌入在CDialog中。我还得到了一个可用的 CDockablePane 。我可以将其拔出并移动它,但是当我想将其停靠时,程序崩溃了。
这是因为可停靠窗格类尝试生成一个虚拟窗格来预览真实窗格的位置。它调用 GetTopLevelFrame() 返回 NULL。这会在 afxpane.cpp @CreateEx() 中产生崩溃。
有人对我有任何帮助或想法吗? :(
问候,
编辑:
好的,一些代码:
我编写了一个继承自 CFrameWndEx 的小类(因为它的构造函数受到保护):
class CMyFrame: public CFrameWndEx
{
public:
DECLARE_MESSAGE_MAP()
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
CDockablePane m_DockWnd; // Will use an own class inherited from CDockablePane later on
};
现在我将此类嵌入到我的 CDialog 中,并将其大小更改为对话框大小:
BOOL CMyDlg::OnInitDialog()
{
CRect wndRect;
GetWindowRect(wndRect);
m_pFrame = new CMyFrame();
m_pFrame->Create(NULL, NULL, WS_CHILD | WS_VISIBLE | WS_BORDER, wndRect, this);
m_pFrame->MoveWindow(wndRect);
CDialog::OnInitDialog();
...
}
在 CMyFrame 类的 OnCreate() 中,我设置了 CDockablePane 并将其停靠:
int CMyFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CFrameWndEx::OnCreate(lpCreateStruct) == -1)
return -1;
CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows));
EnableDocking(CBRS_ALIGN_ANY);
// DT_SMART creates dummy dockable panes for previewing the possible position of
// the currently floating pane, this leads to a crash at call to GetTopLevelFrame()
CDockingManager::SetDockingMode(DT_SMART);
EnableAutoHidePanes(CBRS_ALIGN_ANY);
// m_DockWnd is a CDockablePane
if (!m_DockWnd.Create(_T("Test"), this, CRect(0, 0, 200, 200), TRUE, IDC_DOCK_WND,
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | CBRS_LEFT | CBRS_FLOAT_MULTI))
{
TRACE0("Failed to create Properties window\n");
return 1; // failed to create
}
m_DockWnd.EnableDocking(CBRS_ALIGN_ANY);
DockPane(&m_DockWnd);
return 0;
}
I try to create an area onto a CDialog, where I can put some CDockablePanes in. Those shall be perfectly dockable to a fixed dialog content.
The Codejock Dialog Panes Sample is exactly what I want, but realized with the MFC feature pack classes: http://codejock.com/downloads/samples/dockingpane.asp
At the moment I got a class inherited from CFrameWndEx, which is embedded in the CDialog. I also got a working CDockablePane in it. I can undock it and move it, but when I want to dock it the program crashes.
This is because the dockable pane class tries to generate a dummy pane for previewing where the real pane would go. It calls GetTopLevelFrame() which returns NULL. This produces the crash in afxpane.cpp @CreateEx().
Does someone has any help or ideas for me? :(
Greets,
Edit:
Okay, some code:
I wrote a little class inherited from CFrameWndEx (because its constructor is protected):
class CMyFrame: public CFrameWndEx
{
public:
DECLARE_MESSAGE_MAP()
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
CDockablePane m_DockWnd; // Will use an own class inherited from CDockablePane later on
};
Now I embedded this class in my CDialog and change its size to the dialogs size:
BOOL CMyDlg::OnInitDialog()
{
CRect wndRect;
GetWindowRect(wndRect);
m_pFrame = new CMyFrame();
m_pFrame->Create(NULL, NULL, WS_CHILD | WS_VISIBLE | WS_BORDER, wndRect, this);
m_pFrame->MoveWindow(wndRect);
CDialog::OnInitDialog();
...
}
In the OnCreate() of the CMyFrame class I set up the CDockablePane and dock it:
int CMyFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CFrameWndEx::OnCreate(lpCreateStruct) == -1)
return -1;
CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows));
EnableDocking(CBRS_ALIGN_ANY);
// DT_SMART creates dummy dockable panes for previewing the possible position of
// the currently floating pane, this leads to a crash at call to GetTopLevelFrame()
CDockingManager::SetDockingMode(DT_SMART);
EnableAutoHidePanes(CBRS_ALIGN_ANY);
// m_DockWnd is a CDockablePane
if (!m_DockWnd.Create(_T("Test"), this, CRect(0, 0, 200, 200), TRUE, IDC_DOCK_WND,
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | CBRS_LEFT | CBRS_FLOAT_MULTI))
{
TRACE0("Failed to create Properties window\n");
return 1; // failed to create
}
m_DockWnd.EnableDocking(CBRS_ALIGN_ANY);
DockPane(&m_DockWnd);
return 0;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
好吧,我终于明白了。
我没有让 MFC 创建 dummywnd,而是自己创建了它。因此,MFC 会跳过创建和对 GetTopLevelFrame() 的调用。
现在的问题是,dummywnd 成员变量受到保护并且没有公共 set 方法。所以我继承了一个类并为自己构建了一个公共设置方法。
Okay, I finally got it.
Instead of letting the MFC create the dummywnd, I created it by myself. So the MFC skips the creation and the call to GetTopLevelFrame().
Now the problem was, that the dummywnd member variable was protected and had no public set method. So I inherited a class and built myself a public set method.
另一个简单的方法是,如果您处于实现对接框架的 Dlg 中,则将对接模式设置为 DT_IMMEDIATE。称呼
CDockingManager::SetDockingMode(DT_IMMEDIATE);
在 CFrameWndEx 对象的 OnCreate 中(或适当的地方)。
Another simple method is to set your docking mode to DT_IMMEDIATE if you are in a Dlg implementing Docking Frames. Call
CDockingManager::SetDockingMode(DT_IMMEDIATE);
in you CFrameWndEx object's OnCreate (or someplace appropriate).