【第30节】MFC编程:ListCtrl控件和TreeCtrl控件

目录

引言

一、高级控件ListCtrl

二、高级控件TreeCtrl

三、Shell控件

四、CImageList

五、综合代码示例


引言

在MFC编程里,高级控件能大幅提升应用程序的交互性与功能性。接下来,咱们会详细讲讲ListCtrl和TreeCtrl这两个高级控件。不仅会介绍它们的功能、操作方法,还会分享创建与使用时的实操步骤,助力大家掌握这些控件的开发技巧 。

一、高级控件ListCtrl

ListCtrl控件可以把字符串内容,用列表形式展示出来。这种展示方法既整齐又直观,在实际使用过程中,能让用户更方便。

一般情况下,使用ListCtrl控件时,需要将它和CListCtrl类,或者从CListCtrl派生出来的类所创建的对象进行绑定。

常见函数如下:

具体每个消息的含义,可在控件属性栏中选择消息查看中文解释,也可查阅MSDN。

ListCtrl控件的创建步骤

  1. 添加变量:为ListCtrl控件添加变量。
  1. 添加类:右键点击list控件,选择"添加类",类名设为CMyListCtrl,基类选择CListCtrl(该类继承于CListCtrl)。

  2. 绑定变量生成代码:绑定变量完成后会在当前对话框类的相应位置生成代码。

头文件中:

cpp 复制代码
protected:
virtual void DoDataExchange(CDataExchange*pDX);
DECLARE_MESSAGE_MAP()
// 该窗口类对应的h类中
public:
CListCtrl mListCtrl;

CPP文件中:

cpp 复制代码
void CListCtrlDlg::DoDataExchange(CDataExchange*pDX)
{
    CDialogEx::DoDataExchange(pDX);
    DDX_Control(pDX, IDC_LIST1, mListCtrl);
}
  1. 初始化:在该窗口类的OnInitDialog()中对ListCtrl初始化。
cpp 复制代码
//获取当前控件的扩展风格
DWORD dwOldStyle = mListCtrl.GetExtendedStyle();  //获取原风格
//设置当前控件的扩展风格
mListCtrl.SetExtendedStyle(dwOldStyle |
    LVS_EX_FULLROWSELECT| //报表视图形式
    LVS_EX_GRIDLINES //网格线(只适用与report风格的listctrl)
    LVS_EX_CHECKBOXES);  //item前生成checkbox控件
//获取list的宽度
CRect rc;
mListCtrl.GetClientRect(rc);
int nWidth = rc.Width();
//为List插入列信息
mListCtrl.InsertColumn(0, L"姓名", 0, nWidth/3); //当前列编号、要求插入的信息、风格、列的宽度
mListCtrl.InsertColumn(1, L"性别", 0, nWidth /3);
mListCtrl.InsertColumn(2, L"年龄", 0, nWidth/3);
//插入生信息
mListCtrl.InsertItem(0, L"张三"); //行号
mListCtrl.SetItemText(0, 1, L"男"); //行号、列号
mListCtrl.SetItemText(0, 2, L"20");
mListCtrl.InsertItem(1, L"李四");
mListCtrl.SetItemText(1, 1, L"男");
mListCtrl.SetItemText(1, 2, L"22");

运行之后,列表框会显示相应内容。

  1. 响应选中行:为新添加的List类添加点击事件,通过类向导选择"消息"中的NM_CLICK消息。

头文件中:

cpp 复制代码
public :
afx_msg void OnNMGIick(NMHDR *pNMHDR, LRESULT *pResult);

CPP文件中:

cpp 复制代码
// 消息映射宏中添加的代码
BEGIN_MESSAGE_MAP(CMyListCtrl, CListCtrl)
    ON_NOTIFY_REFLECT(NM_CLICK, &CMyListCtrl::OnNMClicK)
END_MESSAGE_MAP()
// 函数实现部分
void CMyListCtrl::OnNMClicK(NMHDR *pNMHDR, LRESULT *pResult)
{
    LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
    //TODO:在此添加控件通知处理程序代码
    *pResult = 0;
}

可以在注释下面添加相应代码。

二、高级控件TreeCtrl

树控件是较为复杂的控件,这里先简要介绍其基本使用方法,后续课程会介绍一些使用技巧。树控件的每个节点都由一个HTREEITEM类型的句柄标识,在插入或查找树节点时会用到。

CTree类的常见函数

重点函数详解

cpp 复制代码
HTREEITEM InsertItem(
    LPCTSTR lpszItem,
    int nImage,
    int nSelectedImage,
    HTREEITEM hParent =TVI_ROOT,
    HTREEITEM hInsertAfter =TVI_LAST);
  • lpszItem:为新节点的标签文本字符串的指针。

  • nImage:为新节点的图标在树形控件图像序列中的索引。

  • nSelectedImage:为新节点被选中时的图标在图像序列中的索引。

  • hParent:为插入节点的父节点的句柄。

  • hInsertAfter:为新节点的前一个节点的句柄,即新节点将被插入到hInsertAfter节点之后。

与其他控件使用方法相同,需要为Tree控件绑定一个控件类型的变量。

通知消息

Tree控件和所有控件一样,都有针对父窗口的通知消息,可通过类向导查看,如:TVN_SELCHANGED、TVN_BEGINDRAG、TVN_BEGINLABELEDIT、TVN_BEGINRDRAG、TVN_DELETEITEM、TVN_ENDLABELEDIT、TVN_GETDISPINFO、TVN_ITEMEXPANDED等。

我们可测试其中的TVN_SELCHANGED消息(被选择的树节点改变的消息),与tab控件一样,这个消息也有对应的发给自身的反射消息,在类向导中添加其处理程序即可。

三、Shell控件

Shell控件主要用于实现与Windows Shell相关的功能,例如文件资源管理器的树形视图和列表视图。以下是关于MFC中Shell控件用法的详细介绍:

  1. Shell控件概述

MFC提供了两个主要的Shell控件:

  • `CMFCShellTreeCtrl`:用于显示文件系统的树形结构,类似于Windows资源管理器的左侧树形视图。

  • `CMFCShellListCtrl`:用于显示指定文件夹中的文件列表,类似于Windows资源管理器的右侧文件列表。

这两个控件可以结合使用,创建一个类似于文件资源管理器的应用程序。

  1. 创建Shell控件

以下是如何在MFC应用程序中使用Shell控件的步骤:

2.1 创建MFC项目

  • 使用Visual Studio的MFC应用程序向导创建一个新的MFC项目。在向导中,选择"单个文档"或"对话框"应用程序类型,并确保勾选"ActiveX控件"和"导航窗格"选项。导航窗格选项会自动在窗口左侧嵌入一个`CMFCShellTreeCtrl`控件。

2.2 添加Shell控件

  • `CMFCShellTreeCtrl`:通常由向导自动创建,嵌入在主窗口的左侧窗格中。

  • `CMFCShellListCtrl`:需要在视图类中手动添加。首先在视图头文件中包含`afxShellListCtrl.h`,然后声明一个`CMFCShellListCtrl`类型的成员变量。接着,在`OnCreate`方法中初始化并创建该控件。
    示例代码:

cpp 复制代码
#include <afxShellListCtrl.h>

class CMFCShellControlsView : public CView {
private:
    CMFCShellListCtrl m_wndList;
};

在`OnCreate`方法中:

cpp 复制代码
int CMFCShellControlsView::OnCreate(LPCREATESTRUCT lpCreateStruct) {
    if (CView::OnCreate(lpCreateStruct) == -1)
        return -1;

    CRect rect;
    GetClientRect(&rect);
    m_wndList.Create(WS_CHILD | WS_VISIBLE | LVS_REPORT, rect, this, 2);

    return 0;
}
  1. Shell控件的交互
  • 树形控件与列表控件的联动:当用户在`CMFCShellTreeCtrl`中选择一个文件夹时,`CMFCShellListCtrl`应显示该文件夹中的内容。可以通过处理树形控件的`TVN_SELCHANGED`消息来实现这一功能。

示例代码:

cpp 复制代码
void CMFCShellControlsView::OnTvnSelchangedTree(NMHDR *pNMHDR, LRESULT *pResult) {
    LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
    CString strPath;
    m_wndTree.GetItemPath(strPath, pNMTreeView->itemNew.hItem);
    m_wndList.SetFolder(strPath);
    *pResult = 0;
}
  1. Shell控件的扩展功能
  • 文件操作:可以通过`CMFCShellListCtrl`实现文件的复制、移动、删除等操作。

  • 自定义显示:可以自定义列表控件的显示方式,例如图标视图、详细信息视图等。

  1. 注意事项
  • 路径处理:Shell控件使用PIDL(指向项目标识符列表的指针)来唯一标识文件和文件夹。可以使用`CMFCShellManager`类来管理PIDL和路径之间的转换。

  • 权限问题:某些系统文件夹可能需要管理员权限才能访问,需确保应用程序有足够的权限。

通过以上步骤和代码示例,您可以在MFC应用程序中实现类似文件资源管理器的功能,并充分利用Shell控件的强大功能。

四、CImageList

`CImageList` 是 MFC(Microsoft Foundation Classes)中的一个类,用于管理相同大小的图像集合,通常用于为其他控件(如列表控件、树控件、标签控件等)提供图标资源。以下是 `CImageList` 的用法详细介绍:

  1. 创建 `CImageList` 对象

`CImageList` 的创建通过 `Create` 方法实现,该方法有多个重载版本,常用的形式如下:

cpp 复制代码
BOOL Create(int cx, int cy, UINT nFlags, int nInitial, int nGrow);
BOOL Create(UINT nBitmapID, int cx, int nGrow, COLORREF crMask);
BOOL Create(LPCTSTR lpszBitmapID, int cx, int nGrow, COLORREF crMask);

- 参数说明:

  • `cx` 和 `cy`:图像的宽度和高度(以像素为单位)。

  • `nFlags`:指定图像列表的类型,如 `ILC_COLOR4`(16色)、`ILC_COLOR8`(256色)、`ILC_COLOR32`(真彩色)等。

  • `nInitial`:初始图像数量。

  • `nGrow`:当图像列表需要扩展时,每次增加的图像数量。

  • `nBitmapID` 或 `lpszBitmapID`:位图资源的 ID 或路径。

  • `crMask`:用于生成透明掩码的颜色。

示例:

cpp 复制代码
CImageList m_ImageList;
m_ImageList.Create(32, 32, ILC_COLOR32 | ILC_MASK, 0, 4);
  1. 添加图像

`CImageList` 支持从资源文件或外部文件添加图像:

cpp 复制代码
// 从资源文件添加图标
m_ImageList.Add(AfxGetApp()->LoadIcon(IDI_ICON1));
m_ImageList.Add(AfxGetApp()->LoadIcon(IDI_ICON2));

// 从资源文件添加位图
CBitmap bmp;
bmp.LoadBitmap(IDB_BITMAP1);
m_ImageList.Add(&bmp, RGB(0, 0, 0)); // RGB(0, 0, 0) 为透明色
bmp.DeleteObject();

// 从外部文件添加位图
HBITMAP hBitmap = (HBITMAP)LoadImage(NULL, _T("e:\\TIME.bmp"), IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
CBitmap* pBitmap = new CBitmap;
pBitmap->Attach(hBitmap);
m_ImageList.Add(pBitmap, RGB(0, 0, 0));
delete pBitmap;
  1. 关联控件

`CImageList` 通常与其他控件(如 `CListCtrl`、`CTreeCtrl`)一起使用,通过 `SetImageList` 方法关联:

cpp 复制代码
// 关联列表控件
CListCtrl m_ListCtrl;
m_ListCtrl.SetImageList(&m_ImageList, LVSIL_NORMAL);

// 关联树控件
CTreeCtrl m_TreeCtrl;
m_TreeCtrl.SetImageList(&m_ImageList, TVSIL_NORMAL);
  1. 绘制图像

可以通过 `Draw` 方法将图像绘制到设备上下文(DC)中:

cpp 复制代码
CDC* pDC = GetDC();
CPoint pt(30, 50);
for (int i = 0; i < m_ImageList.GetImageCount(); i++) {
    m_ImageList.Draw(pDC, i, pt, ILD_NORMAL);
    pt.x += 60;
}
ReleaseDC(pDC);
  1. 常用操作
  • 获取图像数量:`int GetImageCount()`

  • 删除图像:`BOOL Remove(int nImage)`

  • 设置背景颜色:`COLORREF SetBkColor(COLORREF cr)`

  • 删除图像列表:`BOOL DeleteImageList()`

  • 提取图标:`HICON ExtractIcon(int nImage)`

  1. 应用示例

以下是一个完整的示例,展示如何创建 `CImageList` 并关联到 `CListCtrl`:

cpp 复制代码
// 在对话框类中定义成员变量
CImageList m_ImageList;
CListCtrl m_ListCtrl;

// 在 OnInitDialog 中初始化
m_ImageList.Create(32, 32, ILC_COLOR32 | ILC_MASK, 0, 4);
m_ImageList.Add(AfxGetApp()->LoadIcon(IDI_ICON1));
m_ImageList.Add(AfxGetApp()->LoadIcon(IDI_ICON2));

m_ListCtrl.SetImageList(&m_ImageList, LVSIL_NORMAL);
m_ListCtrl.InsertItem(0, _T("Item 1"), 0);
m_ListCtrl.InsertItem(1, _T("Item 2"), 1);
  1. 注意事项
  • `CImageList` 本身不可见,必须与其他控件结合使用。

  • 图像列表中的图像大小必须一致。

  • 使用透明色时,确保 `ILC_MASK` 标志被设置。

通过以上方法,可以有效地在 MFC 应用程序中使用 `CImageList` 来管理和显示图像资源。

五、综合代码示例

该项目是一个演示 MFC 中列表控件(CListCtrl)和树形控件(CTreeCtrl)使用的示例程序。主要功能包括:

  1. 列表控件(CListCtrl)功能:
  • 使用网格线样式和整行选择

  • 包含3列数据展示

  • 每行显示3个数据项

  • 支持图标显示

  • 点击列表项会弹出消息框显示选中内容

  1. 树形控件(CTreeCtrl)功能:
  • 支持图标显示

  • 包含两级树形结构:

  • 第一级:SDK、MFC

  • 第二级:SDK001/SDK002、MFC001/MFC002

  • 支持节点选择和点击事件

  • 点击树节点会弹出消息框显示节点文本

  1. Shell控件功能:
  • 使用 CMFCShellTreeCtrl 和 CMFCShellListCtrl 实现文件系统浏览

  • 树形控件显示文件夹结构

  • 列表控件显示当前文件夹内容

  • 两个控件联动,选择文件夹时自动更新列表内容

  1. 界面特点:
  • 使用图标列表(CImageList)管理界面图标

  • 包含4个图标资源(1.ico ~ 4.ico)

  • 支持对话框最小化时的图标显示

  1. 其他功能:
  • 包含"关于"对话框

  • 支持系统菜单

  • 使用 Unicode 字符集

  • 支持 Windows 视觉样式

这个项目主要用于演示 MFC 中常用控件的使用方法和基本功能,包括列表控件、树形控件、Shell控件等。

cpp 复制代码
// 01.ListTree.h : PROJECT_NAME 应用程序的主头文件
//

#pragma once

#ifndef __AFXWIN_H__
	#error "在包含此文件之前包含"stdafx.h"以生成 PCH 文件"
#endif

#include "resource.h"		// 主符号


// CMy01ListTreeApp: 
// 有关此类的实现,请参阅 01.ListTree.cpp
//

class CMy01ListTreeApp : public CWinApp
{
public:
	CMy01ListTreeApp();

// 重写
public:
	virtual BOOL InitInstance();

// 实现

	DECLARE_MESSAGE_MAP()
};

extern CMy01ListTreeApp theApp;
cpp 复制代码
// 01.ListTreeDlg.h : 头文件
//

#pragma once
#include "afxcmn.h"
#include "afxshelltreectrl.h"
#include "afxshelllistctrl.h"


// CMy01ListTreeDlg 对话框
class CMy01ListTreeDlg : public CDialogEx
{
// 构造
public:
	CMy01ListTreeDlg(CWnd* pParent = NULL);	// 标准构造函数

// 对话框数据
#ifdef AFX_DESIGN_TIME
	enum { IDD = IDD_MY01LISTTREE_DIALOG };
#endif

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);	// DDX/DDV 支持


// 实现
protected:
	HICON m_hIcon;

	// 生成的消息映射函数
	virtual BOOL OnInitDialog();
	afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
	afx_msg void OnPaint();
	afx_msg HCURSOR OnQueryDragIcon();
	DECLARE_MESSAGE_MAP()
public:
	CListCtrl m_list;
	// 初始化list
	void InitList();
	// 初始化图标数组
	CImageList m_img;
	void InitImgList();
	afx_msg void OnNMClickList1(NMHDR *pNMHDR, LRESULT *pResult);
	// 初始化树控件
	CTreeCtrl m_tree;
	void  InitTree();
	afx_msg void OnTvnSelchangedTree1(NMHDR *pNMHDR, LRESULT *pResult);
	afx_msg void OnNMClickTree1(NMHDR *pNMHDR, LRESULT *pResult);
	CMFCShellTreeCtrl m_mfcTree;
	CMFCShellListCtrl m_mfcList;
};
cpp 复制代码
//resource.h
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ 生成的包含文件。
// 供 01.ListTree.rc 使用
//
#define IDM_ABOUTBOX                    0x0010
#define IDD_ABOUTBOX                    100
#define IDS_ABOUTBOX                    101
#define IDD_MY01LISTTREE_DIALOG         102
#define IDR_MAINFRAME                   128
#define IDI_ICON1                       130
#define IDI_ICON2                       131
#define IDI_ICON3                       132
#define IDI_ICON4                       133
#define IDC_LIST1                       1000
#define IDC_TREE1                       1001
#define IDC_MFCSHELLTREE1               1002
#define IDC_MFCSHELLLIST1               1003

// Next default values for new objects
// 
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE        135
#define _APS_NEXT_COMMAND_VALUE         32771
#define _APS_NEXT_CONTROL_VALUE         1004
#define _APS_NEXT_SYMED_VALUE           101
#endif
#endif
cpp 复制代码
//01.ListTree.rc
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"

#define APSTUDIO_READONLY_SYMBOLS
/
//
// Generated from the TEXTINCLUDE 2 resource.
//
#ifndef APSTUDIO_INVOKED
#include "targetver.h"
#endif
#include "afxres.h"
#include "verrsrc.h"

/
#undef APSTUDIO_READONLY_SYMBOLS

/
// 中文(简体,中国) resources

#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED

#ifdef APSTUDIO_INVOKED
/
//
// TEXTINCLUDE
//

1 TEXTINCLUDE 
BEGIN
    "resource.h\0"
END

2 TEXTINCLUDE 
BEGIN
    "#ifndef APSTUDIO_INVOKED\r\n"
    "#include ""targetver.h""\r\n"
    "#endif\r\n"
    "#include ""afxres.h""\r\n"
    "#include ""verrsrc.h""\r\n"
    "\0"
END

3 TEXTINCLUDE 
BEGIN
    "#define _AFX_NO_SPLITTER_RESOURCES\r\n"
    "#define _AFX_NO_OLE_RESOURCES\r\n"
    "#define _AFX_NO_TRACKER_RESOURCES\r\n"
    "#define _AFX_NO_PROPERTY_RESOURCES\r\n"
    "\r\n"
    "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)\r\n"
    "LANGUAGE 4, 2\r\n"
    "#include ""res\\My01ListTree.rc2""  // 非 Microsoft Visual C++ 编辑的资源\r\n"
    "#include ""l.CHS\\afxres.rc""      // 标准组件\r\n"
    "#if !defined(_AFXDLL)\r\n"
    "#include ""l.CHS\\afxribbon.rc""   // MFC 功能区和控制条资源\r\n"
    "#endif\r\n"
    "#endif\r\n"
    "\0"
END

#endif    // APSTUDIO_INVOKED


/
//
// Icon
//

// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDR_MAINFRAME           ICON                    "res\\01.ListTree.ico"

IDI_ICON1               ICON                    "res\\1.ico"

IDI_ICON2               ICON                    "res\\2.ico"

IDI_ICON3               ICON                    "res\\3.ico"

IDI_ICON4               ICON                    "res\\4.ico"


/
//
// Dialog
//

IDD_ABOUTBOX DIALOGEX 0, 0, 170, 62
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "关于 01.ListTree"
FONT 9, "MS Shell Dlg", 0, 0, 0x1
BEGIN
    ICON            IDR_MAINFRAME,IDC_STATIC,14,14,21,20
    LTEXT           "01.ListTree,1.0 版",IDC_STATIC,42,14,114,8,SS_NOPREFIX
    LTEXT           "Copyright (C) 2018",IDC_STATIC,42,26,114,8
    DEFPUSHBUTTON   "确定",IDOK,113,41,50,14,WS_GROUP
END

IDD_MY01LISTTREE_DIALOG DIALOGEX 0, 0, 320, 200
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
EXSTYLE WS_EX_APPWINDOW
CAPTION "01.ListTree"
FONT 9, "MS Shell Dlg", 0, 0, 0x1
BEGIN
    CONTROL         "",IDC_LIST1,"SysListView32",LVS_REPORT | LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,136,7,177,72
    CONTROL         "",IDC_TREE1,"SysTreeView32",TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT | WS_BORDER | WS_HSCROLL | WS_TABSTOP,7,7,129,71
    CONTROL         "",IDC_MFCSHELLTREE1,"MfcShellTree",WS_BORDER | WS_HSCROLL | WS_TABSTOP,7,79,128,114
    CONTROL         "",IDC_MFCSHELLLIST1,"MfcShellList",WS_BORDER | WS_TABSTOP | 0x841,135,79,178,114
END


/
//
// Version
//

VS_VERSION_INFO VERSIONINFO
 FILEVERSION 1,0,0,1
 PRODUCTVERSION 1,0,0,1
 FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
 FILEFLAGS 0x1L
#else
 FILEFLAGS 0x0L
#endif
 FILEOS 0x40004L
 FILETYPE 0x1L
 FILESUBTYPE 0x0L
BEGIN
    BLOCK "StringFileInfo"
    BEGIN
        BLOCK "080404B0"
        BEGIN
            VALUE "CompanyName", "TODO: <公司名>"
            VALUE "FileDescription", "01.ListTree"
            VALUE "FileVersion", "1.0.0.1"
            VALUE "InternalName", "01.ListTree.exe"
            VALUE "LegalCopyright", "TODO:  (C) <公司名>。  保留所有权利。"
            VALUE "OriginalFilename", "01.ListTree.exe"
            VALUE "ProductName", "TODO: <产品名>"
            VALUE "ProductVersion", "1.0.0.1"
        END
    END
    BLOCK "VarFileInfo"
    BEGIN
        VALUE "Translation", 0x804, 1200
    END
END


/
//
// DESIGNINFO
//

#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
    IDD_ABOUTBOX, DIALOG
    BEGIN
        LEFTMARGIN, 7
        RIGHTMARGIN, 163
        TOPMARGIN, 7
        BOTTOMMARGIN, 55
    END

    IDD_MY01LISTTREE_DIALOG, DIALOG
    BEGIN
        LEFTMARGIN, 7
        RIGHTMARGIN, 313
        TOPMARGIN, 7
        BOTTOMMARGIN, 193
    END
END
#endif    // APSTUDIO_INVOKED


/
//
// AFX_DIALOG_LAYOUT
//

IDD_MY01LISTTREE_DIALOG AFX_DIALOG_LAYOUT
BEGIN
    0
END


/
//
// Dialog Info
//

IDD_MY01LISTTREE_DIALOG DLGINIT
BEGIN
    IDC_MFCSHELLTREE1, 0x37c, 88, 0
0x4d3c, 0x4346, 0x6853, 0x6c65, 0x546c, 0x6572, 0x4365, 0x7274, 0x5f6c, 
0x6e45, 0x6261, 0x656c, 0x6853, 0x6c65, 0x436c, 0x6e6f, 0x6574, 0x7478, 
0x654d, 0x756e, 0x463e, 0x4c41, 0x4553, 0x2f3c, 0x464d, 0x5343, 0x6568, 
0x6c6c, 0x7254, 0x6565, 0x7443, 0x6c72, 0x455f, 0x616e, 0x6c62, 0x5365, 
0x6568, 0x6c6c, 0x6f43, 0x746e, 0x7865, 0x4d74, 0x6e65, 0x3e75, 
    IDC_MFCSHELLLIST1, 0x37c, 88, 0
0x4d3c, 0x4346, 0x6853, 0x6c65, 0x4c6c, 0x7369, 0x4374, 0x7274, 0x5f6c, 
0x6e45, 0x6261, 0x656c, 0x6853, 0x6c65, 0x436c, 0x6e6f, 0x6574, 0x7478, 
0x654d, 0x756e, 0x463e, 0x4c41, 0x4553, 0x2f3c, 0x464d, 0x5343, 0x6568, 
0x6c6c, 0x694c, 0x7473, 0x7443, 0x6c72, 0x455f, 0x616e, 0x6c62, 0x5365, 
0x6568, 0x6c6c, 0x6f43, 0x746e, 0x7865, 0x4d74, 0x6e65, 0x3e75, 
    0
END


/
//
// String Table
//

STRINGTABLE
BEGIN
    IDS_ABOUTBOX            "关于 01.ListTree(&A)..."
END

#endif    // 中文(简体,中国) resources
/



#ifndef APSTUDIO_INVOKED
/
//
// Generated from the TEXTINCLUDE 3 resource.
//
#define _AFX_NO_SPLITTER_RESOURCES
#define _AFX_NO_OLE_RESOURCES
#define _AFX_NO_TRACKER_RESOURCES
#define _AFX_NO_PROPERTY_RESOURCES

#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
LANGUAGE 4, 2
#include "l.CHS\afxres.rc"      // 标准组件
#if !defined(_AFXDLL)
#include "l.CHS\afxribbon.rc"   // MFC 功能区和控制条资源
#endif
#endif

/
#endif    // not APSTUDIO_INVOKED
cpp 复制代码
// 01.ListTree.cpp : 定义应用程序的类行为。
//

#include "stdafx.h"
#include "01.ListTree.h"
#include "01.ListTreeDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// CMy01ListTreeApp

BEGIN_MESSAGE_MAP(CMy01ListTreeApp, CWinApp)
	ON_COMMAND(ID_HELP, &CWinApp::OnHelp)
END_MESSAGE_MAP()


// CMy01ListTreeApp 构造

CMy01ListTreeApp::CMy01ListTreeApp()
{
	// 支持重新启动管理器
	m_dwRestartManagerSupportFlags = AFX_RESTART_MANAGER_SUPPORT_RESTART;

	// TODO: 在此处添加构造代码,
	// 将所有重要的初始化放置在 InitInstance 中
}


// 唯一的一个 CMy01ListTreeApp 对象

CMy01ListTreeApp theApp;


// CMy01ListTreeApp 初始化

BOOL CMy01ListTreeApp::InitInstance()
{
	// 如果一个运行在 Windows XP 上的应用程序清单指定要
	// 使用 ComCtl32.dll 版本 6 或更高版本来启用可视化方式,
	//则需要 InitCommonControlsEx()。  否则,将无法创建窗口。
	INITCOMMONCONTROLSEX InitCtrls;
	InitCtrls.dwSize = sizeof(InitCtrls);
	// 将它设置为包括所有要在应用程序中使用的
	// 公共控件类。
	InitCtrls.dwICC = ICC_WIN95_CLASSES;
	InitCommonControlsEx(&InitCtrls);

	CWinApp::InitInstance();


	AfxEnableControlContainer();

	// 创建 shell 管理器,以防对话框包含
	// 任何 shell 树视图控件或 shell 列表视图控件。
	CShellManager *pShellManager = new CShellManager;

	// 激活"Windows Native"视觉管理器,以便在 MFC 控件中启用主题
	CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows));

	// 标准初始化
	// 如果未使用这些功能并希望减小
	// 最终可执行文件的大小,则应移除下列
	// 不需要的特定初始化例程
	// 更改用于存储设置的注册表项
	// TODO: 应适当修改该字符串,
	// 例如修改为公司或组织名
	SetRegistryKey(_T("应用程序向导生成的本地应用程序"));

	CMy01ListTreeDlg dlg;
	m_pMainWnd = &dlg;
	INT_PTR nResponse = dlg.DoModal();
	if (nResponse == IDOK)
	{
		// TODO: 在此放置处理何时用
		//  "确定"来关闭对话框的代码
	}
	else if (nResponse == IDCANCEL)
	{
		// TODO: 在此放置处理何时用
		//  "取消"来关闭对话框的代码
	}
	else if (nResponse == -1)
	{
		TRACE(traceAppMsg, 0, "警告: 对话框创建失败,应用程序将意外终止。\n");
		TRACE(traceAppMsg, 0, "警告: 如果您在对话框上使用 MFC 控件,则无法 #define _AFX_NO_MFC_CONTROLS_IN_DIALOGS。\n");
	}

	// 删除上面创建的 shell 管理器。
	if (pShellManager != NULL)
	{
		delete pShellManager;
	}

#ifndef _AFXDLL
	ControlBarCleanUp();
#endif

	// 由于对话框已关闭,所以将返回 FALSE 以便退出应用程序,
	//  而不是启动应用程序的消息泵。
	return FALSE;
}
cpp 复制代码
// 01.ListTreeDlg.cpp : 实现文件
//

#include "stdafx.h"
#include "01.ListTree.h"
#include "01.ListTreeDlg.h"
#include "afxdialogex.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// 用于应用程序"关于"菜单项的 CAboutDlg 对话框

class CAboutDlg : public CDialogEx
{
public:
	CAboutDlg();

// 对话框数据
#ifdef AFX_DESIGN_TIME
	enum { IDD = IDD_ABOUTBOX };
#endif

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

// 实现
protected:
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialogEx(IDD_ABOUTBOX)
{
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()


// CMy01ListTreeDlg 对话框



CMy01ListTreeDlg::CMy01ListTreeDlg(CWnd* pParent /*=NULL*/)
	: CDialogEx(IDD_MY01LISTTREE_DIALOG, pParent)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CMy01ListTreeDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_LIST1, m_list);
	DDX_Control(pDX, IDC_TREE1, m_tree);
	DDX_Control(pDX, IDC_MFCSHELLTREE1, m_mfcTree);
	DDX_Control(pDX, IDC_MFCSHELLLIST1, m_mfcList);
}

BEGIN_MESSAGE_MAP(CMy01ListTreeDlg, CDialogEx)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_NOTIFY(NM_CLICK, IDC_LIST1, &CMy01ListTreeDlg::OnNMClickList1)
	ON_NOTIFY(TVN_SELCHANGED, IDC_TREE1, &CMy01ListTreeDlg::OnTvnSelchangedTree1)
	ON_NOTIFY(NM_CLICK, IDC_TREE1, &CMy01ListTreeDlg::OnNMClickTree1)
END_MESSAGE_MAP()


// CMy01ListTreeDlg 消息处理程序

BOOL CMy01ListTreeDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// 将"关于..."菜单项添加到系统菜单中。

	// IDM_ABOUTBOX 必须在系统命令范围内。
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		BOOL bNameValid;
		CString strAboutMenu;
		bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
		ASSERT(bNameValid);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// 设置此对话框的图标。  当应用程序主窗口不是对话框时,框架将自动
	//  执行此操作
	SetIcon(m_hIcon, TRUE);			// 设置大图标
	SetIcon(m_hIcon, FALSE);		// 设置小图标

	// TODO: 在此添加额外的初始化代码
	InitImgList();
	InitList();
	InitTree();
	m_mfcTree.SetRelatedList(&m_mfcList);
	return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}

void CMy01ListTreeDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialogEx::OnSysCommand(nID, lParam);
	}
}

// 如果向对话框添加最小化按钮,则需要下面的代码
//  来绘制该图标。  对于使用文档/视图模型的 MFC 应用程序,
//  这将由框架自动完成。

void CMy01ListTreeDlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); // 用于绘制的设备上下文

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// 使图标在工作区矩形中居中
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// 绘制图标
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialogEx::OnPaint();
	}
}

//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CMy01ListTreeDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}

void CMy01ListTreeDlg::InitList()
{
	// 设置扩展风格  带网格  整行选中
	m_list.SetExtendedStyle(LVS_EX_GRIDLINES | LVS_EX_FULLROWSELECT);
	// 设置list的关联图标数组
	m_list.SetImageList(&m_img, LVSIL_SMALL);
	// 设置行列信息
	// 1. 先设置列标题
	m_list.InsertColumn(0, L"第1列", 0, 80);
	m_list.InsertColumn(1, L"第2列", 0, 80);
	m_list.InsertColumn(2, L"第3列", 0, 80);
	// 2. 再插入行信息   行标题  行内容
	for (int i=0;i<20;i++)
	{
		TCHAR szShow[20] = {};
		swprintf_s(szShow, 20, L"第%d行",i+1);
		// 行标题 
		m_list.InsertItem(i, szShow,i%4);
		// 行内容
		swprintf_s(szShow, 20, L"第%d行%d列", i + 1,1);
		m_list.SetItemText(i, 1, szShow);
		swprintf_s(szShow, 20, L"第%d行%d列", i + 1, 2);
		m_list.SetItemText(i, 2, szShow);
	}

}

void CMy01ListTreeDlg::InitImgList()
{
	// 每个icon的信息  大小等
	// 创建一成员为32*32大小使用32位色的icon数组,
	// 数组初始空间大小为4个,满了之后按1递增
	m_img.Create(32, 32, ILC_COLOR32, 4, 1);
	m_img.Add(AfxGetApp()->LoadIconW(IDI_ICON1));
	m_img.Add(AfxGetApp()->LoadIconW(IDI_ICON2));
	m_img.Add(AfxGetApp()->LoadIconW(IDI_ICON3));
	m_img.Add(AfxGetApp()->LoadIconW(IDI_ICON4));

}



void CMy01ListTreeDlg::OnNMClickList1(NMHDR *pNMHDR, LRESULT *pResult)
{
	LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
	// TODO: 在此添加控件通知处理程序代码
	*pResult = 0;
	CString str = m_list.GetItemText(pNMItemActivate->iItem, pNMItemActivate->iSubItem);
	MessageBox(str.GetBuffer());
}

void CMy01ListTreeDlg::InitTree()
{
	// 设置关联图标
	m_tree.SetImageList(&m_img, TVSIL_NORMAL);
	// 1级节点
	HTREEITEM hParent = m_tree.InsertItem(
		L"SDK",// 插入文本
		0,// 正常情况下显示的图标在数组中的索引
		3,// 该节点被点击的时候显示的图标在数组中的索引
		TVI_ROOT,// 父节点
		TVI_LAST// 插入方式
	);
	// 2级节点
	m_tree.InsertItem(L"SDK001", 1,3,hParent, TVI_LAST);
	m_tree.InsertItem(L"SDK002", 2,3,hParent, TVI_LAST);
	// 1级节点
	hParent = m_tree.InsertItem(L"MFC", 0,3,TVI_ROOT, TVI_LAST);
	m_tree.InsertItem(L"MFC001", 1, 3, hParent, TVI_LAST);
	m_tree.InsertItem(L"MFC002", 2, 3, hParent, TVI_LAST);
}


void CMy01ListTreeDlg::OnTvnSelchangedTree1(NMHDR *pNMHDR, LRESULT *pResult)
{
	LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
	// TODO: 在此添加控件通知处理程序代码
	*pResult = 0;
	m_tree.Invalidate();
}


void CMy01ListTreeDlg::OnNMClickTree1(NMHDR *pNMHDR, LRESULT *pResult)
{
	// TODO: 在此添加控件通知处理程序代码
	*pResult = 0;
	CPoint pt;
	GetCursorPos(&pt);
	// 屏幕坐标转客户区坐标 
	m_tree.ScreenToClient(&pt);
	UINT uFlags = 0;
	//TVHT_ONITEMLABEL 
	HTREEITEM hTree  = m_tree.HitTest(pt, &uFlags);
	if (uFlags == TVHT_ONITEMLABEL || 
		uFlags == TVHT_ONITEMICON)
	{
		CString str = m_tree.GetItemText(hTree);
		MessageBox(str);
	}
	
}

运行效果:

相关推荐
王禄DUT几秒前
相似度计算 第33次CCF-CSP计算机软件能力认证
开发语言·c++
Lzc7749 分钟前
C++进阶——位图+布隆过滤器+海量数据处理
c++·位图+布隆过滤器+海量数据处理
Felven11 分钟前
A. Olympiad Date
数据结构·c++·算法
努力学习的小廉13 分钟前
【C++】 —— 笔试刷题day_12
开发语言·c++
四维碎片16 分钟前
【Qt】数据库管理
数据库·c++·qt
·前路漫漫亦灿灿31 分钟前
C++_STL之list篇
开发语言·c++
清水白石00843 分钟前
STL性能优化实战:如何让C++程序畅快运行
开发语言·c++·性能优化
学习同学1 小时前
C++ 初阶总复习 (16~30)
开发语言·c++
Yvsanf1 小时前
C++细节知识for面试
开发语言·c++
郭涤生2 小时前
全书测试:《C++性能优化指南》
开发语言·c++·笔记·性能优化