树形控件
一、第一阶段
1、新建一个MFC AppWizard(exe)单文档工程,如下图所示。
2、将提前准备好的图标资源放在你所创建的工程文件夹的“res”里面,如下图所示。
3、然后在“Icon”里右击“引入(M)…”,将图标资源引入进来,并右击“属性”,对其ID号重新命名,如下图所示。
4、接下来,我们插入一个类,将其基类选为“CTreeView”,并在“CMyTreeView”开头处嵌入:#include “afxcview.h”,如下图所示。
5、然后定义图像列表CImageList m_imageList的对象,并添加一个树状图标,如下图所示。
6、给CmyTreeView添加虚函数OnInitialUpdate(),并添加相应代码,如下图所示。
void CMyTreeView::OnInitialUpdate()
{
CTreeView::OnInitialUpdate();
// TODO: Add your specialized code here and/or call the base class
m_imageList.Create(32,32,ILC_COLOR32|ILC_MASK,0,0); //32*32是图标分辨率,ILC_COLOR32是32位颜色,ILC_MASK是透明底色
//向图像列表中添加图标
m_imageList.Add(AfxGetApp()->LoadIcon(IDR_MAINFRAME)); //AfxGetApp()是获得窗口的一个指针
m_imageList.Add(AfxGetApp()->LoadIcon(IDI_ICODangDang));
m_imageList.Add(AfxGetApp()->LoadIcon(IDI_ICOJingDong));
m_imageList.Add(AfxGetApp()->LoadIcon(IDI_ICOTaoBao));
m_imageList.Add(AfxGetApp()->LoadIcon(IDI_ICOWeiPinHui));
this->GetTreeCtrl().SetImageList(&m_imageList,TVSIL_NORMAL); //通过当前这个视图类获取TreeCtrl()树状控件的使用权
//获取树状控件默认的显示方式
DWORD dwStyle = GetWindowLong(this->GetTreeCtrl().m_hWnd,GWL_STYLE);
dwStyle |= TVS_FULLROWSELECT | TVS_HASBUTTONS | TVS_HASLINES | TVSIL_NORMAL | TVS_LINESATROOT;
SetWindowLong(this->GetTreeCtrl().m_hWnd,GWL_STYLE,dwStyle);//设定当前CMytreeView中树形控件的显示风格
//下面建立树形控件的分支节点
m_treeItem = this->GetTreeCtrl().InsertItem("电子商务",0,0); //根节点
this->GetTreeCtrl().InsertItem("当当网",1,0,m_treeItem);
this->GetTreeCtrl().InsertItem("京东",2,0,m_treeItem);
this->GetTreeCtrl().InsertItem("淘宝",3,0,m_treeItem);
this->GetTreeCtrl().InsertItem("唯品会",4,0,m_treeItem);
}
7、接下来在CMainFrame的public下添加定义切分视图的成员变量代码,如下图所示。
CSplitterWnd m_wndSplitter;
8、然后给CMainFrame添加OnCreateClient函数,并将两个头文件嵌入进来,如下图所示。
9、在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))
return false;
m_wndSplitter.CreateView(0,0,RUNTIME_CLASS(CMyTreeView),CSize(300,500),pContext);
m_wndSplitter.CreateView(0,1,RUNTIME_CLASS(CChapter_0702View),CSize(500,500),pContext);
return true;
return CFrameWnd::OnCreateClient(lpcs, pContext);
}
10、此时编译运行会出现“error C2143: syntax error : missing ‘;’ before ‘*’ ”,这时,我们只需嵌入#include "Chapter_0702Doc.h"即可,如下图所示。
11、编译运行结果如下图所示。
二、第二阶段
12、对CMyTreeView进行编程,首先在“Add Windows Message Handler…”添加“=NM_CLICK”,代码如下。
void CMyTreeView::OnClick(NMHDR* pNMHDR, LRESULT* pResult)
{
// TODO: Add your control notification handler code here
HTREEITEM itemSel = this->GetTreeCtrl().GetSelectedItem(); //获得树状控件的使用权
if(!this->GetTreeCtrl().GetChildItem(itemSel)) //如果被选中的节点没有孩子节点的话
{
CString str = this->GetTreeCtrl().GetItemText(itemSel);
AfxMessageBox(str);
}
*pResult = 0;
}
13、编译运行后结果如下图所示。
三、第三阶段
14、接下来的工作就是实现左右两边数据的传递,当点击左边树状菜单里面的叶子节点时,右边会弹出相应的数据。
15、新建一个“C/C++ Header File”,以及与之配套的“C++ Source File”,如下图所示。
16、首先对GlobalParas.h进行条件编译(框架),代码如下。
#if !defined GlobalParas_H
#define GlobalParas_H
//待会儿在这里添加代码
#endif
17、然后在GlobalParas.cpp里添加代码(MFC里只要是.cpp文件,都要把标准的应用程序框架stdafx.h给嵌入进来),如下图所示。
18、将HWND g_viewWnd;
CString g_itemSelStr;
这两行代码拷贝到GlobalParas.h中对应地方去,如下图所示。
此时,我们的全局量就已经建好了。
19、接下来我们要获取窗口的句柄,通过全局量把窗口句柄进行保存,让后面发送消息的窗口对应的全局的窗口句柄进行发送。(我们现在的思路是,通过点击某一叶子节点,把这个消息发送到右边的视图区域去,右边的视图区域它是一个窗口,把这个消息发过来,是通过API函数。)于是就有下面的过程。
20、在点击事件(OnClick())中,把代码所获取的字符串给它送到全局量中去,如下图所示。
21、由于发送消息的机制最复杂,所以我们放到最后去实现。
22、假设消息已经发送过去了,接下来的工作就是在右边的视图区域里把接收的字符串写出来。写出来很简单,就是在CChapter_0702View 的OnDraw(0函数里面用pDC就行,代码如下。
void CChapter_0702View::OnDraw(CDC* pDC)
{
CChapter_0702Doc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
pDC->TextOut(200,200,g_itemSelStr); //假设输出的位置坐标是(200,200)
}
(记得在开头处嵌入全局量的头文件。)
23、接下来就是发送消息的机制了。
首先在GlobalParas.h里面做准备工作,添加代码如下图所示。
24、在CChapter_0702View里面建立对它消息的响应。在它的头文件里面,建立接收消息的函数,如下图所示。
还要在它的消息机制里进行绑定和实现(绑定就是把它对应的消息进行绑定),在.cpp文件里绑定消息,如下图所示。
25、定义编写消息响应函数On_treeItemSel(),如下图所示。
LRESULT CChapter_0702View::On_treeItemSel(WPARAM wParam, LPARAM lParam)
{
if(1 == wParam) //如果传过来的参数值是1的话,我们刷新当前这个视图类
Invalidate(true);
return 0;
}
26、最后的一个工作就是发送消息的代码(在OnClick()函数里),如下图所示。
::SendMessage(g_viewWnd,WM_treeItemSel,1,0); //发送消息的机制(::是运算符,调用全局API函数)
27、运行结果如下图所示。