Windows系统HOOK拦截系统消息

直接上代码

#include <Windows.h>
#include <stdio.h>
#include <iostream>

HWND hgWnd;
HHOOK myhook;

LPCWSTR ConvertToLPCWSTR(const char* str)
{
	int length = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0);
	wchar_t* wideStr = new wchar_t[length];
	MultiByteToWideChar(CP_UTF8, 0, str, -1, wideStr, length);
	return wideStr;
}

LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
	PKBDLLHOOKSTRUCT p = (PKBDLLHOOKSTRUCT)lParam;
	const char *info = NULL;
	char text[50], data[20];

	PAINTSTRUCT ps;
	HDC hdc;

	if (nCode >= 0)
	{
		if (wParam == WM_KEYDOWN)info = "command key up";
		else if (wParam == WM_KEYUP)info = "command key down";
		else if (wParam == WM_SYSKEYDOWN)info = "system key up";
		else if (wParam == WM_SYSKEYUP)info = "system key down";

		ZeroMemory(text, sizeof(text));
		ZeroMemory(data, sizeof(data));
		sprintf_s(text, "%s - key :[%04d], scan: [%04d]  ", info, p->vkCode, p->scanCode);
		sprintf_s(data, "key: %c  ", p->vkCode);

		hdc = GetDC(hgWnd);
		TextOut(hdc, 10, 10, ConvertToLPCWSTR(text), strlen(text));
		TextOut(hdc, 10, 30, ConvertToLPCWSTR(data), strlen(data));
		ReleaseDC(hgWnd, hdc);
	}
	//非零值
	//return 1;
	return CallNextHookEx(myhook, nCode, wParam, lParam);
}

// 5. 窗口过程处理
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	hgWnd = hwnd;

	switch (msg)
	{
	case WM_CLOSE:
		DestroyWindow(hwnd);
		break;
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	default:
		return DefWindowProc(hwnd, msg, wParam, lParam);
	}
	return 0;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
	LPSTR lpCmdLine, int nCmdShow)
{
	WNDCLASSEX wc;
	HWND hwnd;
	MSG Msg;
	char text[30];

	const char szClassName[] = "myWindowClass";

	// 1. 设置注册窗口结构体
	wc.cbSize = sizeof(WNDCLASSEX);// 注册窗口结构体的大小
	wc.style = 0;// 窗口的样式
	wc.lpfnWndProc = WndProc;// 指向窗口处理过程的函数指针
	wc.cbClsExtra = 0;// 指定紧跟在窗口类结构后的附加字节数
	wc.cbWndExtra = 0;// 指定紧跟在窗口事例后的附加字节数
	wc.hInstance = hInstance;// 本模块的实例句柄
	wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); // 图标的句柄
	wc.hCursor = LoadCursor(NULL, IDC_ARROW);// 光标的句柄
	wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);// 背景画刷的句柄
	wc.lpszMenuName = NULL;// 指向菜单的指针
	wc.lpszClassName = ConvertToLPCWSTR(szClassName);// 指向类名称的指针
	wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION); // 和窗口类关联的小图标

	// 2. 使用【窗口结构体】注册窗口
	if (!RegisterClassEx(&wc))
	{
		MessageBox(NULL, TEXT("windows enroll fail!"), TEXT("fail"), MB_ICONEXCLAMATION | MB_OK);
		return 0;
	}

	// 3. 创建窗口
	hwnd = CreateWindowEx(
		WS_EX_CLIENTEDGE,// 窗口的扩展风格
		ConvertToLPCWSTR(szClassName),// 指向注册类名的指针
		TEXT("windows title"),// 指向窗口名称的指针
		WS_OVERLAPPEDWINDOW,// 窗口风格
		CW_USEDEFAULT, CW_USEDEFAULT, 350, 200, // 窗口的 x,y 坐标以及宽高
		NULL,// 父窗口的句柄
		NULL,// 菜单的句柄
		hInstance,// 应用程序实例的句柄
		NULL// 指向窗口的创建数据
	);

	if (hwnd == NULL)
	{
		MessageBox(NULL, TEXT("windows creat fail"), TEXT("error"), MB_ICONEXCLAMATION | MB_OK);
		return 0;
	}

	// 4. 显示窗口
	ShowWindow(hwnd, nCmdShow);
	UpdateWindow(hwnd);

	// 设置键盘全局监听
	myhook = SetWindowsHookEx(
		WH_KEYBOARD_LL, // 监听类型【键盘】
		KeyboardProc,// 处理函数
		hInstance,// 当前实例句柄
		0// 监听窗口句柄(NULL为全局监听)
	);

	if (myhook == NULL)
	{
		sprintf_s(text, "listening kry fail!error : %d \n", GetLastError());
		MessageBox(hwnd, ConvertToLPCWSTR(text), TEXT("error"), MB_OK);
	}


	// 5. 消息循环
	while (GetMessage(&Msg, NULL, 0, 0) > 0)
	{
		TranslateMessage(&Msg);
		DispatchMessage(&Msg);
	}
	return Msg.wParam;
}

注意KeyboardProc函数

返回是非零值时,该消息将不会传递到下一个钩子子程或者窗口中,

返回是CallNextHookEx(myhook, nCode, wParam, lParam);时,消息将会继续传递下去。后续子程将会继续处理该消息。

上述代码作用:

注释掉的是return1;时:

按下按键之后,搜索栏有字符且应用程序窗口也有字符,因为虽然拦截了,但是允许向下传递。

注释掉的是return CallNextHookEx(myhook, nCode, wParam, lParam); 时:结果如图:

按下按键之后,搜索栏没有字符,而程序窗口有字符(因为拦截显示且不向下传递)

函数参考文档

KeyboardProc 回调函数 - Win32 apps | Microsoft Learn

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值