windows SDK编程 --- 消息之键盘消息(4)

ops/2025/2/12 21:48:21/

前置知识

一、 键盘消息

在Windows操作系统中,键盘消息是用来通知应用程序有关键盘输入事件的一种机制。当用户在键盘上进行操作,比如按键或释放键时,Windows会生成相应的消息并发送给处理这些输入的应用程序。这些消息对于开发图形用户界面(GUI)应用程序至关重要,因为它们允许应用程序响应用户的输入。

下面是几种主要的键盘消息及其用途的详细说明:

  1. WM_KEYDOWN
描述:
当用户按下一个键盘键(并未完全释放)时发送此消息给拥有焦点的窗口。
参数:
wParam:虚拟键码。
lParam:提供了有关按键的更多信息,如重复次数、扫描码、ALT键是否被按下等。
lParam 参数的详细位分布:
0-15位:重复计数(Repeat count)。这表示自从用户开始按下键以来,由于按键保持不放,相同的消息被自动重复发送的次数。这个计数不是累积的,每次消息发送时都是独立的计数。
16-23位:扫描码(Scan code)。这是键盘硬件产生的代码,用于识别物理键。
24位:扩展键标志(Extended-key flag)。如果是扩展键(如功能键、方向键等),该位为125-28位:保留,未使用。
29位:上下文代码。对于 WM_KEYDOWN 消息,这个值始终为030位:上一个键状态(Previous key state)。如果在发送此消息之前键是未按下的,则此位为1;如果键已经是按下状态,则此位为031位:转换状态(Transition state)。对于 WM_KEYDOWN,该位总是为0;对于 WM_KEYUP,该位为1
  1. WM_KEYUP
描述:
当用户释放一个键盘键时发送此消息。
参数:
wParam:虚拟键码。
lParam:同样包含键的重复次数、扫描码、是否有ALT键等信息。
  1. WM_CHAR
描述:
用于处理字符输入,当按下能产生字符的键时,通过 TranslateMessage 函数生成。例如,按下 A 键时,如果启用了大写锁定或者同时按住了Shift键,可能会发送 WM_CHAR 消息并携带字符 ‘A’。
参数:
wParam:字符的ASCII或Unicode值。
lParam:与 WM_KEYDOWN 和 WM_KEYUP 相同,提供了关于按键事件的更多细节。
  1. WM_SYSKEYDOWN 和 WM_SYSKEYUP
描述:
这些消息类似于 WM_KEYDOWN 和 WM_KEYUP,但它们用于处理系统键(如Alt和F10)。
参数:
wParam:虚拟键码。
lParam:包含与普通键盘消息相同的额外信息。

二、什么是虚拟键码

虚拟键码是Windows操作系统定义的一组常数,用于表示键盘上的每一个按键。这些键码可以让开发者在编程时准确地识别用户按下或释放的具体键,无论键盘布局和硬件如何。虚拟键码在处理键盘输入提供了一个硬件无关的方法来识别键盘动作。简而言之,虚拟键码就是对键盘按键的一种编程上的抽象表示。wParam 参数会包含被按下或释放键的虚拟键码。

VK_A:字母 'A' 键(值为 0x41)
VK_0:数字 '0' 键(值为 0x30)
VK_ESCAPE:Esc键(值为 0x1B)
VK_RETURN:回车键(值为 0x0D)
VK_LEFT:左方向键(值为 0x25)
VK_RIGHT:右方向键(值为 0x27)
VK_UP:上方向键(值为 0x26)
VK_DOWN:下方向键(值为 0x28

三、什么是扫描码?扫描码和虚拟键码的关系?

在Windows编程中,处理键盘事件如 WM_KEYDOWN 时,可以通过消息的 lParam 获取扫描码,而 wParam 提供虚拟键码。这允许程序同时利用键的物理位置(扫描码)和逻辑功能(虚拟键码)来响应用户的键盘操作。

键盘扫描码(Scan Code)

键盘扫描码是键盘硬件为每次按键生成的原始代码,表示按下的是键盘上的哪一个物理键。这些代码通常是硬件级的,与操作系统和键盘布局无关。扫描码的主要作用是在最底层—即硬件和操作系统的界面—提供键位信息。

  • 特点:扫描码直接来自键盘,不受键盘语言布局的影响。
  • 用途:用于在低级别(如驱动程序或操作系统核心)处理键盘输入。

虚拟键码(Virtual-Key Code)

虚拟键码是操作系统级的抽象,它将扫描码转换为一个标准化的代码,这反映了按键的“功能”,而不仅仅是位置。例如,无论在哪种键盘布局中,字母“A”的虚拟键码都是相同的,即使其物理位置可能不同。

  • 特点:虚拟键码依赖于键盘布局,因为它反映了按键的逻辑功能(如字符、命令等)。
  • 用途:用于编写应用程序时处理更高级的输入(如文字输入、控制命令等)。

两者的区别

  • 来源:扫描码来自键盘硬件;虚拟键码由操作系统提供。
  • 依赖性:扫描码与键盘布局无关,与物理键位置直接相关;虚拟键码依赖于键盘布局,反映键的逻辑功能。
  • 用途:扫描码通常在较低的系统级别(如操作系统或驱动程序)使用,用于识别物理键位;虚拟键码在更高级的应用程序中使用,用于处理具体的键盘功能,如文本输入或用户界面控制。

三、快捷键Shortcut Keys)和热键(Hotkeys)有什么区别

快捷键(Shortcut Keys)

  • 快捷键通常是指在特定应用程序内部使用的键盘组合,用于执行应用程序的特定功能。这些快捷键只在该应用程序具有焦点时有效。例如,许多应用程序都使用 Ctrl + S 作为保存操作的快捷键。
  • 上下文依赖:快捷键的作用依赖于当前应用程序的状态和哪个窗口或控件有焦点。
  • 实现方式:在应用程序的消息处理逻辑中捕捉和处理特定的 WM_KEYDOWN 或 WM_KEYUP 消息来实现快捷键功能。

热键(Hotkeys)

  • 热键是系统级的键盘快捷键,它们在整个操作系统中都是有效的,无论当前哪个应用程序有焦点。热键通常用于操作系统功能或某些特定应用程序的功能,这些功能需要从任何地方快速访问。
  • 全局作用域:热键无论在哪个应用程序中都能被触发
  • 注册使用:通过使用Windows API的 RegisterHotKey 函数来设置。这个函数允许你定义一个热键和一个与之关联的消息,当热键被按下时,这个消息将被发送到指定的窗口处理。

示例代码

#include <windows.h>//5.消息处理
LRESULT CALLBACK WndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam
)
{// 根据消息类型进行分支处理switch (msg){case WM_CREATE:{//注册热键RegisterHotKey(hwnd, 5566, MOD_CONTROL, VK_F1);return 0;}//键盘消息case WM_KEYDOWN:{//获得键盘状态BYTE KeyState[256];if (GetKeyboardState(KeyState)==0){return TRUE; }//键盘扫描码BYTE ScanCode = (int)lParam >> 16 && 0xff;WORD ch;//将键盘扫描码转换成Ascii码ToAscii(wParam, ScanCode, KeyState, &ch, 0);char buffer[100];wsprintf(buffer, "你按下了:%c\n", ch);OutputDebugString(buffer);return 0;}case WM_CHAR:{char buffer[100];wsprintf(buffer, "你按下了:%c\n", wParam);OutputDebugString(buffer);return 0;}case WM_KEYUP:{return 0;}//热键消息case WM_HOTKEY:{MessageBox(NULL, "HotKey!", "WM_HOTKEY", MB_OK);return 0;}case WM_CLOSE:{//询问是否关闭窗口int id = MessageBox(NULL, "你确定关闭窗口吗", "WM_CLOSE", MB_YESNO);if (id == IDYES){DestroyWindow(hwnd);}return 0;}case WM_DESTROY:{//注销热键UnregisterHotKey(hwnd,5566);PostQuitMessage(0); return 0;}}return DefWindowProc(hwnd, msg, wParam, lParam);}int WINAPI WinMain(HINSTANCE hInstance,     // 当前实例的句柄HINSTANCE hPrevInstance, // 前一个实例的句柄,现在总是为 NULLLPSTR lpCmdLine,         // 命令行参数的字符串int nCmdShow             // 指示程序窗口应如何被显示
)
{//1.注册窗口char MyWindowClassName[] = "MyWindowClass";         //窗口类名WNDCLASSEX wc = { 0 };wc.cbSize = sizeof(WNDCLASSEX);wc.style = CS_VREDRAW | CS_HREDRAW;     //wc.lpfnWndProc = WndProc;    //窗口过程函数(窗口回调函数->处理消息)wc.hInstance = hInstance;wc.hIcon = NULL;             //图标wc.hCursor = NULL;          //光标wc.hbrBackground = CreateSolidBrush(RGB(0, 255, 0));    //窗口背景颜色刷子wc.lpszMenuName = NULL;     //菜单名称wc.lpszClassName = MyWindowClassName;    //窗口类名if (RegisterClassEx(&wc) == 0){return 0;}//2.创建窗口char MyWindowName[] = "MyWindowClass";         //窗口名称HWND hwnd = CreateWindowEx(0,MyWindowClassName,MyWindowName,WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,hInstance,NULL);if (hwnd == NULL){return 0;}//3.显示更新窗口ShowWindow(hwnd, SW_SHOWNORMAL);UpdateWindow(hwnd);//4.消息循环(消息队列)MSG msg = {};while (GetMessage(&msg, NULL, 0, 0)){TranslateMessage(&msg);DispatchMessage(&msg);}return 0;
}

http://www.ppmy.cn/ops/20246.html

相关文章

java算法 递归运算优化(备忘录模式)

一、递归是很常见的一种运算&#xff0c;有明显特征特征的场景一般使用递归比较合适。其一&#xff0c;相邻的数据存在一定的逻辑关系&#xff0c;其二、必须存在出口的值&#xff0c;如第一个元素或者最后元素的值能轻松计算出来。 二、递归和备忘录示例 1、题目&#xff1a;…

Redis篇:缓存雪崩及解决方案

1.何为缓存雪崩 缓存雪崩是指在同一时段大量的缓存key同时失效或者Redis服务宕机&#xff0c;导致大量请求到达数据库&#xff0c;带来巨大压力。 2.缓存雪崩的解决方案 解决方案&#xff1a; 给不同的Key的TTL添加随机值 利用Redis集群提高服务的可用性 给缓存业务添加降级…

Golang函数和包

文章目录 函数基本语法参数传递方式返回值特点可变参数函数类型匿名函数defer机制闭包 包基本概念包的使用init函数 函数 基本语法 基本语法 Go中函数的基本语法如下&#xff1a; 使用案例如下&#xff1a; package mainimport "fmt"// 函数定义 func Factorial(nu…

(python)动态规划

前言 曾经有一位叫做小明的年轻人,他生活在一个被困在连绵不断的山脉中的村庄里。这座村庄每年都会受到洪水的威胁,而村民们只能通过一条崎岖而危险的小路逃离洪水的侵袭。小明决定解决这个问题。他花了很长时间研究了地形图和洪水的模式,最终他发现了一种方法:他可以在山脚…

骑砍2霸主MOD开发(8)-action_sets.xml骨骼动画

一.action_sets.xml 1.文件目录:Modules\Native\ModuleData\action_sets.xml 2.action_set(骨骼动画animation) action1 action2 action3 3.通过在action_set中配置skeleton,人,马匹,牛,羊等骨架 二.使用编辑器修改动作 三.骨架&骨骼&骨骼动画 1.骨架skeleton Skele…

Zabbix 安装部署说明文档

Zabbix是一个开源的网络监控和管理系统&#xff0c;其架构设计用于提供企业级的监控解决方案。以下是Zabbix的主要组件&#xff1a; 1.Zabbix Server&#xff1a;这是Zabbix系统的核心组件&#xff0c;负责接收Agent程序报告的系统可用性、系统完整性和统计数据。Zabbix Serve…

安装配置Maven(idea里面配置)

放在这个路径下&#xff08;如果需要可以免费发给你&#xff0c;dd我就好了&#xff09; D:\IearnSoftware\maven\apache-maven-3.6.1-bin.zip&#xff08;我自己的路径下面&#xff0c;防止忘记&#xff09; 1.首先测试maven在不在&#xff0c;配置对不对 mvn -v 这样就是成…

Python数据分析实验二:Python数据预处理

目录 一、实验目的与要求二、实验任务三、主要程序清单和运行结果&#xff08;一&#xff09;对chipotle.csv文件的销售数据进行分析&#xff08;二&#xff09;对描述泰坦尼克号成员的信息进行可视化和相关分析 四、实验体会 一、实验目的与要求 1、目的&#xff1a;   掌握…