大学IT网 - 最懂大学生的IT学习网站! QQ资料交流群:367606806
当前位置:大学IT网 > C++技巧 > 动态切换采用 CSplitterWnd 静态划分的视图布局(

动态切换采用 CSplitterWnd 静态划分的视图布局((2)

关键词:视图静态划分布局切换  阅读(2095) 赞(17)

[摘要]本文是对动态切换采用 CSplitterWnd 静态划分的视图布局(MFC)的讲解,与大家分享。

代码如下(红色部分为新增):

1)在MainFrame.h中:

     CSplitterWnd m_wndSliter;
     CSplitterWnd m_wndSliterL; // 新增加一个拆分器
     CSplitterWnd m_wndSliterR;

2)OnCreateClient实现:

 BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)
 {
     // TODO: 在此添加专用代码和/或调用基类
 
     CRect rect;
     GetClientRect(&rect);
 
     m_wndSliter.CreateStatic(this, 1, 2);
     m_wndSliter.CreateView(0,0, RUNTIME_CLASS(CViewFrom), CSize(180, rect.Height()), pContext);
 
     m_wndSliterR.CreateStatic(&m_wndSliter, 2, 1, WS_CHILD|WS_VISIBLE, m_wndSliter.IdFromRowCol(0, 1));
     m_wndSliterR.CreateView(0,0, RUNTIME_CLASS(CViewEdit), CSize(rect.Width()-180, 100), pContext);
     m_wndSliterR.CreateView(1,0, RUNTIME_CLASS(CViewList), CSize(rect.Width()-180, rect.Height()-100), pContext);
 
     m_wndSliterL.CreateStatic(&m_wndSliter, 2, 1, WS_CHILD|WS_VISIBLE, m_wndSliter.IdFromRowCol(0, 0));
     m_wndSliterL.ShowWindow(SW_HIDE);
 
     return TRUE;
     //return CFrameWnd::OnCreateClient(lpcs, pContext);
 }

初始化新增加的拆分器,但是不给它设置视图,并且将其隐藏(本处分开两行写,实际可简化代码一步到位)。 隐藏是很重要的,拆分器划分布局后,如果不会为其创建视图,会导致应用程序运行失败。

即在软件首次创建视图布局的时候,就采用 m_wndSliterL 将左边一列划分为两行,但是又不给它设置视图。而是将左边的视图直接设置在了 m_wndSliter 这个顶层划分中, 并且,非常重要的,要将 m_wndSliterL 隐藏。

上述两步完成后,编译运行,效果和没有修改前一样(如图1)。

下面,我们来添加动态来回切换视图的代码:

1)在CMainFrame.h中添加一个标记,以及一个方法申明:

 //...   
 bool _isCommomViewStyle;
 
 //...
 void SwitchViewStyle();


2)在CMainFrame的构造函数函数中将_isCommomViewStyle标记初始化为true,即默认状态。

3)添加SwitchViewStyle方法的实现,如下所示:

 // 切换视图
 void CMainFrame::SwitchViewStyle()
 {
     if (_isCommomViewStyle)
     {
         CWnd* viewLeft = m_wndSliter.GetPane(0,0);
         CWnd* viewTop = m_wndSliterR.GetPane(0,0);
         CWnd* viewBot = m_wndSliterR.GetPane(1,0);
 
         viewLeft->SetParent(&m_wndSliterL);
         viewTop->SetParent(&m_wndSliterL);
         viewBot->SetParent(&m_wndSliter);
 
         ::SetWindowLong(viewLeft->m_hWnd, GWL_ID, m_wndSliterL.IdFromRowCol(0, 0));
         ::SetWindowLong(viewTop->m_hWnd, GWL_ID, m_wndSliterL.IdFromRowCol(1, 0));
         ::SetWindowLong(viewBot->m_hWnd, GWL_ID, m_wndSliter.IdFromRowCol(0, 1));
         
         m_wndSliterL.SetRowInfo(1, 200, 0);
         m_wndSliterL.ShowWindow(SW_SHOW);
         m_wndSliterR.ShowWindow(SW_HIDE);
 
         m_wndSliterL.RecalcLayout();
         m_wndSliter.RecalcLayout();
         
         _isCommomViewStyle=false;
     }
     else
     {
         CWnd* viewLeft = m_wndSliterL.GetPane(0,0);
         CWnd* viewTop = m_wndSliterL.GetPane(1,0);
         CWnd* viewBot = m_wndSliter.GetPane(0,1);
 
         viewLeft->SetParent(&m_wndSliter);
         viewTop->SetParent(&m_wndSliterR);
         viewBot->SetParent(&m_wndSliterR);
 
         ::SetWindowLong(viewLeft->m_hWnd, GWL_ID, m_wndSliter.IdFromRowCol(0, 0));
         ::SetWindowLong(viewTop->m_hWnd, GWL_ID, m_wndSliterR.IdFromRowCol(0, 0));
         ::SetWindowLong(viewBot->m_hWnd, GWL_ID, m_wndSliterR.IdFromRowCol(1, 0));
 
         m_wndSliterL.ShowWindow(SW_HIDE);
         m_wndSliterR.ShowWindow(SW_SHOW);
         m_wndSliterR.RecalcLayout();
         m_wndSliter.RecalcLayout();
 
         _isCommomViewStyle=true;
     }
 }

即首先判断当前视图的状态,如果是普通状态(图1),则切换到图2所示状态;否则切换到图1所示状态。切换后同时更新状态标志。

在切换状态的时候,主要步骤为:

1)获取各位置的视图对象,采用CSplitterWnd::GetPane(int row, int col);

2) 重新设置各视图的父容器,CWnd::SetParent(CWnd* pNewWnd);

3) 修改视图窗体信息,::SetWindowLong,具体见代码

4)切换SplitterWnd的显示

5)更新SplitterWnd的布局

其中,非常重要的一点是,SplitterWnd对象划分完成后,必须为每一部分设置视图对象(初次创建时采用CreateView方法),否则程序将不可运行。但是,如果该SpliiterWnd不可见则例外。

最后,我们可以在工具栏添加一个按钮,在该按钮的点击事件响应函数中,调用SwitchViewStyle即可完成布局的动态切换。

下载示例代码

注:本示例中m_wndSliter*变量的申明命名并不规范,请注意。

全文完

enjoy..


本文最早由 杨志军(ic#,yang.email#qq.com) 发表于 个人备忘录软件,以及博客园。转发请保留本声明。

2014/4/22

«上一页12下一页»


相关评论