在本专栏上一篇文章中带领大家学习了对话框的创建,并且在项目中创建出了对话框。在这一篇文章中,我将带领大家学习Win32通用控件,了解_WM_NOTIFY
消息,并且带领大家初步写出课程中加载Windows所有进程的应用程序的雏形,带领大家详解其中的原理。
文章目录
- 一.标准控件与通用控件
- 二.WM_INITDIALOG消息
- 三.WM_NOTIFY消息
- 1.WM_NOTIFY消息的使用
- 2.WM_NOTIFY消息参数
- 3.NMHDR结构
- 四.加载Windows进程应用程序项目初步
- 1. 我们首先画出对话框界面:
- 2. 然后我们来写出应用程序入口函数:
- 使用通用控件的向前声明:
- 1. INITCOMMONTROLSEX结构体:
- 2.`InitCommonControlsEx`函数
- 3.主对话框的回调函数
- 4.初始化进程窗口函数:
- 5.初始化模块窗口函数:
- `ListView——Insertcolumn`宏
- ` LVCOLUMN 结构`:
- 6.向列表中加假的进程
- `LVM_INSERTITEM`消息
- `LVM_SETITEM`消息
- `LVITEMA` 结构
- 7.向模块列表中加入假的模块数据
- 三.加载Windows进程应用程序项目初步完整代码
一.标准控件与通用控件
Windows中有很多控件,有一些控件是我们不需要加载的,使用频率很高我们称为标准控件,有一些使用频率不是很高,我们在使用的时候需要加载,我们称为通用控件。
标准控件:
Static
Group Box
Button
CHeck Box
Radio Box
Edit
ComboBox
ListBox
Windows通用控件,包含在commctrl32.dll
中,使用前需要:
#include <commctrl.h>
#pragma comment(lib,"comctl32.lib")
通用控件包括:
Animation
ComboBoxEx
Drag_List_Box
Flat_Scroll_bar
Header
HotKey
ImageList
IPAddress
List_View
Month_Calendar
Pager
Progress_Bar
Property_Sheets
Rebar
Status Bars
SysLink
Tab
Toolbar
Trackbar
TreeView
Up_and_Down
特别说明:
通过用控件在使用前,需要通过INITCOMMONCONTROLSEX
进行初始化。 只要在你的程序中任意地方使用了该函数,就会使得Windows的程序加载器PE Loader加载该库。
INITCOMMONCONTROLSEX icex;
icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
icex.dwICC = ICC_WIN95_CLASSES;
InitCOmmonControlsEx(&icex);
二.WM_INITDIALOG消息
MSDN官方文档;WM_INITDIALOG消息
#define WM_INITDIALOG 0x0110
发送时间:在对话框显示之前,发送到对话框回调函数。
参数:
· wParem:用于接收默认键盘焦点的控件的句柄。 仅当对话框过程返回 TRUE 时,系统才分配默认键盘焦点。
lParam:其他初始化数据。
三.WM_NOTIFY消息
1.WM_NOTIFY消息的使用
该消息类型与WM_COMMAND类型相似,都是由子窗口向父窗口发送的消息。
WM_NOTIFY消息可以包含比WM_COMMAND更为丰富的信息。
Windows中有很多通用控件的消息,都是通过WM_NOTIFY来描述的。
2.WM_NOTIFY消息参数
MSDN官方文档:WM_NOTIFY消息
- 发送时间:当发生事件或控件需要一些信息时,由公共控件发送到父窗口。
- 参数:
wParam:发送消息的公用控件的标识符。
lParam:指向包含通知代码和其他信息的NMHDR的指针。 - 注意:
消息的目标必须是控件父级的HWND.
3.NMHDR结构
typedef struct tagNMHDR{HWNDhwndFrom; //发送通知消息的控件窗口句柄UINT idFrom; //发送通知消息的控件IDUINT code; //通知代码
};
这个结构体能满足一般的需求,但能描述的信息任然是有限的。
解决方案:对每一种不同用途的通知消息都定义一种结构体来表示:
四.加载Windows进程应用程序项目初步
这一章开始,带领大家开发一个加载Windows进程的EXE,其中包括:加载Windows当前的所有进程,包括进程名,PID,镜像地址,镜像大小,并且再单击进程的时候,加载该进程所有的模块。
本篇文章将会一步一步带领大家写出基本的代码,在最后给出完整的代码。在项目开发完毕后,我会发布完整代码。
1. 我们首先画出对话框界面:
2. 然后我们来写出应用程序入口函数:
#include "framework.h"
#include "PEProcess.h"
#include <CommCtrl.h>
#pragma comment(lib,"comctl32.lib") //需要使用通用控件
HINSTANCE hIns = 0;//入口函数
int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow
) {hIns = hInstance;//使用通用控件的向前声明INITCOMMONCONTROLSEX icex;icex.dwSize = sizeof(INITCOMMONCONTROLSEX);icex.dwICC = ICC_WIN95_CLASSES;InitCommonControlsEx(&icex);DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG_MAIN), NULL, (DLGPROC)MainDlgProc); //加载主对话框return 0;
}
使用通用控件的向前声明:
1. INITCOMMONTROLSEX结构体:
这里我们使用到了INITCOMMONCONTROLSEX
结构体,我们来看看这个结构体:
MSDN官方文档:INITCOMMONTROLSEX结构体
typedef struct tagINITCOMMONCONTROLSEX {DWORD dwSize;DWORD dwICC;
} INITCOMMONCONTROLSEX, *LPINITCOMMONCONTROLSEX;
该结构通常用于从动态链接库加载常见控件类信息。
参数说明:
dwSize:结构大小(以字节为单位)
dwICC:指向将从DLL加载哪些常见控件类的位标志集。
2.InitCommonControlsEx
函数
MSDN官方文档:InitCOmmonControlsEx函数
BOOL InitCOmmonControlsEx([in] const INITCOMMONCONTROLSEX *pocce
);
函数说明:
函数功能:确保加载公共控件(Comctl32),并从该DLL注册特定的公共控件类
参数说明:
指向INITCOMMONCONTROLSEX结构体,该结构包含指定将注册哪些控件类信息。
返回值:
成功返回TRUE,失败返回FALSE.
在写入了入口函数,并且加载了主对话框之后,我们运行,发现程序页面已经出来了:
3.主对话框的回调函数
我们应该想到:
- 在对话框显示之前,需要初始化对话框,需要我们将列名等信息全部初始化
- 在对话框显示之前,发送的消息为
WM_INITDIALOG
,初始化的工作应该在这个消息内完成 - 由于初始化的过程比较复杂,我这里对初始化进程窗口和初始化模块窗口分别封装了函数处理
OOL CALLBACK MainDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {BOOL nRet = FALSE;switch (uMsg) {case WM_CLOSE: {EndDialog(hDlg, 0);PostQuitMessage(0);break;}case WM_INITDIALOG: {InitProcessListView(hDlg); //设置ProcessListView的风格break;}case WM_COMMAND: {switch (LOWORD(wParam)) {case IDC_BUTTON_ABOUT: {DialogBox(hIns, MAKEINTRESOURCE(IDD_ABOUTBOX), NULL, NULL);}case IDC_BUTTON_PE: {//打开新的对话框,PE查看器return 0;}case IDC_BUTTON_OUT: {EndDialog(hDlg, 0);return TRUE;}}}}return nRet;
}
4.初始化进程窗口函数:
VOID InitProcessListView(HWND hDlg) {//设置窗口风格的话调用了结构体LV_COLUMN lv;HWND hListProcess;//初始化memset(&lv, 0, sizeof(LV_COLUMN));//获取IDC_LIST_PROCESS句柄hListProcess = GetDlgItem(hDlg, IDC_LIST3);//设置整行选中SendMessage(hListProcess, LVM_GETEXTENDEDLISTVIEWSTYLE, LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT);//第一列:lv.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM;lv.pszText = (LPWSTR)TEXT("进程"); //列标题lv.cx = 200; //行宽lv.iSubItem = 0;//ListView_InsertColumn(hListProcess,0,&lv);SendMessage(hListProcess, LVM_INSERTCOLUMN, 0, (DWORD)&lv);//EnumProcess(hLostProcess);//第二列lv.pszText = (LPWSTR)TEXT("PID");lv.cx = 75;lv.iSubItem = 1;//ListView_InsertColumn(hListProcess, 1, &lv);SendMessage(hListProcess, LVM_INSERTCOLUMN, 1, (DWORD)&lv);//第三列lv.pszText = (LPWSTR)TEXT("镜像基址");lv.cx = 150;lv.iSubItem = 2;//ListView_InsertColumn(hListProcess, 2, &lv);SendMessage(hListProcess, LVM_INSERTCOLUMN, 2, (DWORD)&lv);//第三列lv.pszText = (LPWSTR)TEXT("镜像大小");lv.cx = 174;lv.iSubItem = 3;//ListView_InsertColumn(hListProcess, 3, &lv);SendMessage(hListProcess, LVM_INSERTCOLUMN, 3, (DWORD)&lv);
}
5.初始化模块窗口函数:
OID InitMoudleListView(HWND hDlg) {//设置窗口风格需要调用结构体LV_COLUMN lv;HWND hListMoudles;//初始化memset(&lv, 0, sizeof(LV_COLUMN));//获取模块列表句柄hListMoudles = GetDlgItem(hDlg, IDC_LIST_MOUDLE);//设置整行选中SendMessage(hListMoudles, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT);//第一列:lv.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM;lv.pszText = (LPWSTR)TEXT("模块名称");lv.cx = 400;lv.iSubItem = 0;//ListView_Insertcolumn(hListMoudles,0,&lv);SendMessage(hListMoudles, LVM_INSERTCOLUMN, 0, (DWORD)&lv);//第二列:lv.pszText = (LPWSTR)TEXT("模块位置");lv.cx = 400;lv.iSubItem = 1;SendMessage(hListMoudles, LVM_INSERTCOLUMN, 0, (DWORD)&lv);
}
我们可以发现,在初始化进程窗口和初始化模块窗口函数中,我们先写好了我们想要显示的标题,之后使用发送消息的方式使内容显示。这里我注释掉了一个,实际上这两种方式没有什么区别,都能使内容显示。
我们来看看ListView——Insertcolumn
宏:
ListView——Insertcolumn
宏
MSDN官方文档:ListView——Insertcolumn宏
void ListView_InsertColumn(hwnd,iCol,pcol
);
- 功能:从列表视图控件中插入新列
- 参数:
- hwnd:列表视图控件的句柄。
- iCol:新列的索引。
- pcol:指向包含新列属性的 LVCOLUMN 结构的指针。
LVCOLUMN 结构
:
MSDN官方文档:LVCOLUMN 结构
包含有关报表视图中的列的信息。
这个结构体大家到微软文档中自行查看吧,解释起来真的很费劲。
6.向列表中加假的进程
由于我们还没有学习如何加载操作系统中的所有进程,所以今天带领大家向列表中加载假的进程数据,有关如何加载操作系统真正的进程,后续会为大家讲解。
//加载进程函数
VOID EnumProcess(HWND hListProcess) {LV_ITEM vitem;//初始化,第一个进程memset(&vitem, 0, sizeof(LV_ITEM));vitem.mask = LVIF_TEXT;//假数据:vitem.pszText = (LPWSTR)TEXT("csrss.exe");vitem.iItem = 0;vitem.iSubItem = 0;//ListView_Insertem(hListProcess,*vitem);SendMessage(hListProcess, LVM_INSERTITEM, 0, (DWORD)&vitem);vitem.pszText = (LPWSTR)TEXT("448");vitem.iItem = 0;vitem.iSubItem = 1;SendMessage(hListProcess, LVM_SETITEM, 0, (DWORD)&vitem);//ListView_SetItem(hListProcess, &vitem);vitem.pszText = (LPWSTR)TEXT("56590000");vitem.iItem = 0;vitem.iSubItem = 2;ListView_SetItem(hListProcess, &vitem);vitem.pszText = (LPWSTR)TEXT("000F0000");vitem.iItem = 0;vitem.iSubItem = 3;ListView_SetItem(hListProcess, &vitem);//第二个进程假数据:vitem.pszText = (LPWSTR)TEXT("QQ.exe");vitem.iItem = 1;vitem.iSubItem = 0;SendMessage(hListProcess, LVM_INSERTITEM, 0, (DWORD)&vitem);vitem.pszText = (LPWSTR)TEXT("153");vitem.iItem = 1;vitem.iSubItem = 1;ListView_SetItem(hListProcess, &vitem);vitem.pszText = (LPWSTR)TEXT("65580000");vitem.iItem = 1;vitem.iSubItem = 2;ListView_SetItem(hListProcess, &vitem);vitem.pszText = (LPWSTR)TEXT("001E0000");vitem.iItem = 1;vitem.iSubItem = 3;ListView_SetItem(hListProcess, &vitem);//第三个进程假数据:vitem.pszText = (LPWSTR)TEXT("WeChat.exe");vitem.iItem = 2;vitem.iSubItem = 0;SendMessage(hListProcess, LVM_INSERTITEM, 0, (DWORD)&vitem);vitem.pszText = (LPWSTR)TEXT("256");vitem.iItem = 2;vitem.iSubItem = 1;ListView_SetItem(hListProcess, &vitem);vitem.pszText = (LPWSTR)TEXT("75960000");vitem.iItem = 2;vitem.iSubItem = 2;ListView_SetItem(hListProcess, &vitem);vitem.pszText = (LPWSTR)TEXT("015B0000");vitem.iItem = 2;vitem.iSubItem = 3;ListView_SetItem(hListProcess, &vitem);
}
这里加载了一些假的数据。
这里有个需要尤其注意的地方: 就是在列表中显示我们加入的数据的时候,只有在第一个,我们使用SendMessage
函数的时候,发送了LVM_INSERTITEM
类型的消息,使用宏的时候使用了ListView_Insertem
宏,在后续显示数据的时候,我们都是用的是LVM_SETITEM
类型的消息,或者是使用了ListView_SetItem
宏,这里要尤其注意,如果使用错误的话,是不能显示的。
我们来看看这两种消息的区别:
LVM_INSERTITEM
消息
MSDN官方文档:LVM_INSERTITEM消息
- 发送时间:在列表视图控件中插入新项。
- 附加信息:
- wParam:必须为0.
- lParam:指向指定列表视图项属性的 LVITEM 结构的指针。
LVM_SETITEM
消息
MSDN官方文档:LVSETITEM消息
- 发送时间:设置列表视图项的某些或全部属性。 还可以发送LVM_SETITEM来设置子项的文本
- 附加信息:
- wParam:必须为0.
- lParam:指向包含新项属性的 LVITEM 结构的指针
注意两者区别为在列表视图控件中插入新项和添加子项。
LVITEMA
结构
MSDN官方文档:LVITEMA结构
结构用途:用于指定或接收列表视图项的属性。
这个结构由于用法很多,大家自行到MSDN官方文档中查阅。
7.向模块列表中加入假的模块数据
这个函数与老师上课讲的完全一致,但是并非真的添加了数据:
VOID EnumMoudles(HWND hListProcess, WPARAM wParam, LPARAM lParam) {DWORD dwRowId;TCHAR szPid[21];LV_ITEM lv;//初始化memset(&lv, 0, sizeof(LV_ITEM));//获取选择行dwRowId = SendMessage(hListProcess, LVM_GETNEXTITEM,-1 , LVNI_SELECTED);if (dwRowId == -1) {MessageBox(NULL, TEXT("请选择进程"), TEXT("出错啦"), MB_OK);return;}//获取PIDlv.iSubItem = 1;lv.pszText = szPid;lv.cchTextMax = 0x20;SendMessage(hListProcess, LVM_GETITEMTEXT, dwRowId, (DWORD)&lv);MessageBox(NULL, szPid, TEXT("PID"), MB_OK);
}
三.加载Windows进程应用程序项目初步完整代码
讲述了这些代码,这里给大家给出完整代码,但是由于控件的ID不同,复制的时候还需要自己改动。
// PEProcess.cpp : 定义应用程序的入口点。
//#include "framework.h"
#include "PEProcess.h"
#include <CommCtrl.h>
#pragma comment(lib,"comctl32.lib")
HINSTANCE hIns = 0;//程序向前声明
BOOL CALLBACK MainDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); //主窗口(对话框)回调函数
VOID InitProcessListView(HWND hDlg); //初始化主窗口进程列表函数
VOID EnumProcess(HWND hListProcess); //设置假的进程数据函数
VOID InitMoudleListView(HWND hDlg); //初始化主窗口模块列表函数
VOID EnumMoudles(HWND hListProcess, WPARAM wParam, LPARAM lParam); //设置假的模块列表函数int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow
) {hIns = hInstance;//使用通用控件的向前声明INITCOMMONCONTROLSEX icex;icex.dwSize = sizeof(INITCOMMONCONTROLSEX);icex.dwICC = ICC_WIN95_CLASSES;InitCommonControlsEx(&icex);DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG_MAIN), NULL, (DLGPROC)MainDlgProc);return 0;
}//各类函数实现
BOOL CALLBACK MainDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {BOOL nRet = FALSE;switch (uMsg) {case WM_CLOSE: {EndDialog(hDlg, 0);PostQuitMessage(0);break;}case WM_INITDIALOG: {InitProcessListView(hDlg); //设置ProcessListView的风格,初始化进程列表InitMoudleListView(hDlg); //设置MoudleListView的风格,初始化模块列表break;}case WM_COMMAND: {switch (LOWORD(wParam)) {case IDC_BUTTON_ABOUT: {DialogBox(hIns, MAKEINTRESOURCE(IDD_ABOUTBOX), NULL, NULL);}case IDC_BUTTON_PE: {//打开新的对话框,PE查看器return 0;}case IDC_BUTTON_OUT: {EndDialog(hDlg, 0);PostQuitMessage(0);return TRUE;}}}case WM_NOTIFY: {NMHDR* pNMHDR = (NMHDR*)lParam;if (wParam == IDC_LIST_PROCESS && pNMHDR->code == NM_CLICK) {EnumMoudles(GetDlgItem(hDlg, IDC_LIST_PROCESS), wParam, lParam);}break;}}return nRet;
}VOID InitProcessListView(HWND hDlg) {//设置窗口风格调用结构体LV_COLUMN lv;HWND hListProcess;//初始化memset(&lv, 0, sizeof(LV_COLUMN));//获取进程列表句柄hListProcess = GetDlgItem(hDlg, IDC_LIST_PROCESS);//设置整行选中SendMessage(hListProcess, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT);//出错代码:::::SendMessage(hListProcess, LVM_GETEXTENDEDLISTVIEWSTYLE, LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT);//第一列:lv.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM;lv.pszText = (LPWSTR)TEXT("进程"); //列标题lv.cx = 350; //行宽lv.iSubItem = 0;//ListView_InsertColumn(hListProcess,0,&lv);SendMessage(hListProcess, LVM_INSERTCOLUMN, 0, (DWORD)&lv);//第二列lv.pszText = (LPWSTR)TEXT("PID");lv.cx = 100;lv.iSubItem = 1;//ListView_InsertColumn(hListProcess, 1, &lv);SendMessage(hListProcess, LVM_INSERTCOLUMN, 1, (DWORD)&lv);//第三列lv.pszText = (LPWSTR)TEXT("镜像基址");lv.cx = 150;lv.iSubItem = 2;//ListView_InsertColumn(hListProcess, 2, &lv);SendMessage(hListProcess, LVM_INSERTCOLUMN, 2, (DWORD)&lv);//第四列lv.pszText = (LPWSTR)TEXT("镜像大小");lv.cx = 200;lv.iSubItem = 3;//ListView_InsertColumn(hListProcess, 3, &lv);SendMessage(hListProcess, LVM_INSERTCOLUMN, 3, (DWORD)&lv);EnumProcess(hListProcess);
}//加载进程函数
VOID EnumProcess(HWND hListProcess) {LV_ITEM vitem;//初始化,第一个进程memset(&vitem, 0, sizeof(LV_ITEM));vitem.mask = LVIF_TEXT;//假数据:vitem.pszText = (LPWSTR)TEXT("csrss.exe");vitem.iItem = 0;vitem.iSubItem = 0;//ListView_Insertem(hListProcess,*vitem);SendMessage(hListProcess, LVM_INSERTITEM, 0, (DWORD)&vitem);vitem.pszText = (LPWSTR)TEXT("448");vitem.iItem = 0;vitem.iSubItem = 1;SendMessage(hListProcess, LVM_SETITEM, 0, (DWORD)&vitem);//ListView_SetItem(hListProcess, &vitem);vitem.pszText = (LPWSTR)TEXT("56590000");vitem.iItem = 0;vitem.iSubItem = 2;ListView_SetItem(hListProcess, &vitem);vitem.pszText = (LPWSTR)TEXT("000F0000");vitem.iItem = 0;vitem.iSubItem = 3;ListView_SetItem(hListProcess, &vitem);//第二个进程假数据:vitem.pszText = (LPWSTR)TEXT("QQ.exe");vitem.iItem = 1;vitem.iSubItem = 0;SendMessage(hListProcess, LVM_INSERTITEM, 0, (DWORD)&vitem);vitem.pszText = (LPWSTR)TEXT("153");vitem.iItem = 1;vitem.iSubItem = 1;ListView_SetItem(hListProcess, &vitem);vitem.pszText = (LPWSTR)TEXT("65580000");vitem.iItem = 1;vitem.iSubItem = 2;ListView_SetItem(hListProcess, &vitem);vitem.pszText = (LPWSTR)TEXT("001E0000");vitem.iItem = 1;vitem.iSubItem = 3;ListView_SetItem(hListProcess, &vitem);//第三个进程假数据:vitem.pszText = (LPWSTR)TEXT("WeChat.exe");vitem.iItem = 2;vitem.iSubItem = 0;SendMessage(hListProcess, LVM_INSERTITEM, 0, (DWORD)&vitem);vitem.pszText = (LPWSTR)TEXT("256");vitem.iItem = 2;vitem.iSubItem = 1;ListView_SetItem(hListProcess, &vitem);vitem.pszText = (LPWSTR)TEXT("75960000");vitem.iItem = 2;vitem.iSubItem = 2;ListView_SetItem(hListProcess, &vitem);vitem.pszText = (LPWSTR)TEXT("015B0000");vitem.iItem = 2;vitem.iSubItem = 3;ListView_SetItem(hListProcess, &vitem);
}VOID InitMoudleListView(HWND hDlg) {//设置窗口风格需要调用结构体LV_COLUMN lv;HWND hListMoudles;//初始化memset(&lv, 0, sizeof(LV_COLUMN));//获取模块列表句柄hListMoudles = GetDlgItem(hDlg, IDC_LIST_MOUDLE);//设置整行选中SendMessage(hListMoudles, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT);//第一列:lv.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM;lv.pszText = (LPWSTR)TEXT("模块名称");lv.cx = 400;lv.iSubItem = 0;//ListView_Insertcolumn(hListMoudles,0,&lv);SendMessage(hListMoudles, LVM_INSERTCOLUMN, 0, (DWORD)&lv);//第二列:lv.pszText = (LPWSTR)TEXT("模块位置");lv.cx = 400;lv.iSubItem = 1;SendMessage(hListMoudles, LVM_INSERTCOLUMN, 0, (DWORD)&lv);
}VOID EnumMoudles(HWND hListProcess, WPARAM wParam, LPARAM lParam) {DWORD dwRowId;TCHAR szPid[21];LV_ITEM lv;//初始化memset(&lv, 0, sizeof(LV_ITEM));//获取选择行dwRowId = SendMessage(hListProcess, LVM_GETNEXTITEM,-1 , LVNI_SELECTED);if (dwRowId == -1) {MessageBox(NULL, TEXT("请选择进程"), TEXT("出错啦"), MB_OK);return;}//获取PIDlv.iSubItem = 1;lv.pszText = szPid;lv.cchTextMax = 0x20;SendMessage(hListProcess, LVM_GETITEMTEXT, dwRowId, (DWORD)&lv);MessageBox(NULL, szPid, TEXT("PID"), MB_OK);
}
程序效果:
今天的分享就到这里,如果文章中出现错误或者是本人理解不到位的地方,还请大家及时指出来,我会非常虚心地学习。希望大家共同进步!!!