C++ MFC 功能包 -->在 CDialog 上创建多个 CDockablePanes

发布于 2024-10-16 02:00:30 字数 2221 浏览 2 评论 0原文

我尝试在 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

红尘作伴 2024-10-23 02:00:30

好吧,我终于明白了。

我没有让 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.

你好,陌生人 2024-10-23 02:00:30

另一个简单的方法是,如果您处于实现对接框架的 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).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文