目录
- 1,系统击键消息和非系统击键消息
- [2,PostMessage 发送自定义消息](#2,PostMessage 发送自定义消息)
- 3,客户区鼠标消息
-
- [3.1,鼠标光标函数 GetCursorPos](#3.1,鼠标光标函数 GetCursorPos)
- [3.2,鼠标光标函数 SetCursorPos](#3.2,鼠标光标函数 SetCursorPos)
1,系统击键消息和非系统击键消息
在 Windows 编程中,系统击键盘消息用来处理键盘输入事件,它们在窗口过程函数(WndProc)被处理。
WM_KEYDOWN 和 WM_SYSKEYDOWN
- WM_KEYDOWN :
当用户按下一个非系统键(如字母、数字、功能键等,不包括与 Alt 键组合的情况)时,系统会向拥有输入焦点的窗口发送此消息。 - WM_SYSKEYDOWN :
当用户按下一个系统键(通常是与 Alt 键组合的键,如 Alt + Tab、Alt + F4 等)时, 系统会向拥有输入焦点的窗口发送此消息。
参数:
- WPARAM wParam:
指定了按下的虚拟键码(Virtual - Key Codes)。例如,VK_A 代表字母 A,VK_1 代表数字 1 等。 - LPARAM lParam:
包含了与按键相关的额外信息,如重复次数、扫描码、键的状态等。低 16 位表示按键的重复次数,接下来 8 位是扫描码,再接下来 1 位表示扩展键标志(如是否是小键盘上的键),再接下来 1 位表示是否是上下文代码(仅对 WM_SYSKEYDOWN 有意义,用于判断是否与 Alt 键组合),然后是先前键状态和转换状态等信息。
WM_KEYUP 和 WM_SYSKEYUP
- WM_KEYUP:当用户释放一个非系统键时
- WM_SYSKEYUP:当用户释放一个系统键时
参数: 与 WM_KEYDOWN 和 WM_SYSKEYDOWN 的参数类似,WPARAM wParam 包含释放的虚拟键码,LPARAM lParam 包含与按键相关的额外信息,但某些位的含义可能有所不同,如重复次数在键释放时通常为 0。
javascript
LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
case WM_KEYUP:
if (wParam == VK_SPACE) {
// 用户释放了空格键
MessageBox(hwnd, TEXT("你释放了空格键"), TEXT("提示"), MB_OK);
}
break;
case WM_SYSKEYUP:
// 可以在此处理系统键释放的情况
break;
case WM_KEYDOWN:
if (wParam == VK_RETURN) {
// 用户按下了回车键
MessageBox(hWnd, TEXT("你按下了回车键"), TEXT("提示"), MB_OK);
}
break;
case WM_SYSKEYDOWN:
if (wParam == VK_F4 && (lParam & 0x20000000)) {
// 用户按下了Alt + F4
MessageBox(hWnd, _T("按下 Alt + F4"), _T("标题"), MB_OK);
}
break;
case WM_KEYUP:
if (wParam == VK_RETURN)
{
// 用户按下了回车键
MessageBox(hWnd, TEXT("你松开了回车键"), TEXT("提示"), MB_OK);
}
break;
case WM_SYSKEYUP:
if (wParam == VK_F4 && (lParam & 0x20000000))
{
// 用户按下了Alt + F4
MessageBox(hWnd, _T("松开 Alt + F4"), _T("标题"), MB_OK);
}
break;
case WM_LBUTTONDOWN:
MessageBox(hWnd,_T("按下鼠标左键"),_T("标题"),MB_OK);
break;
// 其他消息处理...
default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
return 0;
}
实现一个功能,当点击鼠标左键时,窗口绘制字符串 hello world
javascript
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
static BOOL bDrawTopLeft = FALSE;
static BOOL bDrawCenter = FALSE;
switch (message) {
case WM_LBUTTONDOWN:
bDrawTopLeft = TRUE;
InvalidateRect(hwnd, NULL, TRUE);
break;
case WM_KEYDOWN:
if (wParam == VK_RETURN) {
bDrawCenter = TRUE;
InvalidateRect(hwnd, NULL, TRUE);
}
break;
case WM_PAINT: {
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
if (bDrawTopLeft) {
SetTextColor(hdc, RGB(0, 0, 0));
SetBkMode(hdc, TRANSPARENT);
TextOut(hdc, 0, 0, TEXT("hello world"), lstrlen(TEXT("hello world")));
}
if (bDrawCenter) {
RECT rect;
GetClientRect(hwnd, &rect);
int x = rect.left + (rect.right - rect.left) / 2;
int y = rect.top + (rect.bottom - rect.top) / 2;
SetTextColor(hdc, RGB(0, 0, 0));
SetBkMode(hdc, TRANSPARENT);
DrawText(hdc, TEXT("hello world"), -1, &rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
}
EndPaint(hwnd, &ps);
break;
}
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, message, wParam, lParam);
}
return 0;
}
2,PostMessage 发送自定义消息
javascript
// 定义自定义消息
#define WM_MY_CUSTOM_MESSAGE (WM_USER + 100)
// 发送自定义消息,携带数据
int data = 42;
HWND targetWnd = GetForegroundWindow();
PostMessage(targetWnd, WM_MY_CUSTOM_MESSAGE, (WPARAM)data, (LPARAM)&somePointer);
// 在窗口过程函数中处理自定义消息
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
switch (message) {
case WM_MY_CUSTOM_MESSAGE:
int receivedData = (int)wParam;
SomeType* receivedPointer = (SomeType*)lParam;
// 处理接收到的数据
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
default:
return DefWindowProc(hwnd, message, wParam, lParam);
}
}
3,客户区鼠标消息
当用户移动,按下或释放鼠标按钮时,会生成鼠标输入事件。
移动光标会不断发送 WM_MOUSEMOVE 消息
| 项目 | Value |
|---|---|
| WM_LBUTTONDOWN | 按下鼠标左键 |
| WM_MBUTTONDOWN | 按下鼠标中键 |
| WM_RBUTTONDOWN | 按下鼠标右键 |
| WM_LBUTTONUP | 释放鼠标左键 |
| WM_MBUTTONUP | 释放鼠标中键 |
| WM_RBUTTONUP | 释放鼠标右键 |
| WM_MOUSEMOVE | 光标在窗口客户区内移动 |
| WM_LBUTTONDBLCLK | 双击鼠标左键 |
| WM_RBUTTONDBLCLK | 双击鼠标右键时 |
javascript
LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
case WM_LBUTTONDOWN:
// 处理鼠标左键按下逻辑
break;
case WM_RBUTTONUP:
// 处理鼠标右键释放逻辑
break;
case WM_MOUSEMOVE:
// 处理鼠标移动逻辑
break;
default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
return 0;
}
客户区鼠标消息的 lParam 参数表示鼠标发生时光标热点的位置,
lParam 参数的低位字表示热点的 X 坐标。高位字表示 Y 坐标。
javascript
case WM_LBUTTONDOWN:
{
int x = LOWORD(lParam);
int y = HIWORD(lParam);
TCHAR buffer[50];
wsprintf(buffer, TEXT("鼠标光标位置: x = %d, y = %d"), x, y);
MessageBox(hWnd, buffer, TEXT("鼠标位置"), MB_OK);
}
break;
3.1,鼠标光标函数 GetCursorPos
获取光标的函数:
GetCursorPos
BOOL GetCursorPos(LPPOINT lpPoint);
typedef struct tagPOINT {
LONG x;
LONG y;
} POINT, *PPOINT;
可以获取鼠标光标的当前位置。
javascript
#include <windows.h>
#include <stdio.h>
int main() {
POINT cursorPos;
if (GetCursorPos(&cursorPos)) {
char buffer[50];
sprintf(buffer, "鼠标光标位置: x = %d, y = %d", cursorPos.x, cursorPos.y);
MessageBox(NULL, buffer, "鼠标位置", MB_OK);
} else {
MessageBox(NULL, "获取鼠标位置失败", "错误", MB_OK);
}
return 0;
}
3.2,鼠标光标函数 SetCursorPos
Windows API 中的一个函数,用于设置鼠标光标的屏幕坐标位置。
BOOL SetCursorPos(int X, int Y);
javascript
#include <windows.h>
#include <stdio.h>
int main() {
// 将鼠标光标移动到屏幕坐标 (300, 200) 的位置
if (SetCursorPos(300, 200)) {
POINT newPos;
if (GetCursorPos(&newPos)) {
char buffer[50];
sprintf(buffer, "鼠标光标新位置: x = %d, y = %d", newPos.x, newPos.y);
MessageBox(NULL, buffer, "鼠标新位置", MB_OK);
} else {
MessageBox(NULL, "获取鼠标新位置失败", "错误", MB_OK);
}
} else {
MessageBox(NULL, "设置鼠标位置失败", "错误", MB_OK);
}
return 0;
}