zoukankan      html  css  js  c++  java
  • 浅谈SDI单文档多视切换方法

     

    VC编程 2010-12-04 23:20:29 阅读87 评论0   字号: 订阅

    在我们开发的工程中,经常要遇到单文档多视的开发,且常常伴有切分窗口的需求.这个切分,通常是静态切分的,比如说,客户窗口的左边是一个控件如outlook风格的抽屉控件,右边是一个视图.通过菜单命令,来改变右边视图.

    下面,我以一个例子来说明:

    新建一个单文档的工程.文档基类是CDocument

    1.    CmainFrame头文件中,加入成员变量CsplitterWnd m_splitWnd;

    CmainFrame cpp文件中,重载OnCreateClient函数

    / / #include ".\YouDoc.h"

    //#include ".\YourView1.h"

    //#include ".\YourView2.h"

    BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)

    {

        // TODO: Add your specialized code here and/or call the base class

        //return CFrameWnd::OnCreateClient(lpcs, pContext);

        if(!m_SplitWnd.CreateStatic(this,1,2))

        {

            TRACE("Create splitwnd failure\n");

            return -1;

        }

        //here, add your outlook control

    #if 1

        // m_XTOutBarCtlCmainFrame的成员变量,

        DWORD dwf = CGfxOutBarCtrl::fDragItems|CGfxOutBarCtrl::fEditGroups

            | CGfxOutBarCtrl::fEditItems|CGfxOutBarCtrl::fRemoveGroups

            | CGfxOutBarCtrl::fRemoveItems|CGfxOutBarCtrl::fAddGroups

            | CGfxOutBarCtrl::fAnimation;

    //注意,这是m_XTOutBarCtl的父窗口不是主窗口,也不是m_Splitwnd的右边的视,实际上右//边没有视图,它的父窗口是切分窗口本身.    if(!m_XTOutBarCtl.Create(WS_CHILD|WS_VISIBLE,CRect(),&m_SplitWnd,m_SplitWnd.IdFromRowCol(0, 0), dwf))

        {

            TRACE("Create splitwnd failure\n");

            return -1;

        }

        //init outbar ctrl

        ...

    #endif

    VERIFY(m_SplitWnd.CreateView(0,1,RUNTIME_CLASS(CyourView1),CSize(100, 100), pContext));

    //这句很得要,我们要得到活动的视.

        m_SplitWnd.SetActivePane(0,1);

        m_SplitWnd.SetColumnInfo(0,150,10);

        m_SplitWnd.RecalcLayout();    

        return 1;

    }

     

    2.通过classwizard,向工程中添加一个视类Cview2,在示例工程中,其基类为CformView

    在菜单中增加两个命令:testView1,testView2,ID分别为ID_VIEW_SWITCH1, ID_VIEW_SWITCH2

    及处理函数

    响映其消息:

    BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)

        //{{AFX_MSG_MAP(CMainFrame)

           // NOTE - the ClassWizard will add and remove mapping macros here.

           //    DO NOT EDIT what you see in these blocks of generated code !

        ON_WM_CREATE()

        //}}AFX_MSG_MAP

        ON_COMMAND(ID_VIEW_SWITCH1, OnViewSwitch1)

        ON_COMMAND(ID_VIEW_SWITCH2,OnViewSwitch2)

        //ON_COMMAND_RANGE(ID_VIEW_SWITCH1,ID_VIEW_SWITCH2, OnViewSwitch)

    END_MESSAGE_MAP()

     

       其消息处理为:

     void CMainFrame::OnViewSwitch1()

    {

        // TODO: Add your command handler code here

        CRuntimeClass *pNewViewClass = RUNTIME_CLASS(CyourView1);

        CView *pActiveView = GetActiveView();

        if(pActiveView->IsKindOf(pNewViewClass)) 

        {

               pNewViewClass = RUNTIME_CLASS(CyourView2);     

               judgeViewID(pNewViewClass);

        }

     

    }

    void CMainFrame::OnViewSwitch2()

    {

        // TODO: Add your command handler code here

        CRuntimeClass *pNewViewClass = RUNTIME_CLASS(CyourView2);

        CView *pActiveView = GetActiveView();

        if(pActiveView->IsKindOf(pNewViewClass)) 

        {

            pNewViewClass = RUNTIME_CLASS(CyourView1);     

            judgeViewID(pNewViewClass);

        }

    }

    judgeViewID(pNewViewClass)是处理切换视的函数,其实现为:

    UINT CMainFrame::judgeViewID(CRuntimeClass *pNewViewClass)

    {

     

        CView *pOldActiveView = (CView *)GetActiveView();

     

        if(pOldActiveView->IsKindOf(pNewViewClass))

        {

            return 1;

        }

        //ASSERT(pSplitter->IsChildPane(pOldActiveView,row,col));

        CRect viewRect;

        CDocument *pDoc = this->GetActiveDocument();

        //这个判断是非常重要的,我们要自已把是非删除文档置为FALSE,

        //否则,当我们切换成功后,当View在onDraw时,会得不到document,

        //会产生异常,导致失败!

        if(pDoc)

        {

            //when all views been destroy ,dont close document

            pDoc->m_bAutoDelete = FALSE;

        }

       

        pOldActiveView->GetWindowRect(&viewRect);

        //如果这里不destroywindow,当我们createview时,splitwnd会检测到其窗口存在,

        //而导致创建视失败.

        //就是这句CWnd *pwnd = m_SplitWnd.GetDlgItem(m_SplitWnd.IdFromRowCol(0, 1));

        //当创建视时,它先判断pwnd == NULL

    //而如果在前面不置文档的m_bAutoDelete为FALSE,当destroywondow()视时,文档发现自己//的视类没有了,会把自己关掉,导致其维护的m_viewList的头指针为非法值了,产生意想不//到的fata error.

        pOldActiveView->DestroyWindow();

        if(pDoc)

        {

            //还原其内核的参数值

            pDoc->m_bAutoDelete = true;

        }

        CCreateContext context;

        context.m_pCurrentDoc = pDoc;

        context.m_pNewViewClass = pNewViewClass;

        CWnd *pwnd = m_SplitWnd.GetDlgItem(m_SplitWnd.IdFromRowCol(0, 1));

        if(!m_SplitWnd.CreateView(0,1,pNewViewClass,viewRect.Size(),&context))

        {

            return 0;

        }

      

        m_SplitWnd.SetColumnInfo(0, 120, 10);

        //pSplitter->SetColumnInfo(1, , 10);

        CView *pNewView = (CView *)m_SplitWnd.GetPane(0,1);

        if(pNewView->IsKindOf(RUNTIME_CLASS(CETSOFTView)))

        {

            CDocument *pDoc = this->GetActiveDocument();

        }

        m_SplitWnd.GetParentFrame()->SetActiveView(pNewView);

        m_SplitWnd.RecalcLayout();

        return 1;

    }

  • 相关阅读:
    韦大仙--Katalon---一款好用的selenium自动化测试插件
    Python之路,Day3
    Python之路,Day2
    Python之路,Day1
    Python基础02 基本数据类型
    Python基础01 Hello World!
    韦大仙--LoadRunner压力测试:详细操作流程
    韦大仙--python对文件操作 2--写入与修改
    韦大仙--python对文件操作
    更新pip10后 ImportError: cannot import name ‘main'
  • 原文地址:https://www.cnblogs.com/cy163/p/1931316.html
Copyright © 2011-2022 走看看