编程语言
首页 > 编程语言> > 用纯win32编程响应消息

用纯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