Win32 键盘与鼠标

目录

1,系统击键消息和非系统击键消息

在 Windows 编程中,系统击键盘消息用来处理键盘输入事件,它们在窗口过程函数(WndProc)被处理。

WM_KEYDOWNWM_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_KEYUPWM_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;
}
相关推荐
人工智能训练1 小时前
从 1.1.3 到 1.13.2!Ubuntu 24.04 上 Dify 升级保姆级教程(零数据丢失 + 一键迁移)
linux·运维·人工智能·windows·ubuntu·dify
mldlds1 小时前
Windows安装Redis图文教程
数据库·windows·redis
武藤一雄1 小时前
C#:nameof 运算符全指南
开发语言·microsoft·c#·.net·.netcore
softbangong2 小时前
815-批量Excel文件合并工具,批量excel文件、工作表合并软件
linux·windows·excel·文件合并·excel合并·数据整理
春日见2 小时前
GIT操作大全(个人开发与公司开发)
开发语言·驱动开发·git·matlab·docker·计算机外设·个人开发
七夜zippoe2 小时前
OpenClaw 接入 Telegram:BotFather 实战
microsoft·ngrok·telegram·openclaw·botfather
烛之武2 小时前
Nacos3.2.0下载安装教程(Windows版本)
windows
竹之却3 小时前
【OpenClaw】云服务器端 openclaw 集成本地 Windows端 ollama 模型
windows·llama·ollama·openclaw·qwen3.5
小妖同学学AI3 小时前
微软开源多智能体协作框架AutoGen:像组建公司一样,打造会“开会”的AI团队
人工智能·microsoft·开源
golang学习记3 小时前
VS Code 1.113 发布:Agent 与 Chat 体验全面升级!
vscode·microsoft