MFC树形控件和静态切分视图结合程序

来源:互联网 发布:淘宝如何发放优惠券 编辑:程序博客网 时间:2024/05/17 00:08
目录(?)[+]
  1. 源文件下载链接
  2. 最后界面
  3. 创建单文档exe支持切分窗口
  4. 新建对话框资源
  5. 新建视图类并添加控件型变量和初始化函数
  6. 创建一个切分窗口类
  7. 其实质是在切分窗口添加编辑视图和列表视图对象
  8. 创建右侧切分窗口的框架类
  9. 左面版添加视图类成员变量
  10. 修改MainFrame创建静态切分窗口

源文件下载链接

最后界面


1、创建单文档exe,支持切分窗口。

2、新建对话框资源


ID为IDD_TREEVIEW,Style=CHILD,BORDER=NONE,

删掉按钮OK和CANCEL,添加Tree控件IDC_TREE,占满整个对话框


导入位图资源,ID为IDB_BITMAP


新建列表对话框IDD_LISTCTRLVIEW,Style=CHILD,BORDER=NONE,

添加LISTCONTROL控件IDC_LIST,占满蓝色边框,


和编辑视图的对话框资源IDD_EDITVIEW,Style=CHILD,BORDER=NONE,删掉上面的按钮。

添加EditBox控件IDC_EDIT,占满蓝色边界线


3、新建视图类并添加控件型变量和初始化函数

建立2 个View 的类,这里我们让这2个View 的类继承于FormView,
 CListControlView 继承于FormView 关联对话框 IDD_LISTVIEW,为了后面可以new 将构造函数改为publlic属性(默认为protected)

[cpp] view plaincopyprint?
  1. class CListControlView : public CFormView  
  2.  {  
  3.  public:  
  4.     CListControlView();           // protected constructor used by dynamic creation  
  5.     DECLARE_DYNCREATE(CListControlView)  
[cpp] view plaincopyprint?
  1. };  
为列边框添加控件类型变量m_listCtrl

为对话框添加OnSize消息,使列表框与对话框等大

[html] view plaincopyprint?
  1. void CListControlView::OnSize(UINT nType, int cx, int cy)   
  2.  {  
  3.     CFormView::OnSize(nType, cx, cy);  
  4.       
  5.     // TODO: Add your message handler code here  
  6.     CFormView::ShowScrollBar(SB_VERT,FALSE);  
  7.     CFormView::ShowScrollBar(SB_HORZ,FALSE);  
  8.     if (GetSafeHwnd())  
  9.     {  
  10.         if (m_listCtrl.GetSafeHwnd())  
  11.         {  
  12.             CRect rect(0,0,cx,cy);  
  13.             m_listCtrl.MoveWindow(&rect);  
  14.         }  
  15.     }         
  16.  }  

添加虚函数,初始化列表框

[cpp] view plaincopyprint?
  1. void CListControlView::OnInitialUpdate()   
  2.  {  
  3.     CFormView::OnInitialUpdate();  
  4.       
  5.     // TODO: Add your specialized code here and/or call the base class  
  6.     CRect rect;  
  7.     m_listCtrl.GetClientRect(&rect);  
  8.       
  9.     m_listCtrl.InsertColumn(0, "From", LVCFMT_LEFT, rect.Width()/4);  
  10.     m_listCtrl.InsertColumn(1, "Subject", LVCFMT_LEFT, rect.Width()/4);  
  11.     m_listCtrl.InsertColumn(2, "Date", LVCFMT_LEFT, rect.Width()/4);  
  12.     m_listCtrl.InsertColumn(3, "Size", LVCFMT_LEFT, rect.Width()/4);      
  13.  }  



 CEditControlView 继承于FormView 关联对话框IDD_EDITVIEW,为了后面可以new 将构造函数改为publlic属性(默认为protected)

[cpp] view plaincopyprint?
  1. class CEditControlView : public CFormView  
  2.  {  
  3.  public:  
  4.     CEditControlView();           // protected constructor used by dynamic creation  

为CEditControlView上的编辑控件添加控件型变量m_editCtrl


为对话框添加OnSize消息,使编辑框与对话框等大

[cpp] view plaincopyprint?
  1. void CEditControlView::OnSize(UINT nType, int cx, int cy)   
  2.  {  
  3.     CFormView::OnSize(nType, cx, cy);  
  4.       
  5.     // TODO: Add your message handler code here  
  6.     CFormView::ShowScrollBar(SB_VERT,FALSE);  
  7.     CFormView::ShowScrollBar(SB_HORZ,FALSE);  
  8.     //编辑框与窗口大小一样   
  9.     if (GetSafeHwnd())  
  10.     {  
  11.         if (m_editCtrl.GetSafeHwnd())  
  12.         {  
  13.             CRect rect(0,0,cx,cy);  
  14.             m_editCtrl.MoveWindow(&rect);  
  15.         }  
  16.     }     
  17.  }  


现在创建关联树控件的视图类

CLeftPaneView : public CFormView关联对话框 IDD_TREEVIEW。

为CLeftPaneView树控件关联一个控件类型的变量m_treeCtrl


为对话框添加OnSize消息,使树控件与对话框等大

[cpp] view plaincopyprint?
  1. void CLeftPaneView::OnSize(UINT nType, int cx, int cy)   
  2.  {  
  3.     CFormView::OnSize(nType, cx, cy);  
  4.       
  5.     // TODO: Add your message handler code here  
  6.     if (GetSafeHwnd())  
  7.     {  
  8.         CRect rect;  
  9.         GetClientRect(&rect);  
  10.         if (m_treeCtrl.GetSafeHwnd())  
  11.             m_treeCtrl.MoveWindow(&rect);  
  12.     }     
  13.  }  

添加OnInitialUpdate()虚函数,初始化树控件

[cpp] view plaincopyprint?
  1. void CLeftPaneView::OnInitialUpdate()   
  2.  {  
  3.     CFormView::OnInitialUpdate();  
  4.       
  5.     // TODO: Add your specialized code here and/or call the base class  
  6.     m_ImageList.Create(IDB_BITMAP, 16, 1, RGB(255, 0, 255));      
  7.     m_treeCtrl.SetImageList(&m_ImageList, LVSIL_NORMAL);  
  8.       
  9.     m_hSplitterView = m_treeCtrl.InsertItem("Splitter View", 0, 0);  
  10.     m_hListCtrlView = m_treeCtrl.InsertItem("ListCtrl View", 1, 1);  
  11.     m_hEditView     = m_treeCtrl.InsertItem("EditCtrl View", 2, 2);  
  12.  }  
  13.    


4、创建一个切分窗口类

其实质是在切分窗口添加编辑视图和列表视图对象。

源文件中添加

[cpp] view plaincopyprint?
  1. #include "ListControlView.h"   
  2. #include "EditControlView.h"  
为了后面可以new CSplitterView将构造函数改为publlic属性(默认为protected)
[html] view plaincopyprint?
  1. class CSplitterView : public CView  
  2.  {  
  3.  public:    // changed from protected  
  4.     CSplitterView();           // protected constructor used by dynamic creation  
  5. //  
  6. //  
  7. };  


[cpp] view plaincopyprint?
  1. int CSplitterView::OnCreate(LPCREATESTRUCT lpCreateStruct)   
  2.  {  
  3.     if (CView::OnCreate(lpCreateStruct) == -1)  
  4.         return -1;  
  5.       
  6.     // TODO: Add your specialized creation code here  
  7.     m_wndSplitter.CreateStatic(this, 2, 1);  
  8.    
  9.     CCreateContext *pContext = (CCreateContext*) lpCreateStruct->lpCreateParams;  
  10.    
  11.     m_wndSplitter.CreateView(0,0,RUNTIME_CLASS(CListControlView), CSize(150,0), pContext);  
  12.     m_wndSplitter.CreateView(1,0,RUNTIME_CLASS(CEditControlView), CSize(0,0), pContext);  
  13.       
  14.     return 0;  
  15.  }  

添加成员变量

[cpp] view plaincopyprint?
  1. // Attributes   
  2.  public:  
  3.     CSplitterWnd m_wndSplitter;  
  4.    

添加WM_CREATE、WM_SIZE消息响应
[cpp] view plaincopyprint?
  1. int CSplitterView::OnCreate(LPCREATESTRUCT lpCreateStruct)   
  2.  {  
  3.     if (CView::OnCreate(lpCreateStruct) == -1)  
  4.         return -1;  
  5.       
  6.     // TODO: Add your specialized creation code here  
  7.     m_wndSplitter.CreateStatic(this, 2, 1);  
  8.       
  9.     CCreateContext *pContext = (CCreateContext*) lpCreateStruct->lpCreateParams;  
  10.       
  11.     m_wndSplitter.CreateView(0,0,RUNTIME_CLASS(CListCtrlView), CSize(150,0), pContext);  
  12.     m_wndSplitter.CreateView(1,0,RUNTIME_CLASS(CEditCtrlView), CSize(0,0), pContext);  
  13.       
  14.     return 0;  
  15.  }  
  16.    
  17.  void CSplitterView::OnSize(UINT nType, int cx, int cy)   
  18.  {  
  19.     CView::OnSize(nType, cx, cy);  
  20.       
  21.     // TODO: Add your message handler code here  
  22.     m_wndSplitter.MoveWindow(-2,-2,cx+4,cy+4);  
  23.     m_wndSplitter.SetRowInfo(0, cy-(cy/4), 0);  
  24.     m_wndSplitter.SetRowInfo(1, cy/4, 20);  
  25.     m_wndSplitter.RecalcLayout();  
  26.       
  27.  }  
  28.    

5、创建右侧切分窗口的框架类

因为所有视图都要放在框架窗口中,所以,右面板需要一个框架窗口。

新建框架窗口类CRightPaneFrame,继承自CFrameWnd。

为了在框架中调用不同视图类,添加成员变量,并定义视图ID

[cpp] view plaincopyprint?
  1. #include "SplitterView.h"   
  2.  #include "ListControlView.h"  
  3.  #include "EditControlView.h"  
  4.    
  5.  #define  VIEW_SPLITTER 1  
  6.  #define  VIEW_LISTCTRL 2  
  7.  #define  VIEW_EDIT     3  

[cpp] view plaincopyprint?
  1. public:  
  2. CSplitterView* m_pSplitterView;  
  3. CListControlView* m_pListCtrlView;  
  4. CEditControlView* m_pEditCtrlView;  
  5. UINT m_nCurrentViewID;  

添加虚函数

[cpp] view plaincopyprint?
  1. BOOL CRightPaneFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)   
  2.  {  
  3.     // TODO: Add your specialized code here and/or call the base class  
  4.     // TODO: Add your specialized code here and/or call the base class  
  5.       
  6.     m_pSplitterView = new CSplitterView;  
  7.     m_pSplitterView->Create(NULL, NULL, 0L, CFrameWnd::rectDefault, this, VIEW_SPLITTER, pContext);  
  8.     SetActiveView(m_pSplitterView);  
  9.     m_pSplitterView->ShowWindow(SW_SHOW);  
  10.     m_pSplitterView->SetDlgCtrlID(AFX_IDW_PANE_FIRST);  
  11.     m_nCurrentViewID = VIEW_SPLITTER;  
  12.       
  13.     m_pListCtrlView = new CListControlView;  
  14.     ((CView*) m_pListCtrlView)->Create(NULL, NULL, 0L, CFrameWnd::rectDefault, this, VIEW_LISTCTRL, pContext);  
  15.     m_pListCtrlView->ShowWindow(SW_HIDE);  
  16.     m_pListCtrlView->SetDlgCtrlID(VIEW_LISTCTRL);  
  17.       
  18.     m_pEditCtrlView = new CEditControlView;  
  19.     ((CView*) m_pEditCtrlView)->Create(NULL, NULL, 0L, CFrameWnd::rectDefault, this, VIEW_EDIT, pContext);  
  20.     m_pEditCtrlView->ShowWindow(SW_HIDE);  
  21.     m_pEditCtrlView->SetDlgCtrlID(VIEW_EDIT);  
  22.       
  23.       
  24.     RecalcLayout();  
  25.       
  26.     return TRUE;  
  27.  // return CFrameWnd::OnCreateClient(lpcs, pContext);  
  28.  }  


添加切换视图的函数

public:
  void SwitchToView(UINT nView);

[cpp] view plaincopyprint?
  1. void CRightPaneFrame::SwitchToView(UINT nView)  
  2.  {  
  3.     CView* pOldActiveView = GetActiveView();  
  4.     CView* pNewActiveView = NULL;  
  5.    
  6.     switch (nView)  
  7.     {  
  8.     case    VIEW_SPLITTER:  
  9.                 pNewActiveView = (CView*) m_pSplitterView;  
  10.                 break;  
  11.    
  12.     case    VIEW_LISTCTRL:  
  13.                 pNewActiveView = (CView*) m_pListCtrlView;  
  14.                 break;  
  15.     case    VIEW_EDIT:  
  16.                 pNewActiveView = (CView*) m_pEditCtrlView;  
  17.                 break;  
  18.     }  
  19.    
  20.     if (pNewActiveView)  
  21.     {  
  22.         // don't switch when views are the same  
  23.         if (pOldActiveView == pNewActiveView) return;//不变  
  24.           
  25.         SetActiveView(pNewActiveView);//改变活动的视图  
  26.         pNewActiveView->ShowWindow(SW_SHOW);//显示新的视图  
  27.         pNewActiveView->SetDlgCtrlID(AFX_IDW_PANE_FIRST);  
  28.         pOldActiveView->ShowWindow(SW_HIDE);//隐藏旧的视图  
  29.         pOldActiveView->SetDlgCtrlID(m_nCurrentViewID);  
  30.         m_nCurrentViewID = nView;  
  31.           
  32.         RecalcLayout();//调整框架窗口   
  33.     }  
  34.  }  
  35.    
  36.    

注意:

pNewActiveView->SetDlgCtrlID(AFX_IDW_PANE_FIRST);
 
实际上AFX_IDW_PANE_FIRST是为了解决多个VIEW的情况下消息转发的问题,这是MFC内部使用的一个固定的值,所有当前的活动视图都会切换到AFX_IDW_PANE_FIRST这个ID,主窗口收到的一些消息(比如命令、通知等等消息)会转发给活动视图来处理,框架通过这个ID来定位活动视图。
 当在某个SDI应用程序中使用多个视图并支持视图切换时,很容易忽略这点,造成某些消息得不到正确的响应,

因此当激活某个视图时也要把这个视图的ID改成AFX_IDW_PANE_FIRST。

当主框架调整窗口布局时,即调用RecalcLayout()这个函数时,会将ID为AFX_IDW_PANE_FIRST的窗口/视(必须可见)作为最后一个视图进行拉伸以填充剩余的区域。

6.左面版添加视图类成员变量

在左面版也即树视中添加成员变量,包含右面板和树项

[cpp] view plaincopyprint?
  1. // Attributes   
  2.  public:  
  3.     CImageList m_ImageList;  
  4.     HTREEITEM  m_hSplitterView;  
  5.     HTREEITEM  m_hListCtrlView;  
  6.     HTREEITEM  m_hEditView;  
  7.    
  8.     CRightPaneFrame* m_pRightPaneFrame;  
头文件class CLeftPaneView : public CFormView前加前置声明,以便使用VIEW_SPLITTER等宏定义

[cpp] view plaincopyprint?
  1. class CRightPaneFrame;  

在源文件加

[html] view plaincopyprint?
  1. #include "RightPaneFrame.h"  


添加当树形控件选项改变时消息响应,右边视图变化



[cpp] view plaincopyprint?
  1. void CLeftPaneView::OnSelchangedTree(NMHDR* pNMHDR, LRESULT* pResult)   
  2.  {  
  3.     NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;  
  4.     // TODO: Add your control notification handler code here  
  5.     UINT        nView         = 0;  
  6.     HTREEITEM hSelectedItem = m_treeCtrl.GetSelectedItem();  
  7.       
  8.     if (hSelectedItem == m_hSplitterView)  
  9.         nView = VIEW_SPLITTER;  
  10.     else  
  11.         if (hSelectedItem == m_hListCtrlView)  
  12.             nView = VIEW_LISTCTRL;  
  13.         else  
  14.             if (hSelectedItem == m_hEditView)  
  15.                 nView = VIEW_EDIT;  
  16.               
  17.     if (nView) m_pRightPaneFrame->SwitchToView(nView);  
  18.    
  19.     *pResult = 0;  
  20.  }  


7、修改MainFrame,创建静态切分窗口

在源文件中添加

[cpp] view plaincopyprint?
  1. #include "LeftPaneView.h"   
  2.  #include "RightPaneFrame.h"   
  3.    

修改OnCreateClient函数

[cpp] view plaincopyprint?
  1. BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)   
  2.  {  
  3.     // TODO: Add your specialized code here and/or call the base class  
  4.     if (!m_wndSplitter.CreateStatic(this, 1, 2))  
  5.     {  
  6.         TRACE0("Failed to create splitter window\n");  
  7.         return FALSE;  
  8.     }  
  9.       
  10.     // Get the client rect first for calc left pane size  
  11.     CRect rect;  
  12.     GetClientRect(&rect);  
  13.    
  14.     // create the left tree view first.   
  15.     if (!m_wndSplitter.CreateView(0, 0, RUNTIME_CLASS(CLeftPaneView), CSize(rect.Width()/3, 0), pContext))  
  16.     {  
  17.         TRACE0("Failed to create left pane view\n");  
  18.         return FALSE;  
  19.     }  
  20.    
  21.     // The right pane is a frame which and contain several different views.  
  22.     // The is can be set to active or non-active  
  23.     if (!m_wndSplitter.CreateView(0, 1, RUNTIME_CLASS(CRightPaneFrame), CSize(0, 0), pContext))  
  24.     {  
  25.         TRACE0("Failed to create right pane frame\n");  
  26.         return FALSE;  
  27.     }  
  28.    
  29.     CLeftPaneView* pLeftPaneView     = (CLeftPaneView*)   m_wndSplitter.GetPane(0,0);  
  30.     pLeftPaneView->m_pRightPaneFrame = (CRightPaneFrame*) m_wndSplitter.GetPane(0,1);  
  31.       
  32.     // Set the left pane as the active view  
  33.     SetActiveView((CView*) m_wndSplitter.GetPane(0, 0));  
  34.    
  35.     return TRUE;  
  36.  }  
0 0
原创粉丝点击