27win32编程基础——通用控件ListView的使用和通用控件的消息传递

这些常用的控件,叫标准控件。 

其他不常用的控件,叫做通用控件,就放在一个dll中,windows通用控件,放在Comctl32.dll中使用的时候,要在文件头加

#include<commctrl.h>
#pragma comment(lib,"comctl32.lib")

在vc6低版本中,在使用通用控件之前还要加代码

INITCOMMONCONTROLSEX icex;
icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
icex.dwICC = ICC_WIN95_CLASSES;
InitCOmmonControlsEx(&icex);

对控件使用初始化操作,vs2010版本中都不用加初始化代码,只用加头文件的2句代码即可。

一、以ListView举例用法:

#include <windows.h>
#include "resource.h"
#include<commctrl.h>
#pragma comment(lib,"comctl32.lib")

HINSTANCE hIns;
INT_PTR CALLBACK DialogProc(HWND hwndDlg,UINT uMsg,  WPARAM wParam,LPARAM lParam);

int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
	hIns = hInstance;
	DialogBox(hIns,MAKEINTRESOURCE(IDD_DIALOG1),NULL,DialogProc);
    return 0;
}

void InitListView(HWND hwndDlg){
			LVCOLUMN lvc;
			HWND HlistV=GetDlgItem(hwndDlg,IDC_LIST2);

			//
			//设置ListView的风格,点击就会整行选中
			SendMessage(HlistV, LVM_SETEXTENDEDLISTVIEWSTYLE,LVS_EX_FULLROWSELECT,LVS_EX_FULLROWSELECT);
			//相当于宏,SendMessage相当于宏ListView_SetExtendedListViewStyle(HlistV,LVS_EX_FULLROWSELECT)

			//第一列
			lvc.mask = LVCF_TEXT | LVCF_WIDTH|LVCF_SUBITEM;
			lvc.pszText = TEXT("进程");	//列标题
			lvc.cx = 80;				//列宽
			lvc.iSubItem =0;			//第0列
			SendMessage(HlistV, LVM_INSERTCOLUMN, 0, (DWORD)&lvc);
			//第2列
			lvc.pszText = TEXT("PID");
			lvc.cx = 60;
			lvc.iSubItem =1;	
			SendMessage(HlistV, LVM_INSERTCOLUMN, 1, (long)&lvc);
			//第3列
			lvc.mask = LVCF_TEXT | LVCF_WIDTH|LVCF_SUBITEM;;
			lvc.pszText = TEXT("镜像基址");
			lvc.cx = 60;
			lvc.iSubItem =2;
			//SendMessage(HlistV, LVM_INSERTCOLUMN, 2, (long)&lvc);
			ListView_InsertColumn(HlistV,2, (long)&lvc);
			//第4列
			lvc.pszText = TEXT("镜像大小");
			lvc.cx = 60;
			lvc.iSubItem =3;
			//SendMessage(HlistV, LVM_INSERTCOLUMN, 3, (long)&lvc);
			ListView_InsertColumn(HlistV,3, (long)&lvc);

			//设置背景颜色
			SendMessage(hwndDlg, LVM_SETTEXTCOLOR, 0, RGB(255, 255, 255));
			SendMessage(hwndDlg, LVM_SETBKCOLOR, 0, RGB(135, 160, 135));
			SendMessage(hwndDlg, LVM_SETTEXTBKCOLOR, 0, RGB(60, 100, 130));			
			
		
struct STUDENTINFO  
	{  
    	TCHAR name[15];  
    	TCHAR age[4];  
    	TCHAR dept[20]; 
    	TCHAR job[20]; 
	};
			 STUDENTINFO stu[6] = {  
    { TEXT("无忌"), TEXT("20"),TEXT("技术部"), TEXT("工程师") },  
    { TEXT("三丰"), TEXT("80"), TEXT("总经理"), TEXT("总经理") },  
    { TEXT("远桥"), TEXT("40"), TEXT("技术部"), TEXT("经理") },  
    { TEXT("敏敏"), TEXT("18"), TEXT("客服部"), TEXT("经理") },  
    { TEXT("芷若"),  TEXT("18"), TEXT("行政部"), TEXT("经理") },  
    { TEXT("小昭"),  TEXT("16"), TEXT("经理"), TEXT("前台") }  
	};	
			//往里面填充内容,需要结构体LVITEM
			LVITEM vitem; 
		 	vitem.mask = LVIF_TEXT;  //填入文本
		    for (int i = 0; i < 6; i++)  
		    {  
				vitem.iItem = i;  //第几行填充内容

		        //先添加项再设置子项内容   
		        vitem.iSubItem = 0;  //第几列
				vitem.pszText = stu[i].name; 
		        ListView_InsertItem(HlistV, &vitem);  //只有第1列使用的是ListView_InsertItem,后边都是ListView_SetItem
				//SendMessage(HlistV, LVM_INSERTITEM, 2, (long)&vitem);

		        // 设置子项  
		        vitem.iSubItem = 1;  
		        vitem.pszText = stu[i].age;  
		        ListView_SetItem( HlistV, &vitem);  //宏,可以F12看一下,和SendMessag是一样的

		        vitem.iSubItem = 2;  
		        vitem.pszText = stu[i].dept;  
		        //ListView_SetItem(HlistV, &vitem);
				SendMessage(HlistV, LVM_SETITEM, 2, (long)&vitem);//必须使用LVM_SETITEM,只有第一列是使用LVM_INSERTITEM
				//SendMessage(HlistV, LVM_INSERTITEM, 2, (long)&vitem);//

				vitem.iSubItem = 3;  
		        vitem.pszText = stu[i].job;  
		        ListView_SetItem(HlistV, &vitem);  
		    }  
};

void EnumModules(HWND hwnd,WPARAM wParam,LPARAM lParam){
	DWORD dwRowId;
	TCHAR	szPid[0x20];
	LVITEM lv;
	//初始化结构
	memset(&lv,0,sizeof(LVITEM));
	memset(szPid,0,0x20);
	//获取选择的行,也可以使用ListView_GetNextItem(hwnd,LVNI_SELECTED   )
	dwRowId = SendMessage(hwnd,LVM_GETNEXTITEM,-1,LVNI_SELECTED);
	dwRowId = ListView_GetNextItem(hwnd,-1,LVNI_SELECTED);
	//dwRowId =ListView_GetNextItem(hwnd,-1,LVM_GETNEXTITEM); 


	if(dwRowId==-1)
	{
		MessageBox(NULL,TEXT("请选择进程"),TEXT("出错啦"),MB_OK);
		return;
	}
	//获取选择的行中,pid这一列的内容
	lv.iSubItem = 1;
	lv.pszText = szPid;
	lv.cchTextMax = 0x20;
	SendMessage(hwnd,LVM_GETITEMTEXT,dwRowId,(DWORD)&lv);
	MessageBox(NULL,szPid,TEXT("PID"),MB_OK);
};

INT_PTR CALLBACK DialogProc(HWND hwndDlg,UINT uMsg,  WPARAM wParam,LPARAM lParam){

	HICON hicBig;
	switch(uMsg){
	case WM_CLOSE:
		{
			EndDialog(hwndDlg,0);
			break;
		}
	case WM_INITDIALOG:
		{
		 hicBig = LoadIcon(hIns, MAKEINTRESOURCE(IDI_ICON1));
		 SendMessage(hwndDlg,WM_SETICON,ICON_BIG,DWORD(hicBig));
		 SendMessage(hwndDlg,WM_SETICON,ICON_SMALL,DWORD(hicBig));
		 InitListView(hwndDlg);
		 break;
		}
	case WM_COMMAND:
		switch(LOWORD(wParam))
		{
			case IDC_BUTTON_PE:
				return true;
			
			case IDC_BUTTON_ABOUT:
				return true;
			case IDC_BUTTON_EXIT:
				EndDialog(hwndDlg,0);
				return true;
		}
		break;
	case WM_NOTIFY:
		//当时WM_NOTIFY的时候lParam指向NMHDR结构体
		NMHDR* pNMHDR = (NMHDR*)lParam;
		//判断是否是控件ListView和点击了ListView
		if(wParam == IDC_LIST2 && pNMHDR->code==NM_CLICK)
		{
			EnumModules(GetDlgItem(hwndDlg,IDC_LIST2),wParam,lParam);
		}
		break;
	}

	return FALSE;
};

    列表视图控件是一种非常常用的控件,在需要以报表形式显示数据时,列表控件通常是最好的选择,许多专用的数据报表控件,也是在它的基础上派生而来。与树视图类似,列表控件可以由多个子项目组成,可以设置为Icon(大图标)、SmallIcon(小图标)、List(列表)或Report(报表)。

一、列表视图控件有两个重要的数据结构LVCOLUMN和LVITEM。LVCOLUMN用于定义报表方式下的“列”的结构;LVITEM用于定义“项”的结构。这两个结构的定义及说明如下:

typedef struct _LVCOLUMN {
UINT mask;            说明此结构中哪些成员是有效的
int fmt;                  列的对齐方式
int cx;                    列的初始宽度
LPTSTR pszText;     列的标题
int cchTextMax;      pszText所指向的缓冲区的大小
int iSubItem;         与列关联的子项的索引值,从0开始
int iImage;            与列关联的图像列表中指定图像的索引值
int iOrder;             第几列,0代表最左一列
} LVCOLUMN, FAR LPLVCOLUMN;
-----------------------------------
typedef struct _LVITEM {
UINT   mask;          说明LVITEM结构中哪些成员有效
int    iItem;             项目的索引值(可以视为行号)从0开始
int    iSubItem;      子项的索引值(可以视为列号)从0开始
UINT   state;          子项的状态
UINT   stateMask;   状态有效的屏蔽位
LPTSTR pszText;    主项或子项的名称
int    cchTextMax;  pszText所指向的缓冲区大小
int    iImage;         关联图像列表中指定图像的索引值
LPARAM lParam;    程序定义的32位参数
int iIndent;            表示图像位置缩进的单位
} LVITEM, FAR LPLVITEM;

  

二、相关操作。因为是SDK编程,所以对控件的操作是向控件发送SendMessage()来实现的
LISTVIEW中的相关消息为:
1、LVM_SETTEXTCOLOR 和 LVM_SETTEXTBKCOLOR和 LVM_SETBKCOLOR   //消息设定文本的前景和背景色,wParam 为0,lParam 为颜色的RGB值
2、 LVM_GETNEXTITEM  //找到选中的行,对应ListView_GetNextItem宏将SendMessage打包为函数方式操作。
3、LVM_SETCOLUMNWIDTH  //设置列宽,对应ListView_SetColumnWidth
4、LVM_SETEXTENDEDLISTVIEWSTYLE  //设置扩展风格如:LVS_EX_FULLROWSELECT(选中一整行), LVS_EX_GRIDLINES(网络线),LVS_EX_CHECKBOXES(选择按钮),对应ListView_SetExtendedListViewStyle
5、LVM_INSERTCOLUMN  //插入新列,对应ListView_InsertColumn,wParam 为整型,指定列号,lParam 为指向LV_COLUMN结构的指针
6、LVM_SETCOLUMN  //设置列,参数同上
7、LVM_INSERTITEM  //插入项目(行),对应ListView_InsertItem,加入项目或子项目,wParam 为0,lParam 为指向LV_ITEM结构的指针
8、LVM_SETITEM  //设置子项(行中的每列),对应ListView_SetItem,设置项目或子项目,参数同上
9、LVM_GETITEM  //取得项目或子项目,参数同上
10、LVM_GETITEMCOUNT  //获取项数,对应ListView_GetItemCount
11、LVM_GETNEXTITEM  取得下一个项目或子项目,可以用来取得光标选择的项目
12、LVM_DELETEITEM  //删除项,对应ListView_DeleteItem,删除项目或子项目,wParam 为整型,指定项目索引号,lParam 为0
13、LVM_DELETEALLITEMS  //删除所有项目,wParam 和 lParam 均为0
三、ListCtrl控件的扩展样式
LVS_EX_GRIDLINES //绘制表格线
LVS_EX_SUBITEMIMAGES//子项目图标列表
LVS_EX_CHECKBOXES //带复选框
LVS_EX_TRACKSELECT //自动换行
LVS_EX_HEADERDRAGDROP//报表头可以拖拽
LVS_EX_FULLROWSELECT //选择整行
LVS_EX_ONECLICKACTIVATE//单击激活
LVS_EX_TWOCLICKACTIVATE//双击激活
LVS_EX_FLATSB//扁平滚动条
LVS_EX_REGIONAL
LVS_EX_INFOTIP
LVS_EX_UNDERLINEHOT
LVS_EX_UNDERLINECOLD
LVS_EX_MULTIWORKAREAS//多工作区

 二、LiveView等通用控件的消息,不再是使用WM_COMMAND而是WM_NOTIFY

点击ListView中不同的位置,应该如何处理这种消息呢?

之前的子窗口是通过WM_COMMAND转向父窗口发送的。

但是像ListView这种复杂控件就不能这样的,因此不同的位置,包含的消息信息比较多,使用W_COMMAND,不能包含复杂的消息信息,就产生了WM_NOTIFY消息。

WM_NOTIFY消息与WM_COMMAND类似,都是由子窗口向父窗口发送的消息。

但是WM_NOTIFY包含的消息信息比WM_COMMAND更多、更丰富

Windows中通用组件中很多消息,都是通过WM_NOFITY来描述的,而不是使用WM_COMMAND

当为WM_NOTIFY消息的时候,WPARAM wParam是控件ID,LPARAM lParam指向一个消息扩充的结构体:NMHDR、NMLVCACHEHINT 、NMLVDISPINFO、NMLVFINDITEM

typedef struct tagNMHDR {				
    HWND hwndFrom;			//发送消息通知的控制窗口句柄	
    UINT_PTR idFrom;			//发送通知消息的控制ID值	
    UINT code;			//通知码,做的什么事情,左键还是右键,选中,例如WM_SELCHANGED	
} NMHDR;				
				
如果这些消息描述的信息内容还不够,windows还有扩充了另外一些消息结构				
				
typedef struct tagNMLVCACHEHINT {				
    NMHDR hdr;				像不像继承,这就是c语言写的继承的方法
    int iFrom;				
    int iTo;				
} NMLVCACHEHINT, *PNMLVCACHEHINT;				
				
typedef struct tagNMLVDISPINFO {				
    NMHDR hdr;				
    LVITEM item;				
} NMLVDISPINFO;				
				
typedef struct _NMLVFINDITEM {				
    NMHDR hdr;				
    int iStart;				
    LVFINDINFO lvfi;				
} NMLVFINDITEM, *PNMLVFINDITEM;				

 例如:

NMLVDISPINFO 是 Windows API 中的一个消息类型,用于在列表视图控件(如 ListView)中显示信息。它通常用于自定义列表视图项的显示方式。

在编程中使用 NMLVDISPINFO 消息,你需要按照以下步骤进行:

包含头文件 windows.h 以访问所需的 API。
创建一个消息处理函数,该函数将处理 NMLVDISPINFO 消息。函数签名应如下所示:
c++
void OnDisplayInfo(NMLVDISPINFO* pDispInfo);
在你的代码中,使用 SetWindowLong 或 SetWindowLongPtr 函数将该消息处理函数与 NMLVDISPINFO 消息关联起来。例如: c++
HWND hwnd = CreateWindowEx(0, L"MyWindowClass", L"NMLVCACHEHINT Example", WS_OVERLAPPEDWINDOW, 0, 0, 300, 300, nullptr, nullptr, nullptr, nullptr);//先不定义回调函数,然后使用SetWindowLong定义回调函数。 SetWindowLong(m_hWnd, GWL_WNDPROC, OnDisplayInfo); 在消息处理函数中,解析 NMLVDISPINFO 结构以获取有关消息的信息。你需要关注以下字段: hdr:消息的头部信息,包括消息类型和其他信息。 item:LVITEM 结构,表示要显示的项目信息。它包含了文本、图像、状态等信息。你可以使用 item.pszText 获取文本信息,并根据需要修改其他字段。 iItem:要显示的项目索引。 iSubItem:要显示的子项索引。如果你的列表视图只包含一个列,则该字段通常为 0。 根据需要自定义项目的显示方式。你可以修改 item.pszText 字段来改变文本的显示内容,或者根据其他字段的值来自定义其他显示属性。 返回 TRUE 以指示消息已被处理。如果你返回 FALSE,则消息将被传递给下一个窗口处理函数。 以下是一个简单的示例代码片段,展示了如何使用 NMLVDISPINFO 消息自定义列表视图项的显示方式: c++ #include <windows.h> LRESULT CALLBACK OnDisplayInfo(NMLVDISPINFO* pDispInfo) { // 获取消息头部信息 const NMHDR& hdr = pDispInfo->hdr; // 获取要显示的项目信息 const LVITEM& item = pDispInfo->item; TCHAR szText[256]; // 假设文本不超过 256 个字符 // 根据需要修改项目的显示方式 switch (item.iSubItem) { case 0: // 修改第一列的显示内容 if (item.iItem % 2 == 0) { _tcscpy_s(szText, _T("Modified Text ")); _tcscat_s(szText, _T("Item ")); _tcscat_s(szText, item.pszText); } else { _tcscpy_s(szText, item.pszText); } break; default: // 其他子项的显示方式保持不变 _tcscpy_s(szText, item.pszText); break; } // 设置显示文本并返回 TRUE 表示消息已处理 ListView_SetItemText(pDispInfo->hdr.hwndFrom, item.iItem, item.iSubItem, szText); return TRUE; }

  

 

 

posted @ 2023-10-30 16:12  一日学一日功  阅读(523)  评论(0编辑  收藏  举报