当前位置导航:炫浪网>>网络学院>>编程开发>>C++教程>>Visual C++教程

用VC++实现应用程序窗口的任意分割

     我们在使用OutLook或者NetAnt等工具的时候,一般都会被其复杂的界面所吸引,在这些界面中窗口被分割为若干的区域,真正做到了窗口的任意分割。 那么我们自己如何创建类似的界面,也实现窗口的任意的分割呢?要解决这个问题,在Visual C++6.0编程中就需要使用到MFC提供的CSplitterWnd类。CSplitterWnd看上去像是一种特殊的框架窗口,每个窗口都被相同的或者不同的视图所填充。当窗口被切分后用户可以使用鼠标移动切分条来调整窗口的相对尺寸。虽然VC6.0支持从AppWizard中创建分割窗口,但是自动加入的分割条总是不能让我们满意,因此我们还是通过手工增加代码来熟悉这个类。本实例采用多模板模式,即实现了窗口的任意分割,又介绍了各个视图如何相互通信。
      一、实现方法

      Visual C++中MFC提供了CSplitterWnd类来实现窗口的分割,它的构造函数主要包括下面三个:

    BOOL Create(CWnd* pParentWnd,int nMaxRows,int nMaxCols,SIZE sizeMin,
    CCreateContext* pContext,DWORD dwStyle,UINT nID);

      该函数用来创建动态切分窗口,参数pParentWnd表示切分窗口的父框架窗口;参数nMaxRows,nMaxCols是创建切分窗口的最大列数和行数;sizeMin是窗格的最小尺寸;参数pContext 大多数情况下传给父窗口;nID是切分窗口的ID号。例如下面的代码将创建2x2的窗格。

    m_wndSplitter.Create(this,2,2,CSize(100,100),pContext);

      动态创建的分割窗口的窗格数目不能超过2x2,而且对于所有的窗格,都必须共享同一个视图,所受的限制也比较多,因此我们不将动态创建作为重点。我们的主要精力放在静态分割窗口的创建上。

    BOOL CreateStatic(CWnd* pParentWnd,int nRows,int nCols,DWORD dwStyle,UINT nID) ;

      该函数用来用来创建切静态分窗口,参数含义同上。

    BOOL CreateView (int row,int col,CruntimeClass* pViewClass,SIZE
    sizeinit,CcreateContext* pContext);

      此函数向静态切分的窗口的网格填充视图。在将视图于切分窗口联系在一起的时候必须先将切分窗口创建好。参数含义同上。与动态创建相比,静态创建的代码要简单许多,而且可以最多创建16x16的窗格。不同的窗格我们可以使用CreateView()函数来填充不同的视图。如果我们要创建类似CuteFtp程序的窗口分割,CuteFtp的分割情况如下:

    CCuteFTPView
    CView2 CView3
    CView4

      那么在创建之前我们必须先用AppWizard生成单文档CuteFTP,生成的视类为 CCuteFTPView。同时在增加三个视类或者从视类继承而来的派生类CView2,CView3 CView4,然后在CMainfrm.h中增加下面的代码:

    CSplitterWnd wndSplitter1;
    CSplitterWnd wndSplitter2;

      为了实现拆分窗口,需要重载CMainFrame::OnCreateClient()函数,具体代码如下:

    BOOL CMainFrame::OnCreateClient( LPCREATESTRUCT /*lpcs*/, CCreateContext* pContext)
    {
     //创建一个静态分栏窗口,分为三行一列
     if(m_wndSplitter1.CreateStatic(this,3,1)==NULL)
      return FALSE;
     //将CCuteFTPView连接到0行0列窗格上
     m_wndSplitter1.CreateView(0,0,RUNTIME_CLASS(CCuteFTPView),CSize(100,100), pContext);
     m_wndSplitter1.CreateView(2,0,RUNTIME_CLASS(CView4),CSize(100,100),pContext);
     //将CView4连接到2行0列
     if(m_wndSplitter2.CreateStatic(&m_wndSplitter,1,2,WS_CHILD|WS_VISIBLE, m_wndSplitter.IdFromRowCol(1, 0))==NULL)
      return FALSE; //将第1行0列再分开1行2列
     //将CView2类连接到第二个分栏对象的0行0列
     m_wndSplitter2.CreateView(0,0,RUNTIME_CLASS(CView2),CSize(400,300),pContext);
     //将CView3类连接到第二个分栏对象的0行1列
     m_wndSplitter2.CreateView(0,1,RUNTIME_CLASS(CView3),CSize(400,300),pContext);
     return TRUE;
    }

      在应用程序中拆分窗口后,还有一个重要的工作就是实现各个视图之间的数据通信,有两种方法解决这个问题,一是利用公用的文档;二是利用程序的主框架。为了说明问题,我们让CCuteFTPView、CView2通过文档来实现通信,CView3、CView4通过主框架来通信。对于第一种方法,由AppWizard生成的CCuteFTPView是与文档相连的,同时我们也让CView2与文档相连,因此我们需要修改CCuteFTPApp的InitInstance()函数,增加下面的代码:

    AddDocTemplate (new CMultiDocTemplate(IDR_VIEW2TYPE, RUNTIME_CLASS(CMainDoc),
    RUNTIME_CLASS(CMDIChildWnd), RUNTIME_CLASS(CView2)));

      然后我们重载 CDocument::OnOpenDocument()函数;在该函数中定义如下变量:CCuteFTPView* pCuteFTPView、CView2* pView2、POSITION pos,并添加如下代码:

    pos=GetFirstViewPosition( )
    while(pos!=NULL)
    {
     pView=GetNextView(pos);
     if(pView->IsKindOf(RUNTIME_CLASS(CCuteFTPView))==NULL)
      pCuteFTPView=(CCuteFTPView*)pView;
     else
      pView2=(CView2*)pView;
    }

      这样我们在文档类中就获的了跟它相连的所有的视图的指针。如果需要在 CCuteFTPView中调用CView2中的一个方法DoIt()则代码如下:

    CCuteFTPDoc* pDoc=GetDocument();
    CView2* pView2=pDoc->pView2;
    pView3.DoIt();

      CView3和CView4都是不与文档相关联的。如何实现他们之间的通信呢。 正如我们在上面所说的那样,由于在主框架中我们可以访问任意的视图,因此我们的主要任务还是在程序中获得主框架的指针。例如下面的代码实现在CView3中访问CView4中的方法DoIt()。

    CMainFrame* MainFrame=(CMainFrame*)this->GetParent()->GetParent();
    CView4* View4=(CView4*)MainFrame->m_wndSplitter1.GetPane(2,0);
    View4->DoIt();


      为了更好地加深读者朋友对上述内容的理解,本实例通过灵活运用上述拆分窗口的方法,在多文档视图模板的基础上,实现了窗口的任意拆分,例如当用户在左边视图InPutView中输入字符串、选择颜色后,能立即反映到右边的CCorlorView、CtextView窗口中。

 

共4页 首页 上一页 1 2 3 4 下一页 尾页 跳转到
相关内容
赞助商链接