应用程序类型:MFC SDI
环境:XP + SP2/VS2005
一:常规方法
重写CMainFrame::OnCreateClient
BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)
{
CRect rcClient;
GetClientRect( &rcClient );
CSize size( rcClient.Width() / 2, rcClient.Height() / 2 );
// 创建静态拆分窗口
m_wndSplitter.CreateStatic( this, 1, 2 );
m_wndSplitter.CreateView( 0, 0, RUNTIME_CLASS( CEditView ), size, pContext );
m_wndSplitter.CreateView( 0, 1, RUNTIME_CLASS( CEditView ), size, pContext );
// 必须返回TRUE
return TRUE;
return CFrameWnd::OnCreateClient(lpcs, pContext);
}
如果没有重写此函数,则MFC框架将调用
return CFrameWnd::OnCreateClient(lpcs, pContext);
这导致应用程序的主视图类将在此调用中,通过DECLARE_DYNCREATE/IMPLEMENT_DYNCREATE宏设置的参数信息,调用CreateObject以动态创建。
由于上面的函数必须返回TRUE(如果仍返回框架产生的代码,应用程序视图类会被创建,而你自己分割的视图将不会再被看到。),这将不会引起应用程序视图类的动态创建,所以不要指望主视图类的构造函数会被调用,当然你熟悉的OnInitialUpdate也不会再调用。
二:怪导的需求
今天突然需要既保存拆分视图,又要能使用Doc/View结构,这该如何呢?
方法如下:重写主视图类的Create方法。
框架默认产生的过程如下:
BOOL CSplitView::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext)
{
return CView::Create(lpszClassName, lpszWindowName, dwStyle, rect, pParentWnd, nID, pContext);
}
我们稍做修改即可:
BOOL CSplitView::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext)
{
BOOL bRes = CView::Create(lpszClassName, lpszWindowName, dwStyle, rect, pParentWnd, nID, pContext);
int nWidth = rect.right - rect.left;
int nHeihgt = rect.bottom - rect.top;
CSize size( nWidth / 2,nHeihgt / 2 );
// 创建静态拆分窗口
m_wndSplitter.CreateStatic( this, 2, 2 );
m_wndSplitter.ModifyStyle( WS_BORDER, 0 );
m_wndSplitter.ModifyStyleEx( WS_EX_OVERLAPPEDWINDOW, 0 );
m_wndSplitter.CreateView( 0, 0, RUNTIME_CLASS( CEditView ), size, pContext );
m_wndSplitter.CreateView( 0, 1, RUNTIME_CLASS( CEditView ), size, pContext );
m_wndSplitter.CreateView( 1, 0, RUNTIME_CLASS( CEditView ), size, pContext );
m_wndSplitter.CreateView( 1, 1, RUNTIME_CLASS( CEditView ), size, pContext );
return bRes;
}
怎么样,成功了吧!
不要忘了映射该类WM_SIZE消息,以将窗口铺满视图区。
void CSplitView::OnSize(UINT nType, int cx, int cy)
{
CView::OnSize(nType, cx, cy);
if ( GetSafeHwnd() != NULL && ::IsWindow( m_wndSplitter.m_hWnd ) )
{
m_wndSplitter.MoveWindow( 0, 0, cx, cy );
}
}