Создать несколько CDockablePanes на CDialog
Я пытаюсь сделать то же самое, что и статья, описанная здесь: " C++ MFC Feature Pack -> Создание нескольких CDockablePanes на CDialog"
Я следовал его процедуре и теперь могу отстыковывать и перемещать CDockablePane, но получаю тот же сбой, когда закрепляю его обратно. В своем собственном ответе он сказал, что сам создал dummywnd, поэтому MFC пропустил создание и вызов GetTopLevelFrame(). И это то, где я запутался, как мне создать dummywnd точно?
Мой второй вопрос: как я могу обмениваться данными между CMyFrame и CDialog?
Человек, который задал вопрос и ответил на него, кажется, неактивен годами и недоступен. Может ли кто-нибудь помочь или есть какие-либо идеи?
Спасибо,
Редактировать:
Я сломал программу и проследил в точности так, как описал другой автор. Упомянутое выше фиктивное окно на самом деле находится в файле 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 как дочернее окно в моем диалоговом окне, а затем добавить дочерний CDockablePane в этот CFrameWndEx.
По сути, у меня есть диалоговое окно MFCA с некоторыми элементами управления, и в этом диалоговом окне A мне нужны отрывные вкладки XYZ, и мне нужно добавить несколько элементов управления в каждую отрывную вкладку XYZ. Таким образом, это означает, что каждая отрывная вкладка XYZ на самом деле является одним дочерним диалогом B. Так что это приходит к тому, что я пытаюсь использовать CDockablePanes (на самом деле CPaneDialog) в диалоге A.
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"));
Затем измените его обратно на SetRegistryBase(_T("MainFrame"))
когда вы выходите CMyFrame