c# 快捷键模块

news/2025/1/8 6:58:32/

文章目录

      • 命名空间和类
      • 类成员
        • 静态成员
      • 静态方法
        • `GenerateHotkeyId`
        • `WndProc`
        • `GetWindowHandleAndSource`
        • `Register`
        • `Unregister`
      • 静态方法(外部调用)
        • `RegisterHotKey` 和 `UnRegisterHotKey`
      • 委托
        • `HotKeyCallbackHandler`
      • 枚举
        • `HotkeyModifiers`
    • 应用示例

using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows;
using System.Windows.Input;
using System.Windows.Interop;namespace HotKeyModule
{public static class Hotkey{private static readonly Dictionary<int, HotKeyCallbackHandler> keymap = new Dictionary<int, HotKeyCallbackHandler>();private static int nextHotkeyId = 10;private static readonly object keymapLock = new object();private static int GenerateHotkeyId() => Interlocked.Increment(ref nextHotkeyId);// 窗口消息处理private static IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled){const int WM_HOTKEY = 0x0312;if (msg == WM_HOTKEY){int hotkeyId = wParam.ToInt32();if (keymap.TryGetValue(hotkeyId, out var callback)){callback();handled = true;}}return IntPtr.Zero;}// 获取窗口句柄和HwndSourceprivate static (IntPtr hwnd, HwndSource hwndSource) GetWindowHandleAndSource(Window window){var hwnd = new WindowInteropHelper(window).Handle;var hwndSource = HwndSource.FromHwnd(hwnd) ?? throw new InvalidOperationException("Failed to get HwndSource.");return (hwnd, hwndSource);}// 注册热键public static void Register(Window window, HotkeyModifiers modifiers, Key key, HotKeyCallbackHandler callback){var (hwnd, hwndSource) = GetWindowHandleAndSource(window);hwndSource.AddHook(WndProc);int hotkeyId = GenerateHotkeyId();uint vk = (uint)KeyInterop.VirtualKeyFromKey(key);if (!RegisterHotKey(hwnd, hotkeyId, (uint)modifiers, vk)){throw new InvalidOperationException("Failed to register hotkey. Ensure the key combination is not already in use.");}lock (keymapLock){keymap[hotkeyId] = callback;}}// 注销热键public static void Unregister(Window window, HotKeyCallbackHandler callback){var (hwnd, _) = GetWindowHandleAndSource(window);lock (keymapLock){foreach (var kvp in keymap){if (kvp.Value == callback){UnRegisterHotKey(hwnd, kvp.Key);keymap.Remove(kvp.Key);break;}}}}[DllImport("user32.dll")][return: MarshalAs(UnmanagedType.Bool)]private static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk);[DllImport("user32.dll")][return: MarshalAs(UnmanagedType.Bool)]private static extern bool UnRegisterHotKey(IntPtr hWnd, int id);}// 热键回调委托public delegate void HotKeyCallbackHandler();public enum HotkeyModifiers{ALT = 0x0001,CTRL = 0x0002,SHIFT = 0x0004,WIN = 0x0008,CTRL_ALT = CTRL|ALT,CTRL_SHIFT = CTRL | SHIFT,}
}

命名空间和类

代码定义在一个名为 HotKeyModule 的命名空间中,其中包含一个静态类 Hotkey,用于管理热键的注册和注销。

类成员

静态成员
  1. keymap:

    • 类型:Dictionary<int, HotKeyCallbackHandler>
    • 用途:存储热键ID和对应的回调函数。
  2. nextHotkeyId:

    • 类型:int
    • 用途:生成唯一的热键ID。
    • 初始值:10
  3. keymapLock:

    • 类型:object
    • 用途:用于同步访问 keymap,确保线程安全。

静态方法

GenerateHotkeyId
  • 用途:生成唯一的热键ID。
  • 实现:使用 Interlocked.Increment 方法原子性地增加 nextHotkeyId,并返回其新的值。
WndProc
  • 用途:处理窗口消息,特别是热键消息。
  • 参数:
    • hwnd:窗口句柄
    • msg:消息类型
    • wParam:消息参数
    • lParam:消息参数
    • handled:是否处理了消息
  • 实现:
    • 检查消息类型是否为 WM_HOTKEY(0x0312)。
    • 如果是热键消息,从 wParam 中提取热键ID。
    • keymap 中查找对应的回调函数并执行。
    • handled 设置为 true,表示消息已处理。
GetWindowHandleAndSource
  • 用途:获取窗口句柄和 HwndSource
  • 参数:
    • window:需要处理的 Window 对象
  • 返回:
    • hwnd:窗口句柄
    • hwndSource:与窗口关联的 HwndSource
  • 实现:
    • 使用 WindowInteropHelper 获取窗口句柄。
    • 使用 HwndSource.FromHwnd 获取 HwndSource,如果获取失败则抛出异常。
Register
  • 用途:注册热键。
  • 参数:
    • window:需要注册热键的 Window 对象
    • modifiers:热键修饰符(例如 CTRLALT 等)
    • key:热键按键
    • callback:热键触发时的回调函数
  • 实现:
    • 调用 GetWindowHandleAndSource 获取窗口句柄和 HwndSource
    • WndProc 注册为窗口消息处理函数。
    • 生成唯一的热键ID。
    • 将按键转换为虚拟键码。
    • 调用 RegisterHotKey 函数注册热键,如果注册失败则抛出异常。
    • 将热键ID和回调函数添加到 keymap 中。
Unregister
  • 用途:注销热键。
  • 参数:
    • window:需要注销热键的 Window 对象
    • callback:需要注销的回调函数
  • 实现:
    • 调用 GetWindowHandleAndSource 获取窗口句柄和 HwndSource
    • 升级 keymapLock,确保线程安全。
    • keymap 中查找对应回调函数的热键ID。
    • 调用 UnRegisterHotKey 函数注销热键。
    • keymap 中移除对应的热键ID和回调函数。

静态方法(外部调用)

RegisterHotKeyUnRegisterHotKey
  • 用途:注册和注销热键的外部调用。
  • 参数:
    • hWnd:窗口句柄
    • id:热键ID
    • fsModifiers:热键修饰符
    • vk:虚拟键码
  • 实现:
    • 使用 DllImport 导入 user32.dll 中的 RegisterHotKeyUnRegisterHotKey 函数。

委托

HotKeyCallbackHandler
  • 用途:定义热键回调函数的委托。
  • 类型:public delegate void HotKeyCallbackHandler()

枚举

HotkeyModifiers
  • 用途:定义热键修饰符。
  • 成员:
    • ALT:0x0001
    • CTRL:0x0002
    • SHIFT:0x0004
    • WIN:0x0008
    • CTRL_ALTCTRL | ALT
    • CTRL_SHIFTCTRL | SHIFT

应用示例

这段代码是 OnSourceInitialized 方法的重写,用于在窗口的 SourceInitialized 事件触发时注册热键。SourceInitialized 事件在窗口句柄创建后立即触发。

        protected override void OnSourceInitialized(EventArgs e){Hotkey.Register(this, HotkeyModifiers.CTRL, Key.D, () =>{WindowController.Get<FlowView>().Hide();WindowController.Get<MainView>().Show();});Hotkey.Register(this, HotkeyModifiers.CTRL_ALT, Key.D, () =>{Application.Current.Shutdown();});}

http://www.ppmy.cn/news/1561177.html

相关文章

「Java 数据结构全面解读」:从基础到进阶的实战指南

「Java 数据结构全面解读」&#xff1a;从基础到进阶的实战指南 数据结构是程序设计中的核心部分&#xff0c;用于组织和管理数据。Java 提供了丰富的集合框架和工具类&#xff0c;涵盖了常见的数据结构如数组、链表、栈、队列和树等。本文将系统性地介绍这些数据结构的概念、…

SQL把字符串按逗号分割成记录

在 SQL 中&#xff0c;可以通过以下方法将字符串按逗号分割&#xff0c;并将每个分割的值作为单独的记录插入到结果集中。以下是针对不同数据库系统的实现方法&#xff1a; 1. 使用 STRING_SPLIT&#xff08;SQL Server 2016&#xff09; STRING_SPLIT 是 SQL Server 提供的内置…

【HarmonyOS】:DevEco Studio安装与应用工程创建指南

前言 本文旨在为初涉 HarmonyOS 开发的开发者提供一份详尽的入门指南&#xff0c;涵盖从安装最新版 DevEco Studio 到使用该 IDE 创建首个应用工程的具体步骤。通过遵循本指南&#xff0c;您将能够顺利搭建起自己的开发环境&#xff0c;并迈出构建HarmonyOS应用的第一步。 一、…

Linux 基础七 内存

在操作系统中&#xff0c;进程的内存布局通常分为几个区域&#xff0c;包括代码段、已初始化的数据段、未初始化的数据段&#xff08;BSS段&#xff09;、堆和栈。其中&#xff0c;堆用于动态内存分配&#xff0c;其大小可以在运行时根据需要增长或收缩。 文章目录 7.1 在堆上…

五年制物联网专业智能家居实训室建设方案

一、引言 随着科技的日新月异&#xff0c;人们对生活品质的追求愈发强烈&#xff0c;智能化、舒适化的家居生活成为了新的潮流。早在20世纪80年代&#xff0c;日本和欧洲便率先引领了智能家居的兴起&#xff0c;而我国也在90年代紧随其后&#xff0c;迎来了智能家居产品的萌芽…

被催更了,2025元旦源码继续免费送

“时间从来不会停下&#xff0c;它只会匆匆流逝。抓住每一刻&#xff0c;我们才不会辜负自己。” 联系作者免费领&#x1f496;源&#x1f496;码。 三联支持&#xff1a;点赞&#x1f44d;收藏⭐️留言&#x1f4dd;欢迎留言讨论 更多内容敬请期待。如有需要源码可以联系作者免…

【paddle】初次尝试

张量 张量是 paddlepaddle&#xff0c; torch&#xff0c; tensorflow 等 python 主流机器学习包中唯一通货变量&#xff0c;因此应当了解其基本的功能。 张量 paddle.Tensor 与 numpy.array 的转化 import paddle as paddle import matplotlib.pyplot as plt apaddle.to_t…

什么是Kafka的重平衡机制?

Kafka 的重平衛机制是指在消费者组中新增或删除消费者时&#xff0c;Kafka 集群会重新分配主题分区给各个消费者&#xff0c;以保证每个消费者消费的分区数量尽可能均衡。 重平衡机制的目的是实现消费者的负载均衡和高可用性&#xff0c;以确保每个消费者都能够按照预期的方式…