【问题标题】:Create multiple CDockablePanes onto an CDialog在 CDialog 上创建多个 CDockablePanes
【发布时间】:2016-08-16 21:07:53
【问题描述】:

我正在尝试与此处描述的文章完全相同: "C++ MFC Feature Pack --> Create multiple CDockablePanes onto an CDialog"

我按照他的程序进行操作,现在可以取消停靠并移动 CDockablePane,但停靠回位时也会发生同样的崩溃。在他自己的回答中,他说他自己创建了 dummywnd,因此 MFC 跳过了创建和对 GetTopLevelFrame() 的调用。这就是我感到困惑的地方,我该如何准确地创建 dummywnd?

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

提问和回答问题的人似乎多年不活跃,无法联系到。有人可以帮忙或有什么想法吗?

谢谢,


编辑:

我破坏了程序并完全按照另一位作者的描述进行了追溯。上面提到的dummy window其实是在afxdragframeimpl.cpp中:

void CMFCDragFrameImpl::MoveDragFrame(BOOL bForceMove)

创建地点:

m_pWndDummy = new CDummyDockablePane;

并调用:

m_pWndDummy->CreateEx(0, _T(""), AFXGetTopLevelFrame(m_pDraggedWnd), CRect(0, 0, 0, 0), FALSE, AFX_DUMMY_WND_ID, WS_CHILD);

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

基本上我有一个带有一些控件的 MFC 对话框 A,在这个对话框 A 中我需要一些可撕下的 tabsXYZ,并且我需要在每个可撕下的 tabsXYZ 中添加一些控件。所以这意味着每个可撕下的 tabsXYZ 实际上是一个子 dialogB。所以这就是我尝试在 dialogA 中使用 CDockablePanes(实际上是 CPaneDialog)的地方。

【问题讨论】:

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

标签: mfc cdialog dockable


【解决方案1】:
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()
};

你打开窗口如下:

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
{
    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(_T("MainFrame"))

【讨论】:

  • 非常感谢巴马克,这是一个非常详细的答案。我还没有机会尝试它,但看起来它可以很好地工作。最好的。
猜你喜欢
  • 2011-06-20
  • 1970-01-01
  • 1970-01-01
  • 2020-11-20
  • 2010-09-13
  • 1970-01-01
  • 2020-09-17
  • 1970-01-01
  • 2014-03-14
相关资源
最近更新 更多