MFC中的view, document 和Frame是通过DocTemplate联系起来的, 但是如果我用splitter来进行静态窗口分割, 形成三个View (CMyViewA, CMyViewB, CMyViewC), 如何把这三个view都跟document关联起来呢.一般程序都是这么写的:
CSingleDocTemplate* pDocTemplate;
pDocTemplate = new CSingleDocTemplate(
IDR_MAINFRAME,
RUNTIME_CLASS(CGraphDoc),
RUNTIME_CLASS(CMainFrame), // main SDI frame window
RUNTIME_CLASS(CMyViewA));
if (!pDocTemplate)
return FALSE;
AddDocTemplate(pDocTemplate);但上面的代码如何使Document和CMyViewB, CMyViewC 关联在一起呢. 我查找MFC的源代码也没发现他们之间的关系.
请大家解释一下,谢谢了
CSingleDocTemplate* pDocTemplate;
pDocTemplate = new CSingleDocTemplate(
IDR_MAINFRAME,
RUNTIME_CLASS(CGraphDoc),
RUNTIME_CLASS(CMainFrame), // main SDI frame window
RUNTIME_CLASS(CMyViewA));
if (!pDocTemplate)
return FALSE;
AddDocTemplate(pDocTemplate);但上面的代码如何使Document和CMyViewB, CMyViewC 关联在一起呢. 我查找MFC的源代码也没发现他们之间的关系.
请大家解释一下,谢谢了
解决方案 »
- 树控制自绘里使用虚线会造成树控件出现闪烁吧?
- 【警告:此ID有行骗的嫌疑! 注意若QQ为:55840 若手机联络则为13817328000】 高分稿酬] 寻 C/C++/VC 虚拟 IP 技术
- 在窗体上放了一个Date Time Picker控件,给控件关联了一个COleDateTime变量,赋初值的时候会assert失败,为什么?
- VC6中如何删除一个自定义的类
- 知道一个窗口的位置,怎样获得客户区左上角的坐标?
- 超级简单问题:如何清除Picture中的图片?
- 有个恶毒的家伙在我的帖子里骂街,怎么处理,出个主意!
- 高分求助snmp例程!
- 合作写模块
- 没见过!
- 【如何在其他类中 更新主窗口的edit control内容】
- 栈中的高地址和低地址
和DocTemplate无关。多搞doctemplate可以让你在新建时,选择用那个模版。
pDocTemplate = new CSingleDocTemplate(
IDR_MAINFRAME,
RUNTIME_CLASS(CGraphDoc),
RUNTIME_CLASS(CMainFrame), // main SDI frame window
RUNTIME_CLASS(CMyViewA));
pDocTemplate2 = new CSingleDocTemplate(
IDR_MAINFRAME,
RUNTIME_CLASS(CGraphDoc),
RUNTIME_CLASS(CMainFrame), // main SDI frame window
RUNTIME_CLASS(CMyViewB));
pDocTemplate3 = new CSingleDocTemplate(
IDR_MAINFRAME,
RUNTIME_CLASS(CGraphDoc),
RUNTIME_CLASS(CMainFrame), // main SDI frame window
RUNTIME_CLASS(CMyViewC));
m_wndSplitter.CreateStatic(this, 1, 2);
把框架分成1行2列的分裂窗口。再m_wndSplitter.CreateView(0, 0, pContext->m_pNewViewClass, CSize(xxx,yyy), pContext)
创建0行0列的View,pContext->m_pNewViewClass是你原来的View,CSize指定大小。然后m_wndSplitter.CreateView(0, 1,RUNTIME_CLASS(CMyView2), CSize(xxx,yyy), pContext)
用新View创建0行1列的View。
如果一定要是SDI,你可以通过主框架窗口得到doc类,得到数据以后传递到你指定的view中。
这样看来, 对于用splitter来拆分的窗口来说, CSingleDocTemplate构造函数中的最后一个RUNTIME_CLASS参数并没有什么意义,是不是这样? 大家再讨论一下 。
rect, this, IdFromRowCol(row, col), pContext)) 这句调用确实是将view和doc关联起来了BOOL CSplitterWnd::CreateView(int row, int col,
CRuntimeClass* pViewClass, SIZE sizeInit, CCreateContext* pContext)
{
#ifdef _DEBUG
ASSERT_VALID(this);
ASSERT(row >= 0 && row < m_nRows);
ASSERT(col >= 0 && col < m_nCols);
ASSERT(pViewClass != NULL);
ASSERT(pViewClass->IsDerivedFrom(RUNTIME_CLASS(CWnd)));
ASSERT(AfxIsValidAddress(pViewClass, sizeof(CRuntimeClass), FALSE)); if (GetDlgItem(IdFromRowCol(row, col)) != NULL)
{
TRACE2("Error: CreateView - pane already exists for row %d, col %d.\n",
row, col);
ASSERT(FALSE);
return FALSE;
}
#endif // set the initial size for that pane
m_pColInfo[col].nIdealSize = sizeInit.cx;
m_pRowInfo[row].nIdealSize = sizeInit.cy; BOOL bSendInitialUpdate = FALSE; CCreateContext contextT;
if (pContext == NULL)
{
// if no context specified, generate one from the currently selected
// client if possible
CView* pOldView = (CView*)GetActivePane();
if (pOldView != NULL && pOldView->IsKindOf(RUNTIME_CLASS(CView)))
{
// set info about last pane
ASSERT(contextT.m_pCurrentFrame == NULL);
contextT.m_pLastView = pOldView;
contextT.m_pCurrentDoc = pOldView->GetDocument();
if (contextT.m_pCurrentDoc != NULL)
contextT.m_pNewDocTemplate =
contextT.m_pCurrentDoc->GetDocTemplate();
}
pContext = &contextT;
bSendInitialUpdate = TRUE;
} CWnd* pWnd;
TRY
{
pWnd = (CWnd*)pViewClass->CreateObject();
if (pWnd == NULL)
AfxThrowMemoryException();
}
CATCH_ALL(e)
{
TRACE0("Out of memory creating a splitter pane.\n");
// Note: DELETE_EXCEPTION(e) not required
return FALSE;
}
END_CATCH_ALL ASSERT_KINDOF(CWnd, pWnd);
ASSERT(pWnd->m_hWnd == NULL); // not yet created DWORD dwStyle = AFX_WS_DEFAULT_VIEW;
if (afxData.bWin4)
dwStyle &= ~WS_BORDER; // Create with the right size (wrong position)
CRect rect(CPoint(0,0), sizeInit);
if (!pWnd->Create(NULL, NULL, dwStyle,
rect, this, IdFromRowCol(row, col), pContext)) // 这里确实关联起来了
{
TRACE0("Warning: couldn't create client pane for splitter.\n");
// pWnd will be cleaned up by PostNcDestroy
return FALSE;
}
ASSERT((int)_AfxGetDlgCtrlID(pWnd->m_hWnd) == IdFromRowCol(row, col)); // send initial notification message
if (bSendInitialUpdate)
pWnd->SendMessage(WM_INITIALUPDATE); return TRUE;
}
网上有个更彻底的解释,我在这里贴出来吧, 供有同样疑问的tx参考:SDI means "Single Document Interface", it restricts you to only one single document at a time but not in the number of views you can open for this document.The probably most common approach to open multiple views in an SDI application are Splitter Windows.You add one view to the CSingleDocTemplate (it doesn't matter which one)pDocTemplate = new CSingleDocTemplate(
IDR_MYRESOURCEID,
RUNTIME_CLASS(CMyDoc),
RUNTIME_CLASS(CMyFrameWnd),
RUNTIME_CLASS(CMyListView));Your frame window gets an instance of a CSplitterWnd m_wndSplitter and you overload the OnCreateClient virtual function:BOOL CMyFrameWnd::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)
{
VERIFY(m_wndSplitter.CreateStatic(this,1,2)); // one row / two columns VERIFY(m_wndSplitter.CreateView(0,0,RUNTIME_CLASS(CMyListView),
CSize(300,300),pContext));
VERIFY(m_wndSplitter.CreateView(0,1,RUNTIME_CLASS(CMyEditView),
CSize(300,300),pContext)); return TRUE;
}This example creates a splitter window with one row and two columns. On the left side in the splitter is a view of type CMyListView and on the right side is a view of type CMyEditView.You can even nest multiple splitter windows one in each other to create arbitrary complex view collections in the frame window.Here is a small tutorial which shows how to work with splitter windows in a SDI application:http://www.codeproject.com/KB/splitter/splitterwindowtutorial.aspxEditWiring up of the views you add to the splitter with the document does MFC internally: CCreateContext* pContext which is passed into OnCreateClient contains a reference m_pCurrentDoc to the current document (the Framewindow knows about this document). MFC uses this in CView::OnCreate (ViewCore.cpp) to add the View to the Document: m_pCurrentDoc->AddView(this) and to set the document pointer m_pDocument in the View.Therefore subsequent calls of UpdateAllViews of your document will take care of both views.