今天想分割一下窗口,没有用 Doc/View 结构~ 想用CSplitterWnd 分割出一个 继承自 CTreeCtrl的窗口和一个继承自 CWnd 的窗口。
在 CSpliterWnd 的父窗口的 OnCreate 中调用
int CChildView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
// 创建拆分器窗口
if (!m_wndSplitter.CreateStatic(this, 1, 2))
return -1;
if (!m_wndSplitter.CreateView(0, 0, RUNTIME_CLASS(CHotTreeCtrl), CSize(200, 200), NULL) ||
!m_wndSplitter.CreateView(0, 1, RUNTIME_CLASS(CHotVtPain), CSize(100, 100), NULL))
{
DWORD nRet = GetLastError();
m_wndSplitter.DestroyWindow();
return -1;
}
return 0;
}
编译成功。可是运行时创建出来的Pane(0,0)不是 CTreeCtrl ,而是普通的CWnd~~~,晕死,也许是对MFC了解不够,于是后来就查了查CSplitterWnd::CreateView这个成员函数的代码:
/////////////////////////////////////////////////////////////////////////////
// CSplitterWnd default creation of parts
// You must create ALL panes unless DYNAMIC_SPLIT is defined!
// Usually the splitter window is invisible when creating a pane
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)
{
TRACE(traceAppMsg, 0, "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();//这里是动态 new 一个 你传进来的 窗口类的实例!!!
if (pWnd == NULL)
AfxThrowMemoryException();
}
CATCH_ALL(e)
{
TRACE(traceAppMsg, 0, "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 & ~WS_BORDER;
// Create with the right size (wrong position)
CRect rect(CPoint(0,0), sizeInit);
//值得注意的是这里,它实际上调用的是 CWnd的 Create来创建普通窗口!!而不是掉用的我们继承的CTreeCtrl 的 CHotTreeCtrl 的Create来创建 “SysTreeView“ 类型的窗口!!!所以就没有办法在 pane(0,0)中创建出 树型控件了!!!!可是人家 MFC 的 Doc/view 结构可以正常啊~~ 于是还是要查MFC源代码!!!
if (!pWnd->Create(NULL, NULL, dwStyle,
rect, this, IdFromRowCol(row, col), pContext))
{
TRACE(traceAppMsg, 0, "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;
}
上面提到还是从MFC 源代码入手于是就找 CTreeView的代码!
//CTreeView 的构造函数如下!其中:WC_TREEVIEW 就是字符串“SysTreeView32”
_AFXCVIEW_INLINE CTreeView::CTreeView() : CCtrlView(WC_TREEVIEW,
AFX_WS_DEFAULT_VIEW)
{ }
好!我们继续找 CCtrlView 的代码!-_-
下面的CCtrlView的构造函数,实际上把 “SysTreeView32” 传给了 m_strClass,然后我们注意 CtreeView::PreCreateWindow 成员函数中 它又: cs.lpszClass = m_strClass,到这里就真象大白了,原来 MFC 利用 CSplitterWnd 是用 窗口的 PreCreateWindow 来改变窗口 注册类的!!!
CCtrlView::CCtrlView(LPCTSTR lpszClass, DWORD dwStyle)
{
m_strClass = lpszClass;
m_dwDefaultStyle = dwStyle;
}
BOOL CCtrlView::PreCreateWindow(CREATESTRUCT& cs)
{
ASSERT(cs.lpszClass == NULL);
cs.lpszClass = m_strClass;
// initialize common controls
VERIFY(AfxDeferRegisterClass(AFX_WNDCOMMCTLS_REG));
AfxDeferRegisterClass(AFX_WNDCOMMCTLSNEW_REG);
// map default CView style to default style
// WS_BORDER is insignificant
if ((cs.style | WS_BORDER) == AFX_WS_DEFAULT_VIEW)
cs.style = m_dwDefaultStyle & (cs.style | ~WS_BORDER);
return CView::PreCreateWindow(cs);
}
于是我们重载了 CHotTreeCtrl 的 PreCreateWindow 函数!
BOOL CHotTreeCtrl::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: 在此添加专用代码和/或调用基类
cs.lpszClass = WC_TREEVIEW;
cs.style |= TVS_SHOWSELALWAYS | TVS_SINGLEEXPAND;// | TVS_HASLINES | TVS_HASBUTTONS | TVS_LINESATROOT;
return CTreeCtrl::PreCreateWindow(cs);
}
OK~~~ TreeCtrl 成功创建了!!!! MFC~~ 想说爱你不容易!
浙公网安备 33010602011771号