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

源文件下载链接

最后界面


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)

class CListControlView : public CFormView
 {
 public:
 	CListControlView();           // protected constructor used by dynamic creation
 	DECLARE_DYNCREATE(CListControlView)
};
为列边框添加控件类型变量m_listCtrl

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

void CListControlView::OnSize(UINT nType, int cx, int cy) 
 {
 	CFormView::OnSize(nType, cx, cy);
 	
 	// TODO: Add your message handler code here
 	CFormView::ShowScrollBar(SB_VERT,FALSE);
 	CFormView::ShowScrollBar(SB_HORZ,FALSE);
 	if (GetSafeHwnd())
 	{
 		if (m_listCtrl.GetSafeHwnd())
 		{
 			CRect rect(0,0,cx,cy);
 			m_listCtrl.MoveWindow(&rect);
 		}
 	}		
 }

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

void CListControlView::OnInitialUpdate() 
 {
 	CFormView::OnInitialUpdate();
 	
 	// TODO: Add your specialized code here and/or call the base class
 	CRect rect;
 	m_listCtrl.GetClientRect(&rect);
 	
 	m_listCtrl.InsertColumn(0, "From", LVCFMT_LEFT, rect.Width()/4);
 	m_listCtrl.InsertColumn(1, "Subject", LVCFMT_LEFT, rect.Width()/4);
 	m_listCtrl.InsertColumn(2, "Date", LVCFMT_LEFT, rect.Width()/4);
 	m_listCtrl.InsertColumn(3, "Size", LVCFMT_LEFT, rect.Width()/4);	
 }



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

class CEditControlView : public CFormView
 {
 public:
 	CEditControlView();           // protected constructor used by dynamic creation

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


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

void CEditControlView::OnSize(UINT nType, int cx, int cy) 
 {
 	CFormView::OnSize(nType, cx, cy);
 	
 	// TODO: Add your message handler code here
 	CFormView::ShowScrollBar(SB_VERT,FALSE);
 	CFormView::ShowScrollBar(SB_HORZ,FALSE);
 	//编辑框与窗口大小一样
 	if (GetSafeHwnd())
 	{
 		if (m_editCtrl.GetSafeHwnd())
 		{
 			CRect rect(0,0,cx,cy);
 			m_editCtrl.MoveWindow(&rect);
 		}
 	}	
 }


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

CLeftPaneView : public CFormView关联对话框IDD_TREEVIEW。

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


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

void CLeftPaneView::OnSize(UINT nType, int cx, int cy) 
 {
 	CFormView::OnSize(nType, cx, cy);
 	
 	// TODO: Add your message handler code here
 	if (GetSafeHwnd())
 	{
 		CRect rect;
 		GetClientRect(&rect);
 		if (m_treeCtrl.GetSafeHwnd())
 			m_treeCtrl.MoveWindow(&rect);
 	}	
 }

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

void CLeftPaneView::OnInitialUpdate() 
 {
 	CFormView::OnInitialUpdate();
 	
 	// TODO: Add your specialized code here and/or call the base class
 	m_ImageList.Create(IDB_BITMAP, 16, 1, RGB(255, 0, 255));	
 	m_treeCtrl.SetImageList(&m_ImageList, LVSIL_NORMAL);
 	
 	m_hSplitterView = m_treeCtrl.InsertItem("Splitter View", 0, 0);
 	m_hListCtrlView = m_treeCtrl.InsertItem("ListCtrl View", 1, 1);
 	m_hEditView     = m_treeCtrl.InsertItem("EditCtrl View", 2, 2);
 }
 


4、创建一个切分窗口类

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

源文件中添加

#include "ListControlView.h"
#include "EditControlView.h"
为了后面可以new CSplitterView将构造函数改为publlic属性(默认为protected)
class CSplitterView : public CView
 {
 public:	// changed from protected
 	CSplitterView();           // protected constructor used by dynamic creation
//
//
};


int CSplitterView::OnCreate(LPCREATESTRUCT lpCreateStruct) 
 {
 	if (CView::OnCreate(lpCreateStruct) == -1)
 		return -1;
 	
 	// TODO: Add your specialized creation code here
 	m_wndSplitter.CreateStatic(this, 2, 1);
 
 	CCreateContext *pContext = (CCreateContext*) lpCreateStruct->lpCreateParams;
 
 	m_wndSplitter.CreateView(0,0,RUNTIME_CLASS(CListControlView), CSize(150,0), pContext);
 	m_wndSplitter.CreateView(1,0,RUNTIME_CLASS(CEditControlView), CSize(0,0), pContext);
 	
 	return 0;
 }

添加成员变量

// Attributes
 public:
 	CSplitterWnd m_wndSplitter;
 

添加WM_CREATE、WM_SIZE消息响应
int CSplitterView::OnCreate(LPCREATESTRUCT lpCreateStruct) 
 {
 	if (CView::OnCreate(lpCreateStruct) == -1)
 		return -1;
 	
 	// TODO: Add your specialized creation code here
 	m_wndSplitter.CreateStatic(this, 2, 1);
 	
 	CCreateContext *pContext = (CCreateContext*) lpCreateStruct->lpCreateParams;
 	
 	m_wndSplitter.CreateView(0,0,RUNTIME_CLASS(CListCtrlView), CSize(150,0), pContext);
 	m_wndSplitter.CreateView(1,0,RUNTIME_CLASS(CEditCtrlView), CSize(0,0), pContext);
 	
 	return 0;
 }
 
 void CSplitterView::OnSize(UINT nType, int cx, int cy) 
 {
 	CView::OnSize(nType, cx, cy);
 	
 	// TODO: Add your message handler code here
 	m_wndSplitter.MoveWindow(-2,-2,cx+4,cy+4);
 	m_wndSplitter.SetRowInfo(0, cy-(cy/4), 0);
 	m_wndSplitter.SetRowInfo(1, cy/4, 20);
 	m_wndSplitter.RecalcLayout();
 	
 }
 

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

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

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

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

#include "SplitterView.h"
#include "ListControlView.h"
#include "EditControlView.h"

#define VIEW_SPLITTER 1
#define VIEW_LISTCTRL 2
#define VIEW_EDIT   3

public:
CSplitterView* m_pSplitterView;
CListControlView* m_pListCtrlView;
CEditControlView* m_pEditCtrlView;
UINT m_nCurrentViewID;

添加虚函数

BOOL CRightPaneFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext) 
 {
 	// TODO: Add your specialized code here and/or call the base class
 	// TODO: Add your specialized code here and/or call the base class
 	
 	m_pSplitterView = new CSplitterView;
 	m_pSplitterView->Create(NULL, NULL, 0L, CFrameWnd::rectDefault, this, VIEW_SPLITTER, pContext);
 	SetActiveView(m_pSplitterView);
 	m_pSplitterView->ShowWindow(SW_SHOW);
 	m_pSplitterView->SetDlgCtrlID(AFX_IDW_PANE_FIRST);
 	m_nCurrentViewID = VIEW_SPLITTER;
 	
 	m_pListCtrlView = new CListControlView;
 	((CView*) m_pListCtrlView)->Create(NULL, NULL, 0L, CFrameWnd::rectDefault, this, VIEW_LISTCTRL, pContext);
 	m_pListCtrlView->ShowWindow(SW_HIDE);
 	m_pListCtrlView->SetDlgCtrlID(VIEW_LISTCTRL);
 	
 	m_pEditCtrlView = new CEditControlView;
 	((CView*) m_pEditCtrlView)->Create(NULL, NULL, 0L, CFrameWnd::rectDefault, this, VIEW_EDIT, pContext);
 	m_pEditCtrlView->ShowWindow(SW_HIDE);
 	m_pEditCtrlView->SetDlgCtrlID(VIEW_EDIT);
 	
 	
 	RecalcLayout();
 	
 	return TRUE;
 //	return CFrameWnd::OnCreateClient(lpcs, pContext);
 }


添加切换视图的函数

public:
void SwitchToView(UINT nView);

void CRightPaneFrame::SwitchToView(UINT nView)
 {
 	CView* pOldActiveView = GetActiveView();
 	CView* pNewActiveView = NULL;
 
 	switch (nView)
 	{
 	case	VIEW_SPLITTER:
 				pNewActiveView = (CView*) m_pSplitterView;
 				break;
 
 	case	VIEW_LISTCTRL:
 				pNewActiveView = (CView*) m_pListCtrlView;
 				break;
 	case	VIEW_EDIT:
 				pNewActiveView = (CView*) m_pEditCtrlView;
 				break;
 	}
 
 	if (pNewActiveView)
 	{
 		// don't switch when views are the same
 		if (pOldActiveView == pNewActiveView) return;//不变
 		
 		SetActiveView(pNewActiveView);//改变活动的视图
 		pNewActiveView->ShowWindow(SW_SHOW);//显示新的视图
 		pNewActiveView->SetDlgCtrlID(AFX_IDW_PANE_FIRST);
 		pOldActiveView->ShowWindow(SW_HIDE);//隐藏旧的视图
 		pOldActiveView->SetDlgCtrlID(m_nCurrentViewID);
 		m_nCurrentViewID = nView;
 		
 		RecalcLayout();//调整框架窗口
 	}
 }
 
 

注意:

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.左面版添加视图类成员变量

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

// Attributes
 public:
 	CImageList m_ImageList;
 	HTREEITEM  m_hSplitterView;
 	HTREEITEM  m_hListCtrlView;
 	HTREEITEM  m_hEditView;
 
 	CRightPaneFrame* m_pRightPaneFrame;
头文件class CLeftPaneView : public CFormView前加前置声明,以便使用VIEW_SPLITTER等宏定义

class CRightPaneFrame;

在源文件加

#include "RightPaneFrame.h"


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



void CLeftPaneView::OnSelchangedTree(NMHDR* pNMHDR, LRESULT* pResult) 
 {
 	NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
 	// TODO: Add your control notification handler code here
 	UINT	    nView         = 0;
 	HTREEITEM hSelectedItem = m_treeCtrl.GetSelectedItem();
 	
 	if (hSelectedItem == m_hSplitterView)
 		nView = VIEW_SPLITTER;
 	else
 		if (hSelectedItem == m_hListCtrlView)
 			nView = VIEW_LISTCTRL;
 		else
 			if (hSelectedItem == m_hEditView)
 				nView = VIEW_EDIT;
 			
 	if (nView) m_pRightPaneFrame->SwitchToView(nView);
 
 	*pResult = 0;
 }


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

在源文件中添加

#include "LeftPaneView.h"
 #include "RightPaneFrame.h"
 

修改OnCreateClient函数

BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext) 
 {
 	// TODO: Add your specialized code here and/or call the base class
 	if (!m_wndSplitter.CreateStatic(this, 1, 2))
 	{
 		TRACE0("Failed to create splitter window\n");
 		return FALSE;
 	}
 	
 	// Get the client rect first for calc left pane size
 	CRect rect;
 	GetClientRect(&rect);
 
 	// create the left tree view first.
 	if (!m_wndSplitter.CreateView(0, 0, RUNTIME_CLASS(CLeftPaneView), CSize(rect.Width()/3, 0), pContext))
 	{
 		TRACE0("Failed to create left pane view\n");
 		return FALSE;
 	}
 
 	// The right pane is a frame which and contain several different views.
 	// The is can be set to active or non-active
 	if (!m_wndSplitter.CreateView(0, 1, RUNTIME_CLASS(CRightPaneFrame), CSize(0, 0), pContext))
 	{
 		TRACE0("Failed to create right pane frame\n");
 		return FALSE;
 	}
 
 	CLeftPaneView* pLeftPaneView     = (CLeftPaneView*)   m_wndSplitter.GetPane(0,0);
 	pLeftPaneView->m_pRightPaneFrame = (CRightPaneFrame*) m_wndSplitter.GetPane(0,1);
 	
 	// Set the left pane as the active view
 	SetActiveView((CView*) m_wndSplitter.GetPane(0, 0));
 
 	return TRUE;
 }
 



  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值