Mfc 在CDDialog上创建多个CDockablePane

Mfc 在CDDialog上创建多个CDockablePane,mfc,cdialog,dockable,Mfc,Cdialog,Dockable,我试图做到与本文描述的完全相同: “” 我按照他的程序进行操作,现在可以卸下并移动CDockablePane,但当它重新停靠时,会发生同样的崩溃。在他自己的回答中,他说他自己创建了dummywnd,所以MFC跳过了创建和对GetToLevel Frame()的调用。这就是我困惑的地方,我该如何准确地创建dummywnd 我的第二个问题是如何在CMyFrame和CDialog之间交换数据 问了这个问题并回答了这个问题的人似乎多年来都不活跃,无法联系到他。谁能帮忙或有什么想法吗 谢谢 编辑: 我破

我试图做到与本文描述的完全相同: “”

我按照他的程序进行操作,现在可以卸下并移动CDockablePane,但当它重新停靠时,会发生同样的崩溃。在他自己的回答中,他说他自己创建了dummywnd,所以MFC跳过了创建和对GetToLevel Frame()的调用。这就是我困惑的地方,我该如何准确地创建dummywnd

我的第二个问题是如何在CMyFrame和CDialog之间交换数据

问了这个问题并回答了这个问题的人似乎多年来都不活跃,无法联系到他。谁能帮忙或有什么想法吗

谢谢


编辑:

我破坏了程序,完全按照另一位作者的描述进行了追溯。上面提到的虚拟窗口实际上位于afxdragframeinpl.cpp中:

void cmfcdragframeinpl::MoveDragFrame(BOOL bForceMove)

它在何处创建:

m_pWndDummy=新的CDummyDockablePane

并呼吁:

m_pWndDummy->CreateEx(0,_T(“”),afxGetToLevel框架(m_pDraggedWnd),正确(0,0,0,0),FALSE,AFX_DUMMY_WND_ID,WS_CHILD)

是的,我试图在对话框中创建一个CFrameWndEx作为子窗口,然后在该CFrameWndEx中添加子CDockablePane

基本上,我有一个带有一些控件的MFC对话框a,在这个对话框a中,我需要一些撕下的tabsXYZ,我需要在每个撕下的tabsXYZ中添加一些控件。这意味着每个撕掉的tabsXYZ实际上是一个子dialogB。因此,我尝试在dialogA中使用CDockablePanes(实际上是CPanedDialog)

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();
    ...
}
我不推荐在对话框中放置框架窗口的上面的代码,因为
CFrameWndEx
会做各种奇怪的事情,很容易破坏这段代码。令人惊讶的是,它在VS2015上运行良好,我无法复制任何崩溃。但窗户的行为仍然很奇怪

最好创建一个新的框架窗口,并在框架中放置一个子对话框。例如:

class CMyFrame : public CFrameWndEx
{
    CDialog m_dialog;

    int OnCreate(LPCREATESTRUCT lpCreateStruct)
    {
        CFrameWndEx::OnCreate(lpCreateStruct);
        m_dialog.Create(IDD_CHILD1, this);
        CRect rc;
        m_dialog.GetClientRect(&rc);
        m_dialog.SetWindowPos(NULL, 0, 0, rc.right, rc.bottom, SWP_SHOWWINDOW);
        return 1;
    }

    DECLARE_MESSAGE_MAP()
};
class CMyFrame : public CFrameWndEx
{
    CDockablePane m_DockWnd;
    CDialog m_dialog;

    int OnCreate(LPCREATESTRUCT lpCreateStruct)
    {
        CFrameWndEx::OnCreate(lpCreateStruct);

        CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows));
        CDockingManager::SetDockingMode(DT_SMART);
        EnableAutoHidePanes(CBRS_ALIGN_ANY);

        m_DockWnd.Create(_T("Test"), this, CRect(0, 0, 200, 200), TRUE, 0,
            WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
            CBRS_LEFT | CBRS_FLOAT_MULTI);

        m_dialog.Create(IDD_PAGE1, &m_DockWnd);
        CRect rdialog;
        m_dialog.GetClientRect(&rdialog);
        m_dialog.SetWindowPos(NULL, 0, 0, rdialog.Width(), rdialog.Height(), SWP_SHOWWINDOW);

        m_DockWnd.SetMinSize(rdialog.Size());
        m_DockWnd.EnableDocking(CBRS_ALIGN_ANY);

        EnableDocking(CBRS_ALIGN_ANY);

        DockPane(&m_DockWnd);

        return 0;
    }
    ...
};
您可以按如下方式打开窗口:

void CMyMainFrame::OnButton()
{
    CMyFrame *frame = new CMyFrame;
    frame->LoadFrame(IDR_MAINFRAME, 
            WS_POPUPWINDOW | WS_THICKFRAME | WS_CAPTION | WS_SYSMENU, this);
    frame->SetMenu(0);
    frame->ShowWindow(SW_SHOW);
}
您还可以创建一个子对话框并将其放入停靠窗格中。例如:

class CMyFrame : public CFrameWndEx
{
    CDialog m_dialog;

    int OnCreate(LPCREATESTRUCT lpCreateStruct)
    {
        CFrameWndEx::OnCreate(lpCreateStruct);
        m_dialog.Create(IDD_CHILD1, this);
        CRect rc;
        m_dialog.GetClientRect(&rc);
        m_dialog.SetWindowPos(NULL, 0, 0, rc.right, rc.bottom, SWP_SHOWWINDOW);
        return 1;
    }

    DECLARE_MESSAGE_MAP()
};
class CMyFrame : public CFrameWndEx
{
    CDockablePane m_DockWnd;
    CDialog m_dialog;

    int OnCreate(LPCREATESTRUCT lpCreateStruct)
    {
        CFrameWndEx::OnCreate(lpCreateStruct);

        CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows));
        CDockingManager::SetDockingMode(DT_SMART);
        EnableAutoHidePanes(CBRS_ALIGN_ANY);

        m_DockWnd.Create(_T("Test"), this, CRect(0, 0, 200, 200), TRUE, 0,
            WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
            CBRS_LEFT | CBRS_FLOAT_MULTI);

        m_dialog.Create(IDD_PAGE1, &m_DockWnd);
        CRect rdialog;
        m_dialog.GetClientRect(&rdialog);
        m_dialog.SetWindowPos(NULL, 0, 0, rdialog.Width(), rdialog.Height(), SWP_SHOWWINDOW);

        m_DockWnd.SetMinSize(rdialog.Size());
        m_DockWnd.EnableDocking(CBRS_ALIGN_ANY);

        EnableDocking(CBRS_ALIGN_ANY);

        DockPane(&m_DockWnd);

        return 0;
    }
    ...
};
还要记住,如果主窗口也是
CFrameWndEx
,则在
InitInstance
中进行如下调用:

SetRegistryKey(_T("MyCompany\\MyApp"));
SetRegistryBase(_T("MainFrame"));
打开新的框架窗口时,必须使用

SetRegistryBase(_T("CMyFrame"));
然后在退出
CMyFrame

我不推荐在对话框中放置框架窗口的上面的代码,因为
CFrameWndEx
会做各种奇怪的事情,很容易破坏这段代码。令人惊讶的是,它在VS2015上运行良好,我无法复制任何崩溃。但窗户的行为仍然很奇怪

最好创建一个新的框架窗口,并在框架中放置一个子对话框。例如:

class CMyFrame : public CFrameWndEx
{
    CDialog m_dialog;

    int OnCreate(LPCREATESTRUCT lpCreateStruct)
    {
        CFrameWndEx::OnCreate(lpCreateStruct);
        m_dialog.Create(IDD_CHILD1, this);
        CRect rc;
        m_dialog.GetClientRect(&rc);
        m_dialog.SetWindowPos(NULL, 0, 0, rc.right, rc.bottom, SWP_SHOWWINDOW);
        return 1;
    }

    DECLARE_MESSAGE_MAP()
};
class CMyFrame : public CFrameWndEx
{
    CDockablePane m_DockWnd;
    CDialog m_dialog;

    int OnCreate(LPCREATESTRUCT lpCreateStruct)
    {
        CFrameWndEx::OnCreate(lpCreateStruct);

        CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows));
        CDockingManager::SetDockingMode(DT_SMART);
        EnableAutoHidePanes(CBRS_ALIGN_ANY);

        m_DockWnd.Create(_T("Test"), this, CRect(0, 0, 200, 200), TRUE, 0,
            WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
            CBRS_LEFT | CBRS_FLOAT_MULTI);

        m_dialog.Create(IDD_PAGE1, &m_DockWnd);
        CRect rdialog;
        m_dialog.GetClientRect(&rdialog);
        m_dialog.SetWindowPos(NULL, 0, 0, rdialog.Width(), rdialog.Height(), SWP_SHOWWINDOW);

        m_DockWnd.SetMinSize(rdialog.Size());
        m_DockWnd.EnableDocking(CBRS_ALIGN_ANY);

        EnableDocking(CBRS_ALIGN_ANY);

        DockPane(&m_DockWnd);

        return 0;
    }
    ...
};
您可以按如下方式打开窗口:

void CMyMainFrame::OnButton()
{
    CMyFrame *frame = new CMyFrame;
    frame->LoadFrame(IDR_MAINFRAME, 
            WS_POPUPWINDOW | WS_THICKFRAME | WS_CAPTION | WS_SYSMENU, this);
    frame->SetMenu(0);
    frame->ShowWindow(SW_SHOW);
}
您还可以创建一个子对话框并将其放入停靠窗格中。例如:

class CMyFrame : public CFrameWndEx
{
    CDialog m_dialog;

    int OnCreate(LPCREATESTRUCT lpCreateStruct)
    {
        CFrameWndEx::OnCreate(lpCreateStruct);
        m_dialog.Create(IDD_CHILD1, this);
        CRect rc;
        m_dialog.GetClientRect(&rc);
        m_dialog.SetWindowPos(NULL, 0, 0, rc.right, rc.bottom, SWP_SHOWWINDOW);
        return 1;
    }

    DECLARE_MESSAGE_MAP()
};
class CMyFrame : public CFrameWndEx
{
    CDockablePane m_DockWnd;
    CDialog m_dialog;

    int OnCreate(LPCREATESTRUCT lpCreateStruct)
    {
        CFrameWndEx::OnCreate(lpCreateStruct);

        CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows));
        CDockingManager::SetDockingMode(DT_SMART);
        EnableAutoHidePanes(CBRS_ALIGN_ANY);

        m_DockWnd.Create(_T("Test"), this, CRect(0, 0, 200, 200), TRUE, 0,
            WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
            CBRS_LEFT | CBRS_FLOAT_MULTI);

        m_dialog.Create(IDD_PAGE1, &m_DockWnd);
        CRect rdialog;
        m_dialog.GetClientRect(&rdialog);
        m_dialog.SetWindowPos(NULL, 0, 0, rdialog.Width(), rdialog.Height(), SWP_SHOWWINDOW);

        m_DockWnd.SetMinSize(rdialog.Size());
        m_DockWnd.EnableDocking(CBRS_ALIGN_ANY);

        EnableDocking(CBRS_ALIGN_ANY);

        DockPane(&m_DockWnd);

        return 0;
    }
    ...
};
还要记住,如果主窗口也是
CFrameWndEx
,则在
InitInstance
中进行如下调用:

SetRegistryKey(_T("MyCompany\\MyApp"));
SetRegistryBase(_T("MainFrame"));
打开新的框架窗口时,必须使用

SetRegistryBase(_T("CMyFrame"));

然后在退出
CMyFrame

时将其更改回
SetRegistryBase(\u T(“大型机”)
,我对此没有太多经验,但您发布的链接看起来像是黑客。那里没有“虚拟窗口”。它似乎创建了一个
CFrameWndEx
作为对话框的子窗口。我认为那不可取。您有基于对话框的应用程序吗?如果是,您是否正在尝试将窗格添加到主对话框中?注意,您只需创建一个
CFrameWndEx
并将子对话框添加到其中,或者将子对话框添加到可文档窗格中。您可以跳过文档/视图部分。感谢您的回复。这不是黑客,我已经改变了链接的显示方式。并在“编辑”部分的顶部添加了更多详细信息。关于如何在对话框中使用儿童可拆卸/可固定对话框,您有什么建议吗?最好,你没有回答我的问题。没有理由将框架窗口创建为对话框的子窗口,没有任何好处
CFrameWndEx
可以做任何事情
CDialog
can等等。可以将子对话框添加到框架窗口。另一个链接中提到的方法对初学者来说可能更方便,但它需要可怕的黑客攻击,这会导致更多的问题。我有一个相对较大且复杂的应用程序,它基于CMDIFrameWnd。我正在处理的部分是CDialogEx(比如dialogA),我只能从与该dialogA关联的类中获取所需的数据。我需要在dialogA中创建子dialogXYZ来修改一些属性。我本可以使用一个选项卡控件,每个选项卡对应对话框X、Y和Z中的一个。但同时,我需要对话框X、Y和Z同时出现在屏幕上,所以我试图找到一个“撕下选项卡”的解决方案。我没有得到任何关于“撕下CDialogEx中的标签”的参考资料,所以它让我达到了现在的水平。我对此没有太多经验,但你发布的链接看起来像是黑客。那里没有“虚拟窗口”。它似乎创建了一个
CFrameWndEx
作为对话框的子窗口。我认为那不可取。您有基于对话框的应用程序吗?如果是,您是否正在尝试将窗格添加到主对话框中?注意,您只需创建一个
CFrameWndEx
并将子对话框添加到其中,或者将子对话框添加到可文档窗格中。您可以跳过文档/视图部分。感谢您的回复。这不是黑客,我已经改变了链接的显示方式。并在“编辑”部分的顶部添加了更多详细信息。关于如何在对话框中使用儿童可拆卸/可固定对话框,您有什么建议吗?最好,你没有回答我的问题。没有理由将框架窗口创建为对话框的子窗口,没有任何好处
CFrameWndEx
可以做任何事情
CDialog
c