当前位置: 首页 > news >正文

c# 快捷键模块

文章目录

      • 命名空间和类
      • 类成员
        • 静态成员
      • 静态方法
        • `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();});}

相关文章:

c# 快捷键模块

文章目录 命名空间和类类成员静态成员 静态方法GenerateHotkeyIdWndProcGetWindowHandleAndSourceRegisterUnregister 静态方法&#xff08;外部调用&#xff09;RegisterHotKey 和 UnRegisterHotKey 委托HotKeyCallbackHandler 枚举HotkeyModifiers 应用示例 using System; us…...

【笔记】增值税计算笔记

增值税计算笔记 设 进价为 α \alpha α元 出价为 α τ \alpha\tau ατ元 增值税率为 r r r ∵ { 进 项 税 α 1 r r 销 项 税 α τ 1 r r 增 值 税 销 项 税 − 进 项 税 ∴ 增 值 税 α ( τ − 1 ) r 1 r \because \left\{ \begin{aligned}进项税 &\frac{…...

请解释 JavaScript 中的闭包,以及它的优缺点和常见使用场景?

闭包&#xff08;Closure&#xff09;是什么&#xff1f; 闭包是JavaScript中的一个重要概念&#xff0c;指的是一个函数能够记住并访问它的词法作用域&#xff0c;即使这个函数在其词法作用域之外执行。 换句话说&#xff0c;闭包使得函数可以“记住”它被创建时的环境。 闭…...

SpringBoot 集成 Caffeine 实现本地缓存

目录 1、Caffeine 简介 1.1、Caffeine 简介1.2、对比 Guava cache 的性能主要优化项1.3、常见的缓存淘汰算法1.4、SpringBoot 集成 Caffeine 两种方式 2、SpringBoot 集成 Caffeine 方式一 2.1、缓存加载策略 2.1.1、手动加载2.1.2、自动加载【Loading Cache】2.1.3、异步加载…...

druid连接池参数配置

最近发现生产环境经常有数据库连接超时的问题&#xff0c;排查发现是druid连接池参数设置不合理导致 总结问题如下&#xff1a; 为了防止僵尸连接&#xff0c;k8s ipvs做了连接超时限制&#xff0c;如果TCP连接闲置超过900s(15分钟)&#xff0c;客户端再尝试通过这个连接去发起…...

【OceanBase】通过 OceanBase 的向量检索技术构建图搜图应用

文章目录 一、向量检索概述1.1 关键概念① 非结构化数据② 向量③ 向量嵌入(Embedding)④ 向量相似性检索 1.2 应用场景 二、向量检索核心功能三、图搜图架构四、操作步骤4.1 使用 Docker 部署 OceanBase 数据库4.2 测试OceanBase数据库连通性4.3 开启数据库向量检索功能4.4 克…...

Linux 安装运行gatk的教程

1.下载安装 wget https://github.com/broadinstitute/gatk/releases/download/4.1.8.1/gatk-4.1.8.1.zip2.解压 unzip *.zip3.查看 gatk --help 如下显示表示安装成功&#xff1a; 注意&#xff1a;仅限在该包所在位置的路径下能使用...

什么是unit l2 norm

1. L2 Norm 定义 L2 norm&#xff08;或称欧几里得范数&#xff09;是用来衡量一个向量的“长度”或“大小”的一种方式。在 n 维空间中&#xff0c;给定一个向量V(V1,V2,…,Vn)&#xff0c;其 L2 norm 定义为&#xff1a; 也可以理解为该向量与原点之间的欧几里得距离。 2…...

手写顺序流程图组件

效果图 完整代码 <template><div><div class"container" :style"{ width: ${spacingX * (colNum - 1) itemWidth * colNum}px }"><divv-for"(item, i) in recordList":key"i"class"list-box":style&…...

适配器模式概述

大体介绍 适配器模式&#xff08;Adapter Pattern&#xff09;是一种结构型设计模式&#xff0c;其核心目的是通过提供一个适配器类来使得原本接口不兼容的类可以一起工作。它通过将一个类的接口转换成客户端所期望的接口&#xff0c;使得原本因接口不兼容而无法一起工作的类可…...

Logo设计免费生成器:轻松设计个性化标志

在当今这个信息爆炸的时代&#xff0c;一个好的Logo标志已经成为品牌和企业的名片。它不仅是品牌的象征&#xff0c;也是企业文化和价值观的体现。然而&#xff0c;很多初创企业或小型团队往往因为预算有限&#xff0c;无法请专业的设计师来打造专属的Logo。这时候&#xff0c;…...

智能停车场车牌识别计费系统

作者简介&#xff1a;Java领域优质创作者、CSDN博客专家 、CSDN内容合伙人、掘金特邀作者、阿里云博客专家、51CTO特邀作者、多年架构师设计经验、多年校企合作经验&#xff0c;被多个学校常年聘为校外企业导师&#xff0c;指导学生毕业设计并参与学生毕业答辩指导&#xff0c;…...

谷歌开通第三方平台OAuth登录及Java对接步骤

调研起因&#xff1a; 当然还是因为手头的海外项目&#xff0c;用户注册通常要用邮箱&#xff0c;正常流程需要给用户邮箱发送验证码&#xff0c;再让用户输入密码进行注册。 为了简化流程&#xff0c;让用户使用谷歌邮箱一键完成注册或登录&#xff0c; 我们直接获取谷歌邮箱、…...

人体:精妙绝伦的生命之躯

人体&#xff1a;精妙绝伦的生命之躯 在浩瀚宇宙中&#xff0c;人体犹如一颗璀璨的明珠&#xff0c;是自然界最伟大的杰作之一。它是一个高度复杂且精妙绝伦的有机系统&#xff0c;承载着生命的奥秘与奇迹&#xff0c;展现出令人惊叹的适应性、协调性和自我修复能力。从微观的…...

python的urllib模块和http模块

1.python的urllib库用于操作网页&#xff0c;并对网页内容进行处理 urllib包有如下模块&#xff1a; urllib.request&#xff1a;打开和读取URL urllib.error&#xff1a; 包含urllib.request抛出的异常 urllib.parse&#xff1a; 解析URL urllib.robotparser&#xff1…...

Java [后端] 开发日常记录(1)

目录 1、常用的注解 2、对字符串的处理 3、对JSON串的处理 -- The End -- 详细如下&#xff1a; 1、常用的注解 若返回的字段中有NUll&#xff0c;则不返回 JsonInclude(value JsonInclude.Include.NON_NULL) //在实体类中添加这个注解 JsonInclude(JsonInclude.Include.NON…...

jetbrain 安装 copilot

问题一&#xff1a;Sign in failed. Reason: Request signInInitiate failed with message: Request to /github.com/login/device/code> timed out after 30000ms, request id: 11, error code: -32603 解决方案&#xff1a; 参考资料&#xff1a;https://github.com/orgs/…...

万里数据库GreatSQL监控解析

GreatSQL是MySQL的一个分支&#xff0c;专注于提升MGR&#xff08;MySQL Group Replication&#xff09;的可靠性及性能。乐维监控平台可以有效地监控GreatSQL&#xff0c;帮助用户及时发现并解决潜在的性能问题。 通过在GreatSQL服务器上安装监控代理&#xff0c;收集数据库性…...

OpenCV-Python实战(9)——滤波降噪

一、均值滤波器 cv2.blur() img cv2.blur(src*,ksize*,anchor*,borderType*)img&#xff1a;目标图像。 src&#xff1a;原始图像。 ksize&#xff1a;滤波核大小&#xff0c;&#xff08;width&#xff0c;height&#xff09;。 anchor&#xff1a;滤波核锚点&#xff0c…...

Pytorch | 利用DTA针对CIFAR10上的ResNet分类器进行对抗攻击

Pytorch | 利用DTA针对CIFAR10上的ResNet分类器进行对抗攻击 CIFAR数据集DTA介绍算法流程 DTA代码实现DTA算法实现攻击效果 代码汇总dta.pytrain.pyadvtest.py 之前已经针对CIFAR10训练了多种分类器&#xff1a; Pytorch | 从零构建AlexNet对CIFAR10进行分类 Pytorch | 从零构建…...

汇编常见指令

汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX&#xff08;不访问内存&#xff09;XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...

Swagger和OpenApi的前世今生

Swagger与OpenAPI的关系演进是API标准化进程中的重要篇章&#xff0c;二者共同塑造了现代RESTful API的开发范式。 本期就扒一扒其技术演进的关键节点与核心逻辑&#xff1a; &#x1f504; 一、起源与初创期&#xff1a;Swagger的诞生&#xff08;2010-2014&#xff09; 核心…...

Angular微前端架构:Module Federation + ngx-build-plus (Webpack)

以下是一个完整的 Angular 微前端示例&#xff0c;其中使用的是 Module Federation 和 npx-build-plus 实现了主应用&#xff08;Shell&#xff09;与子应用&#xff08;Remote&#xff09;的集成。 &#x1f6e0;️ 项目结构 angular-mf/ ├── shell-app/ # 主应用&…...

Mysql中select查询语句的执行过程

目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析&#xff08;Parser&#xff09; 2.4、执行sql 1. 预处理&#xff08;Preprocessor&#xff09; 2. 查询优化器&#xff08;Optimizer&#xff09; 3. 执行器…...

RabbitMQ入门4.1.0版本(基于java、SpringBoot操作)

RabbitMQ 一、RabbitMQ概述 RabbitMQ RabbitMQ最初由LShift和CohesiveFT于2007年开发&#xff0c;后来由Pivotal Software Inc.&#xff08;现为VMware子公司&#xff09;接管。RabbitMQ 是一个开源的消息代理和队列服务器&#xff0c;用 Erlang 语言编写。广泛应用于各种分布…...

【MATLAB代码】基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),附源代码|订阅专栏后可直接查看

文章所述的代码实现了基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),针对传感器观测数据中存在的脉冲型异常噪声问题,通过非线性加权机制提升滤波器的抗干扰能力。代码通过对比传统KF与MCC-KF在含异常值场景下的表现,验证了后者在状态估计鲁棒性方面的显著优…...

WebRTC从入门到实践 - 零基础教程

WebRTC从入门到实践 - 零基础教程 目录 WebRTC简介 基础概念 工作原理 开发环境搭建 基础实践 三个实战案例 常见问题解答 1. WebRTC简介 1.1 什么是WebRTC&#xff1f; WebRTC&#xff08;Web Real-Time Communication&#xff09;是一个支持网页浏览器进行实时语音…...

django blank 与 null的区别

1.blank blank控制表单验证时是否允许字段为空 2.null null控制数据库层面是否为空 但是&#xff0c;要注意以下几点&#xff1a; Django的表单验证与null无关&#xff1a;null参数控制的是数据库层面字段是否可以为NULL&#xff0c;而blank参数控制的是Django表单验证时字…...

Spring Security 认证流程——补充

一、认证流程概述 Spring Security 的认证流程基于 过滤器链&#xff08;Filter Chain&#xff09;&#xff0c;核心组件包括 UsernamePasswordAuthenticationFilter、AuthenticationManager、UserDetailsService 等。整个流程可分为以下步骤&#xff1a; 用户提交登录请求拦…...

基于江科大stm32屏幕驱动,实现OLED多级菜单(动画效果),结构体链表实现(独创源码)

引言 在嵌入式系统中&#xff0c;用户界面的设计往往直接影响到用户体验。本文将以STM32微控制器和OLED显示屏为例&#xff0c;介绍如何实现一个多级菜单系统。该系统支持用户通过按键导航菜单&#xff0c;执行相应操作&#xff0c;并提供平滑的滚动动画效果。 本文设计了一个…...