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 结构
:
包含有关报表视图中的列的信息。
这个结构体大家到微软文档中自行查看吧,解释起来真的很费劲。
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
消息
- 发送时间:在列表视图控件中插入新项。
- 附加信息:
- wParam:必须为0.
- lParam:指向指定列表视图项属性的 LVITEM 结构的指针。
LVM_SETITEM
消息
- 发送时间:设置列表视图项的某些或全部属性。 还可以发送LVM_SETITEM来设置子项的文本
- 附加信息:
- wParam:必须为0.
- lParam:指向包含新项属性的 LVITEM 结构的指针
注意两者区别为在列表视图控件中插入新项和添加子项。
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; } //获取PID lv.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; } //获取PID lv.iSubItem = 1; lv.pszText = szPid; lv.cchTextMax = 0x20; SendMessage(hListProcess, LVM_GETITEMTEXT, dwRowId, (DWORD)&lv); MessageBox(NULL, szPid, TEXT("PID"), MB_OK); }
程序效果:
今天的分享就到这里,如果文章中出现错误或者是本人理解不到位的地方,还请大家及时指出来,我会非常虚心地学习。希望大家共同进步!!!