资源描述
【转】MFC分割窗体(SplitterWindows)2011-03-2018:32转载自651405842最终编辑drunkdreamMFC分割窗体(SplitterWindows)vrefereneeMSDNMicrosoftFoundationClassLibraryandTemplatesTNO029文档描述MFC中的CSplitterWnd类,该类用来支持窗体的分割和管理分割后每一个子窗格(pane)的大小1分割窗体风格(SplitterStyles)CSplitterWnd类支持2种不同风格的分割窗口1.1 静态分割(staticsplitter)分割的窗格(pane)在分割窗体(splitterwindow;)创建时创建,而且顺序,数量不会变化,分割控制条(Spli控制每个窗格的大小.通常不同的窗格是不同的视图类(viewclass);例如VisualC+graphics和Windows文件管理器就是这个风格的分割窗体;该风格分割窗体不会用到分割格(splitterbox)1.2 动态分割(dynamicsplitter)当用户控制视图的分割或停止分割,附加窗格会被创建或销毁;这种动态分割开始于一个单独的视图,分割格box)用于初始化分割;当一个视图可以在2个方向上被分割时,会有3个新的视图被创建并显示为3个新的窗格;被激活(active)时,分割格(splitterbox)会如同分割控制条(splitterbar)一样在各个窗格间被绘制;当用户除加窗格会被销毁,只有原来的视图(分割时位于0行0列位置的窗格)会被保留直到分割窗体本身被销毁;例如MicrosoftExcel和MicrosoftWord都是这种风格的分割窗体;当创建任意一种风格的分割窗体时,必须给定分割窗体的最大的行列数;静态风格的分割窗体,每个窗格必须被创建CSplitterWnd:CreateView;动态风格的分割窗体第一个窗格会在CSplitterWnd对象创建被自动创建静态风格的分割窗体的最大行列数为16x16动态风格的分割窗体的最大行列数为2x2推荐的分割方式为:2 分割窗体的例子(SplitterSamples)很多MFC的列子程序都直接或间接的用到了分割窗体MFC入门程序Scrippie程序的第4部中就用到动态切分MFC标准示例中ViewEx展示静态使用切分窗体的方法,包括如何在一个切分窗体中包含另一个切分窗体3 分割窗体中使用的术语(TerminoiogyUsedByImpiement)CspiitterWnd(分割窗体):负责提供窗格切分空间和滚动条(同行(row)共享竖直滚动条(VerticalScrollBar),同列(column)共享水平滚(HorizontaiScroiiBar);同时行列的下标从0,0开始,言即第一个窗格为第0行第0列的窗格Pane(窗格)CSplitterWnd管理的应用程序显示数据的窗体,一般而言窗格是一个视图的派生类对象,实际上窗格可以是任中派生的对象;SplitterBar(分割控制条)在窗格行列间的控件,用于控制行列上窗格的大小SpliiterBox(分割格)动态分割窗体位于竖直滚动条最上的或水平滚动条最左位置的按键,用于创建新的分割窗格SplitterIntersection(分割交叉点)竖直或水平分割控制条的交叉点,可用于同步控制水平,竖直窗格的大小共享滚动条(SharedScrollBars)CSplitterWnd支持共享滚动条,滚动条是CSplitterWnd的子窗体并且在分割窗体中为不同的窗格所共享;如在创建1X2CSplitterWnd时声明了WS_VSCRO分割那么2个窗格共享的竖直滚动条会创建如:Apane00pane01|v当移动滚动条时,WM_VSCRO消息会发送到2个窗格中同样,同列的窗格可以共享水平滚动条、,I、+:注意在分割窗体中共享滚动条是非常有用的,如果是2种不同的视图使用共享滚动条那么就必须要协调滚动位置和所有视图的派生类可以通过CWnc中的操作ScrollBar的方法来控制共享滚动条,但是一些非视图派生类,没有使控件的类或通过标准Window的实现方法的类如CEditView将不适合于共享滚动条4 最小大小(Minimumsize)在分割窗体中每一行都有最小高度限制,每一列都有最小宽度限制,这2个最小值用于控制窗格显示数据最小静态分割窗体的最小大小为0,0;动态分割窗体的最小大小可以在CSplitterWnd:创建时设定;这些值可以同过SetColumnlnfo和SetRowInfo来改变;5 未公布的接口函数(protectedinterface)以下将讨论一些未公布的CSplitterWnd的技术细节以便高级用户来定制CSplitterWnd;这些API没有官方文档公布同时在将来版本的MFC中极可能会被改变:6.1分割控制条(splitterbar)分割格(box)和分割位置跟踪(tracker)的绘制enumESplitTypesplitBox,splitBar,splitIntersection,splitBorder;virtualvoidOnDrawSplitESplitTypenType,constCRect&rect);virtualvoidOnlnvertTracker(constCRect&rect);这些虚函数可以图形表现的分割窗体6.2创建视图和控件virtualBOOLCreateScrollBarCtrl(DWORDdwStyle,UINTnID);默认行为时创建滚动条,但是可以重载用于建新控件6.3动态切分窗体virtualvoidDeleteView(introw,intcol);virtualBOOLSplitRow(intcyBefore);virtualBOOLSplicxBefore);virtualvoidDeleteRow(introw);virtualvoidDeleteColumn(introw);用于实现动态分割窗体的逻体拥有风格SPLS_DYNAMIC_SPL时)Trackback:VC设计分割视图通用创建框架目前基于分割视图的应用开发十分流行,分割视图技术是在同一个框架窗口下同时显示多个视图的一项技术。可以在较短时间内给用户更多的信息量,从而使得用户界面更加的友好,增强了软件的可操作性。本文提出一个分创建框架。1分割视图创建框架分割视图的创建大体上分为两个步骤:其一是创建分割窗体;然后就是处理鼠标和键盘等消息。1)创建分割窗体MFC提供分割窗体类CsplitterWnd,它提供了很多对于分割窗体操作的成员函数,每一个分割窗体都是一个CsplitterWnd的对象。本文提出的框架由于需要对定制的分割窗体进行扩充处理,所以首先从CsplitterWnd继承一个子类CFixSplitterWnd,然后每个分割窗体是一个CfixSplitterWnd的对象,这样以后只需要对CfixSplitterWnd进行改写后就可以增强分割窗体的功能。(后面将提出这种改写)创建分割窗体最重要的函数是主框架类的OnCreateClient函数,它将在主框架创建的时候调用,本文将创建的分割窗体:個抱救,團片转存失败图1/成员变量声明CFixSplitterWndm_wndSplitterH;/用于横向切割CFixSplitterWndm_wndSplitterV;/用于纵向切割BOOLm_bCreateSplitter;/分割窗体的实现BOOLCMainFrame:OnCreateClient(LPCREATESTRCTlpcs,CCreateContext*pContext)/对整个主框架进行混合分割视图BOOLbResult=m_wndSplitterV.CreateStatic(this,1,2);ASSERT(bResult);mwndSplitterH.CreateStatic(&mwndSplitterV,4,1,WSCHILD|WS_VISIBLE,m_wndSplitterV.ldFromRowCol(0,1);/创建各自子窗片的对应的视图m_wndSplitterV.CreateView(0,0,RUNTIME_CLASS(CSceneView),CSize(600,600),pContext);m_wndSplitterH.CreateView(0,0,RUNTIME_CLASS(CPitchView),CSize(100,100),pContext);m_wndSplitterH.CreateView(1,0,RUNTIME_CLASS(CYawView),CSize(100,100),pContext);m_wndSplitterH.CreateView(2,0,RUNTIME_CLASS(CRollView),CSize(100,100),pContext);m_wndSplitterH.CreateView(3,0,RUNTIME_CLASS(CControlView),CSize(100,100),pContext);/设置窗格的初始化的大小m_wndSplitterV.SetRowlnfo(0,IDEAI_RAWHEIGHT,0);m_bCreateSplitter=TRUE;/激活seeneview使得其可以接受命令消息m_wndSplitterV.SetActivePane(0,0,NULL);returnbResult;/主框架窗体大小发生变化,调节相应的窗体大小voidCMainFrame:OnSize(UINTnType,intex,intcy)CMDIFrameWnd:OnSize(nType,cx,cy);CRectrect;GetClientRect(rect);if(m_bCreateSplitter)m_wndSplitterV.SetColumnlnfo(0,rect.Width()*3/4,10);m_wndSplitterV.SetColumnlnfo(1,rect.Width()*1/4,10);m_wndSplitterH.SetRowlnfo(0,rect.Height()/6,10);m_wndSplitterH.SetRowlnfo(1,rect.Height()/6,10);m_wndSplitterH.SetRowInfo(2,rect.Height()/6,10);m_wndSplitterH.SetRowInfo(3,rect.Height()/2,10);m_wndSplitterV.RecalcLayout();m_wndSplitterH.RecalcLayout();注意m_wndSplitterH.CreateView中的第二个参数,这个参数将分割窗体和相应的视图类相对应。通过上述的程序代码即可创建图1所示的分割窗体,那么由于这里每个分割窗体都是一个CfixSplitterW可以通过改写CfixSplitterWnd类的虚函数或消息处理函数来完成自己特定的应用实现。(注意,如果需要对定制分割窗体,一定要派生自己的分割窗体类而不能是MFC勺CsplitterWnd类)这里我们需要分割窗体不能随鼠标拖小,即所有窗格的大小都是一定的,不能在运行时刻改变。所以必须在CfixSplitterWnd类的实现中加入如下代码voidCFixSplitterWnd:OnMouseMove(UINTnFlags,CPointpoint)CWnd:OnMouseMove(nFlags,point);/防止鼠标出现拖动状鼠标会在窗体边界出现拖动状/CSplitterWnd:OnMouseMove(nFlags,point);/至此,分割窗体已经创建完毕,下面需要在分割窗体里处理消息。2)分割窗体处理消息在分割窗体里处理消息和一般的文档视图模型处理消息大致一样,但它也有其特殊之处于各个分割窗体已经与具体的视图类相联系了,所以在需要处理各个分割窗体中的消息时,可以直接到相应的视图类另外,多视图之间的切换会导致目标焦点之间的变更,这样会影响菜单中与视图有关的命令的执行。比如在图1中体中,有一个“开始”命令必须是焦点在CsceneView视图上时才能执行,否则就应该让该命令不能执行(即该菜单则实现时可以首先对鼠标进行点击测试,判断是否在CsceneView视图范围内,如果是的话就允许执行,否则就不2.结论通过本文提出的分割视图创建框架,可以满足对视图进行复杂控制的需求,希望本文可以给大家一个启发,从为完美的分割视图应用程序标准方式,视图获取数据,通知文档处理文档处理完成,通知所有的视图更新/视图收到数据,传递给文档进行修改voidCOneView:SetData(inti)GetDocument()-SetData(i);/文档接受视图的修改请求,完成成通知所有的视图更新voidCXXXDoc:SetData(inti)mData=i;UpdateAIIViews(NULL);/文档通过这个函数返回给视图数据intCXXXDoc:GetData()returnmData;/视图收到文档的更新通知,更新显示voidCOneView:OnUpdate(.)/重绘客户区Invalidate();/引起OnDraw()的调用voidCOneView:OnDraw(CDC*pDC)CXXXDoc*pDoc=GetDocument();CStringstr;str.Format(i=%d,pDoc-GetData();pDC-TextOut(0,0,str);/另一个视图也会收到通知(所有与文档关联的视图都会收到)voidCOtherView:OnUpdate(.)/这个更新控件(假设是从CFormView派生的,m_iData关联在一个EDIT控件上)m_iData=GetDocument()-GetData();UpdateData(FALSE);
展开阅读全文