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;
}
相关推荐
chen_2275 分钟前
windows系统安装wsl
windows·wsl
学习论之费曼学习法16 分钟前
AutoGen框架详解:微软Multi-Agent开发利器
人工智能·microsoft
shandianchengzi1 小时前
【科普】安卓|安卓手机上如何简便实现Ctrl+Z(需要键盘或一台Windows电脑)
android·windows·智能手机·计算机外设·安卓·科普·记录
nashane9 小时前
HarmonyOS 6学习:外接键盘CapsLock与长截图功能的实战调试与完整解决方案
学习·华为·计算机外设·harmonyos
сокол13 小时前
【网安-Web渗透测试-内网渗透】域环境权限维持
服务器·windows·网络安全·系统安全
ACP广源盛1392462567313 小时前
iOS 27 开放 AI 生态@ACP#小型化扩展黄金风口,IX8008全面超越 ASM2806,铸就嵌入式 AI 扩展核心
人工智能·嵌入式硬件·macos·ios·计算机外设·objective-c·cocoa
玖釉-15 小时前
栈——栈的定义及基本操作
c++·windows·算法·图形渲染
取经蜗牛15 小时前
Windows 11 WSL + Ubuntu 24.04 安装指南
linux·windows·ubuntu
大树学长16 小时前
【QT开发】Windows 10 + Qt 5.15.2 手动编译安装 Qt OPC UA 模块完整记录
开发语言·windows·qt
idolao16 小时前
Autodesk VRED Professional 2025安装教程 Windows版:自定义路径+Keygen指南
windows