打破常规创建拆分窗口的方法

来源:互联网 发布:linux 内网 代理上网 编辑:程序博客网 时间:2024/06/18 15:12

应用程序类型: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 );

    }

}