![Windows 如何监听系统热键?](https://linux22.com/image/1614536/Windows%20%E5%A6%82%E4%BD%95%E7%9B%91%E5%90%AC%E7%B3%BB%E7%BB%9F%E7%83%AD%E9%94%AE%EF%BC%9F.png)
对于我正在做的一个项目。我想知道,Windows 10 如何监听系统热键?是否有一些系统服务在后台执行此操作?
我所说的系统热键是指Alt+F4和类似的键。
答案1
当按下某个键时,Windows 内核会从键盘驱动程序接收消息并将其添加到系统消息队列中。这些消息会发送到机器上所有正在运行的程序,包括处理热键按下的程序。
关于哪些程序处理哪些组合键的文档很少,但可以肯定的是,您在任务管理器中看到的 Windows 资源管理器、“Windows 会话管理器”或“Shell 基础结构主机”应用程序负责处理这些组合键。
例如,打开“运行”的Win+R组合键由 Windows 资源管理器处理。如果您从任务管理器关闭 Windows 资源管理器,然后尝试使用该组合键,它将不起作用。更多低级组合键(如Alt+)F4可能由会话管理器或 shell 基础架构主机处理。
因此,没有一个程序可以处理所有组合键。它是多个预装的 Windows 应用程序的混合体。例如,Windows 资源管理器负责 PC 上的大部分 GUI 并处理大量组合键。
编辑:桌面窗口管理器似乎是处理Alt+之类的组合键的管理器F4。
答案2
看https://docs.microsoft.com/en-us/windows/win32/menurc/wm-syscommand以及 wm_command。
这些键在核心 Windows UI dll、user32.dll 中处理。
这是来自编辑器的帮助,解释了如何编程特定的文本编辑器。
Windows 程序的结构
Windows 提供了大量以窗口形式实现的控件。此程序使用 RichEdit 窗口来模拟编辑窗口(记事本使用的窗口)。这为我们提供了类似 Word 的编辑功能,同时仍将其保留为文本。
子主目录
程序启动并注册它将要使用的窗口 (RegisterWindowsEx)。然后它创建窗口和任何子窗口(包括内置控件)(CreateWindowEx)。
它创建菜单和加速键。
它设置了主窗口和 RichEdit 窗口的 100 多个选项。它还告诉 RichEdit 窗口将其收到的某些消息通知主窗口。
然后它会显示窗口并更新它们。您的程序现在作为图形程序运行。
进入循环并将收到的所有消息发送到 DispatchMessage,后者将其发送到主窗口过程或 RichEdit 窗口过程。当窗口关闭时,循环退出,程序结束。
窗口过程
这是窗口程序的核心。该程序有两个窗口:主窗口和 RichEdit 窗口。
程序员必须编写主窗口过程。尽管连接默认管道的过程只有三行代码。
所有窗口都有一个默认的窗口过程。它处理边框、菜单、标题栏、光标、指针等。对于 RichEdit,窗口过程提供了 MS Word 的大多数功能。
窗口管理器会根据消息向任一窗口发送一般窗口消息(如窗口大小调整 wm_size)。编辑控件通知(RichEdit 也发送与编辑控件相同的通知消息)和 RichEdit 通知由 Richedit 窗口发送到主窗口。
我们只处理需要的消息。我们让窗口绘制窗口边框,并将消息传递给我们默认的窗口过程。当我们收到 WM_Command 消息时,我们会像选择菜单项一样处理消息。
如果鼠标指针位于边框、菜单或标题栏上,窗口管理器会将鼠标消息发送到主窗口。如果鼠标指针位于 RichEdit 上,则 RichEdit 窗口将收到这些消息,尽管您可以要求 RichEdit 将它们转发给您,就像此程序对文本已更改和上下文菜单所做的那样。
大多数键都分配给 RichEdit 控件。它具有广泛的键盘编辑界面。系统键(如 Alt + F4)和菜单键(Alt + F)被发送到主窗口,主窗口通常不处理它们,而是将其传递给默认窗口过程。主窗口等待默认过程将其作为要执行的命令发回(如 WM_Close 退出或 WM_Command 用于所选的菜单项)。
除非我们注册其他键,否则它们将转到 RichEdit 窗口。例如:Ctrl + A 选择所有文本并成为 RichEdit 键盘接口的一部分(然后它向主窗口发送选择更改消息)。但是 Ctrl + S 不是 RichEdit 键盘接口的一部分,RichEdit 会忽略它。所以我们需要注册 Ctrl + S,这样主窗口就可以获得它而不是 RichEdit,但不能获得 Ctrl + A。
在 Select Case 函数中,主窗口过程会检查是否要处理该消息。如果不处理,则将调用默认窗口过程,该过程将在必要时处理该消息。
然后
要退出程序,您可以通过向窗口发送 WM_Close 消息来关闭窗口。这将变成您将收到的 WM_Destroy 消息,然后调用 PostQuitMessage。您的窗口过程现已结束。
主循环收到WM_Quit消息并退出循环。
最后两行销毁加速器表和上下文菜单(因为它未分配给窗口)。分配给窗口的其他菜单将自动销毁。程序结束。