用纯win32编程响应消息
作者:互联网
大家都知道,windows操作系统是基于消息的,所有的操作都可以用发送消息来完成;这个项目大概的图形界面是这样的:
文章重点说的是点击事件如何被响应;
先创建一个win32的应用程序,再。RC文件下添加一个Dlalog资源。你们可能会认为Dlalog是MFC专属的资源,mfc是微软提供的一个类库,是为了更好的响应这些资源。如果没有自动添加resource文件,需要在头文件中添加现有项。这些工作做好之后,就可以开始写代码了;
如果想要自己画窗口,需要在winmain函数下完成
- 为class赋值
- 注册窗口句柄
- 创建窗口
- 提供消息处理函数
- 消息循环接收
如果使用Dlalog,那就只需要创建窗口
//创建对话框函数原型
INT_PTR Dialog(
HINSTANCE hInstance, //imagebase
LPCTRSR lpTemplate, //模板,就是创建的Dlalog的ID
HWND hWndParent, //父窗口
DLGPROC lpDialogFunc //函数定义窗口
)
//处理消息的函数
BOOL CALLBACK MainDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {
BOOL bRet = FALSE;
switch (uMsg)
{
case WM_INITDIALOG: //窗口初始化就会触发这个事件
case WM_NOTIFY: //*
case WM_COMMAND: //*
case WM_CLOSE:
//在WinMain中调用函数
DialogBox(hInstance,(MAKEINTRESOURCE)IDC_DIALOG_MAIN,NULL,MainDlgProc);
//进行强制类型转换的原因是第二个参数可以给定一个指针 也可以给定一个序号,如果是一个序号,就用MAKEINTRESOURCE宏进行转换;
现在窗口就可以显示出来了,但是没有内容;需要添加按钮,这时候就要说一下标准控件和通用控件了;
标准控件像Static,Button,Edit等等都是,都是可用的;但是通用代码包含在Comctrl32.dll里,像ComboBoxEx,Header,ImageList这些需要做俩件事
#include<commctrl.h>
#pragma comment(lib,"comctl32.lib")
//除了这个头文件还要告诉windows加载器需要加载的lib;
//这些代码可以放到WinMain下
INITCOMMONCONTROLSEX icex;
icex.dwSize=sizeof(INITCOMMONCONTROLSEX);
icex.dwICC=ICC_WIN95_CLASSES;
InitCommonControlsEx(&icex);
这是在老版本事这样,vs2019能直接用,不需要这些。界面需要用到这个控件:
在画完界面之后就需要添加列 process pid user size 上代码:
VOID InitProcessLostView(HWND hDlg) {
LV_COLUMN lv;
HWND hListProcess;//hwnd
memset(&lv, 0, sizeof(LV_COLUMN));//初始化局部变量
hListProcess = GetDlgItem(hDlg, IDC_LIST_PROCESS);
//获取窗口句柄,hDlg是父窗口句柄,另一个是子空间ID;
//整行选中
SendMessage(hListProcess, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_FULLROWSELECT,
LVS_EX_FULLROWSELECT);
//在windows中一定要发送消息才能干活;
//1
lv.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM;
lv.pszText = (LPWSTR)TEXT("process");//标题
lv.cx = 150;//列宽
lv.iSubItem = 0;//所在第几列,从0开始
SendMessage(hListProcess, LVM_INSERTCOLUMN, 0, (DWORD)&lv);
//2
lv.pszText = (LPWSTR)TEXT("pid");
lv.cx = 120;
lv.iSubItem = 1;
SendMessage(hListProcess, LVM_INSERTCOLUMN, 1, (DWORD)&lv);
//3
lv.pszText = (LPWSTR)TEXT("user");
lv.cx = 100;
lv.iSubItem = 2;
ListView_InsertColumn(hListProcess, 2, &lv);//这个宏和SendMessage的效果是一样的;
//4
lv.pszText = (LPWSTR)TEXT("size");
lv.cx = 100;
lv.iSubItem = 3;
ListView_InsertColumn(hListProcess, 3, &lv);
}
这里有俩个结构需要说一下,
LV_COLUMN用于定义报表方式下的“列”的结构;LV_ITEM用于定义“项”的结构。下面会用到另一个;
到了这一步,就能够显示成这样:
现在需要在process项下添加元素,需要用到另外一个结构体LV_ITEM;
//遍历系统进程
int TraProcess(HWND hDlg) {
LVITEM vitem;
HWND hListProcess;
memset(&vitem, 0, sizeof(LVITEM));
vitem.mask = LVIF_TEXT;
hListProcess = GetDlgItem(hDlg, IDC_LIST_PROCESS);
SendMessage(hListProcess, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT);
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (INVALID_HANDLE_VALUE == hSnapshot)return 0;
PROCESSENTRY32 pi;
pi.dwSize = sizeof(PROCESSENTRY32);
BOOL bRet = Process32First(hSnapshot, &pi);
IMAGE_SECTION_HEADER* pISH = (IMAGE_SECTION_HEADER*)pi.th32ProcessID;
while(bRet) {
bRet = Process32Next(hSnapshot, &pi);
vitem.pszText = pi.szExeFile;
vitem.iItem = 0;//第几行,抱歉,这里应该用循环,因为行数在增加,但是效果一样
vitem.iSubItem = 0;//所在列
SendMessage(hListProcess, LVM_INSERTITEM, 0, (DWORD)&vitem);
}
return 0;
}
后来的版本用LVITEM代替了LV_ITEM,中间的函数都是获取系统进程的win32函数,需要自己去查,程序员一定要会自己解决问题,才能成为好的程序员;
界面基本就写完了,现在要说一个知识;当点击按钮时,是响应函数是父窗口提供的。通过Command事件可以完成响应。但是对于List Contral控件需要响应的消息太多了,如果都用case WM_.....代码就比较难看了,所以window提供了一个结构响应消息,
case WM_NOTIFY://通知消息
该消息和WM_COMMAND消息类型相似,都是向父窗口发送消息,但是WM_NOTIFY比WM_COMMAND消息类型更丰富;
//WM_NOTIFY消息中带有俩个参数
wParam:是控件ID;
lParam:指向一个结构体
//结构体类型:
typedef struct tagNMHDR{
HWND hwndFrom;//发送消息的句柄
UINT idFrom; //发送消息的ID
UINT code; //通知码,是左键消息还是右键
}NMHDR
但是这个结构体还是不能全部包括,windows又对每种不同用途的消息创建了结构体,这些结构体都可以讲子窗口的消息带到父窗口,lParam就指向这些结构;这些结构有一个共同特点:第一个参数都指向第tarNMHDR;
在C++中,继承机制就是 子类会将父类先调用,之后初始化自己的类;这样,无论之后在补充多少东西,继承之后都能将消息带到父类;来看一下实际应用;
在第二个List控件中,想要通过第一个LIST的Pid拿到user和size,就需要通过WM_NOTIFY消息,
//获取进程模块信息
void TraModulse(HWND hListProcess, WPARAM wParam, LPARAM lParam) {
DWORD dwRowId;
TCHAR szPid[0x20];//缓冲区
LV_ITEM lv;
memset(&lv, 0, sizeof(LV_ITEM));
memset(szPid, 0, 0x20);
//获取选中的行
if (Pid != -1) {
//获取PID
vit.iSubItem = 1;
vit.pszText = sizePid;
vit.cchTextMax = 0x20;
SendMessage(hListProcess, LVM_GETITEMTEXT, Pid, (DWORD)&vit);
}
else {
MessageBox(NULL, TEXT("Please close process"), TEXT("ERROR"), MB_OK);
return;
}
}
//放到处理消息的响应还是MainDlgProc里
case WM_NOTIFY://响应点击进程信息
{
NMHDR* p = (NMHDR*)lParam;
if (p->code == NM_CLICK&&wParam == IDC_LIST_PROCESS) {//判断是哪个List 和鼠标按键
TraModulse(GetDlgItem(hDlg, IDC_LIST_PROCESS), wParam, lParam);
}
break;
}
项目代码可以到我资源文件下载
标签:lv,窗口,控件,WM,编程,win32,hListProcess,用纯,消息 来源: https://blog.csdn.net/qq_45806710/article/details/116087691