C# 禁用 全局快捷键

本文经原作者授权以原创方式二次分享,欢迎转载、分享。

原文作者:唐宋元明清

原文地址:https://www.cnblogs.com/kybs0/p/12558056.html

 C# 禁用 全局快捷键
给软件添加快捷键时,经常遇到其它软件或者系统已设置的快捷键,导致功能冲突。

HotKey函数

  • 下面介绍一个user32.dllRegisterHotKey以及UnregisterHotKey热键处理的函数;

    • 注册热键 RegisterHotKey function [1];

BOOL RegisterHotKey(HWND hWnd, //响应热键的窗口句柄,如果为空,则注册到调用线程上Int id, //热键的唯一标识UINT fsModifiers, //热键的辅助按键UINT vk //热键的键值
);
    • 解除注册热键UnregisterHotKey function [2];

BOOL WINAPI UnregisterHotKey( HWND hWnd,//热键注册的窗口 int  id//要解除注册的热键ID 
);

添加热键注册和注销函数

Register方法 -  注册user32.dll函数RegisterHotKey以禁用全局键,并在缓存内添加禁用记录;

ProcessHotKey方法 - 外界全局键调用时,调用回调函数;

public class HotKeys{#region 注册快捷键/// <summary>/// 注册快捷键/// </summary>/// <param name="modifiers"></param>/// <param name="key"></param>public void Register(int modifiers, Keys key){Register(IntPtr.Zero, modifiers, key);}/// <summary>/// 注册快捷键/// </summary>/// <param name="hWnd"></param>/// <param name="modifiers"></param>/// <param name="key"></param>/// <param name="callBack"></param>public void Register(IntPtr hWnd, int modifiers, Keys key, HotKeyCallBackHanlder callBack = null){var registerRecord = _hotkeyRegisterRecords.FirstOrDefault(i => i.IntPtr == hWnd && i.Modifiers == modifiers && i.Key == key);if (registerRecord != null){UnregisterHotKey(hWnd, registerRecord.Id);_hotkeyRegisterRecords.Remove(registerRecord);}int id = registerId++;if (!RegisterHotKey(hWnd, id, modifiers, key))throw new Exception("注册失败!");_hotkeyRegisterRecords.Add(new HotkeyRegisterRecord(){Id = id,IntPtr = hWnd,Modifiers = modifiers,Key = key,CallBack = callBack});}#endregion#region 注销快捷键/// <summary>/// 注销快捷键/// </summary>/// <param name="hWnd"></param>/// <param name="modifiers"></param>/// <param name="key"></param>public void UnRegister(IntPtr hWnd, int modifiers, Keys key){var registerRecord = _hotkeyRegisterRecords.FirstOrDefault(i => i.IntPtr == hWnd && i.Modifiers == modifiers && i.Key == key);if (registerRecord != null){UnregisterHotKey(hWnd, registerRecord.Id);_hotkeyRegisterRecords.Remove(registerRecord);}}/// <summary>/// 注销快捷键/// </summary>/// <param name="modifiers"></param>/// <param name="key"></param>public void UnRegister(int modifiers, Keys key){var registerRecord = _hotkeyRegisterRecords.FirstOrDefault(i => i.IntPtr == IntPtr.Zero && i.Modifiers == modifiers && i.Key == key);if (registerRecord != null){UnregisterHotKey(IntPtr.Zero, registerRecord.Id);_hotkeyRegisterRecords.Remove(registerRecord);}}/// <summary>/// 注销快捷键/// </summary>/// <param name="hWnd"></param>public void UnRegister(IntPtr hWnd){var registerRecords = _hotkeyRegisterRecords.Where(i => i.IntPtr == hWnd);//注销所有foreach (var registerRecord in registerRecords){UnregisterHotKey(hWnd, registerRecord.Id);_hotkeyRegisterRecords.Remove(registerRecord);}}#endregion#region 快捷键消息处理// 快捷键消息处理public void ProcessHotKey(Message message){ProcessHotKey(message.Msg, message.WParam);}/// <summary>/// 快捷键消息处理/// </summary>/// <param name="msg"></param>/// <param name="wParam">消息Id</param>public void ProcessHotKey(int msg, IntPtr wParam){if (msg == 0x312){int id = wParam.ToInt32();var registerRecord = _hotkeyRegisterRecords.FirstOrDefault(i => i.Id == id);registerRecord?.CallBack?.Invoke();}}#endregion#region MyRegion//引入系统API[DllImport("user32.dll")]static extern bool RegisterHotKey(IntPtr hWnd, int id, int modifiers, Keys vk);[DllImport("user32.dll")]static extern bool UnregisterHotKey(IntPtr hWnd, int id);//标识-区分不同的快捷键int registerId = 10;//添加key值注册字典,后续调用时有回调处理函数private readonly List<HotkeyRegisterRecord> _hotkeyRegisterRecords = new List<HotkeyRegisterRecord>();public delegate void HotKeyCallBackHanlder();#endregion}public class HotkeyRegisterRecord{public IntPtr IntPtr { get; set; }public int Modifiers { get; set; }public Keys Key { get; set; }public int Id { get; set; }public HotKeys.HotKeyCallBackHanlder CallBack { get; set; }}//组合控制键public enum HotkeyModifiers{Alt = 1,Control = 2,Shift = 4,Win = 8}
  • 在上方的HotKeys类中,注册方法Register提供了一个回调函数,后续监听到外界全局键时,可以通知回调函数处理。

  • 参数WParam,是窗口响应时快捷键值,在winformWPF窗口消息函数中都是有的。

  • 另,组合快捷键内部枚举类HotkeyModifiers,枚举值来自官网文档WM_HOTKEY message;

无感知禁用全局快捷键

比如:

  • 禁用Ctrl+Alt+1、Ctrl+Alt+2、Ctrl+Alt+3、Ctrl+Alt+4(Windows桌面图标大小的调节快捷键);

HotKeys hotKeys = new HotKeys();hotKeys.Register((int)HotkeyModifiers.Control, Keys.N);hotKeys.Register((int)HotkeyModifiers.Control + (int)HotkeyModifiers.Alt, Keys.D1);hotKeys.Register((int)HotkeyModifiers.Control + (int)HotkeyModifiers.Alt, Keys.D2);hotKeys.Register((int)HotkeyModifiers.Control + (int)HotkeyModifiers.Alt, Keys.D3);hotKeys.Register((int)HotkeyModifiers.Control + (int)HotkeyModifiers.Alt, Keys.D4);

注:

  • 窗口句柄参数,如果提供空的话,则注册到调用线程上。

  • Keys类型在system.windows.Forms程序集下,如果是WPFKey,可以使用KeyInteropWpf键值类型转换为Winform键值再调用此函数。

无感知禁用全局快捷键后回调

如果禁用全局快捷键的同时,外界触发快捷键时需要此程序回调处理,可以添加窗口消息处理:

1) 新建一个类HotKeyHandleWindow,继承自Window;

  • 窗口样式 - 高宽为0,窗口样式None;

  • 添加热键注册的调用;

  • 添加WndProc,处理窗口消息;

public class HotKeyHandleWindow : Window{private readonly HotKeys _hotKeys = new HotKeys();public HotKeyHandleWindow(){WindowStyle = WindowStyle.None;Width = 0;Height = 0;Loaded += (s, e) =>{//这里注册了Ctrl+Alt+1 快捷键_hotKeys.Register(new WindowInteropHelper(this).Handle,(int)HotkeyModifiers.Control + (int)HotkeyModifiers.Alt, Keys.D1, CallBack);};}protected override void OnSourceInitialized(EventArgs e){base.OnSourceInitialized(e);var hwndSource = PresentationSource.FromVisual(this) as HwndSource;hwndSource?.AddHook(new HwndSourceHook(WndProc));}public IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled){//窗口消息处理函数_hotKeys.ProcessHotKey(msg, wParam);return hwnd;}//按下快捷键时被调用的方法public void CallBack(){}}

2)调用窗口类;

var hotKeyHandleWindow = new HotKeyHandleWindow();
hotKeyHandleWindow.Show();
hotKeyHandleWindow.Hide();

以上有回调响应,但是也是无感知的

源码下载[3]

参考资料

[1]

RegisterHotKey function : https://docs.microsoft.com/zh-cn/windows/win32/api/winuser/nf-winuser-registerhotkey?redirectedfrom=MSDN

[2]

UnregisterHotKey function : https://docs.microsoft.com/zh-cn/windows/win32/api/winuser/nf-winuser-unregisterhotkey

[3]

源码下载: https://github.com/Kybs0/DiableGlobalShortcuts

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/284829.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SegmentFault Hackathon 文艺复兴

我有一个 idea&#xff0c;我想实现它&#xff0c;我正实现它&#xff0c;我已实现它。世界上存在一些好奇心旺盛、不爱墨守成规的人&#xff0c;略微偏执但又极度投入的他们崇尚自由&#xff0c;热衷用技术实现自己的想法&#xff0c;他们带着不羁的态度生活&#xff0c;利用编…

卧槽!VS Code 上竟然也能画流程图了???

作为一款开源的主流代码编辑器&#xff0c;VSCode 在发布之后一直受到不少开发者的喜爱。 此前&#xff0c;我们也曾在公众号上分享过多篇文章&#xff0c;向大家推荐了不少 VSCode 上比较实用&#xff08;或沙雕&#xff09;的插件。因此&#xff0c;有很多水友也经常调侃道&…

【QGIS入门实战精品教程】14.1:QGIS如何加载各种在线地图?

文章目录 一、XYZ Tiles连接方式二、插件添加三、WMS/WMTS/OWS连接方式一、XYZ Tiles连接方式 1. 加载OpenStreetMap QGIS默认可以加载OpenStreetMap地图。在左侧点击XYZ Tiles,默认下面有个OpenStreetMap选项,双击打右侧会显示地图,如下图所示: 在OpenStreetMap上右键→…

Oracle11g不能导出空表问题

ORACLE 11g 用exp命令导出库文件备份时&#xff0c;发现只能导出来一部分表而且不提示错误&#xff0c;之前找不到解决方案只能把没导出来的表重新建建立。后来发现是所有的空表都没有导出来。于是想好好查查,因为在以前的10g版本中没有这样的问题。查资料发现Oracle 11g中有个…

SkiaSharp 之 WPF 自绘时钟(案例版)

SkiaSharp是一个跨平台2D图形API&#xff0c;用于.NET平台&#xff0c;基于Googles Skia Graphics库(skia.org网站). 它提供了一个全面的2D API&#xff0c;可以跨移动、服务器和桌面模型来渲染图像。该图形库可实现获取指定坐标像素值、绘制2d图形、绘制文字&#xff08;必须有…

推荐一简单易用的脑图制作工具

幕布是什么&#xff1f; 大纲文档工具&#xff0c;管理你的大脑层级折叠文字&#xff0c;结构化思考助手一键转换思维导图并编辑&#xff0c;效率翻倍幕布可以做什么&#xff1f; 大纲笔记&#xff0c;思维整理 学习笔记清单工具 管理日程管理待办购物清单等等内容创作会议记录…

自动性能统计信息(三)(Automatic Performance Statistics)

1.3 管理自动工作负载库&#xff08;AWR&#xff09;本节讲述如何管理AWR&#xff0c;包含以下主题&#xff1a; 管理快照 管理基线 管理基线模板 传输自动工作负载库数据 使用自动工作负载库视图 生成AWR报告 生成AWR对比报告 生成ASH报告 …

su: user tomcat does not exist

http://www.cnblogs.com/allegro/p/5005352.html 问题在于 你的startup.sh 里面设置了 用户,你需要修改为root或者tomcat用户 这是开发 迁移碰到的问题 test ".$TOMCAT_USER" . && TOMCAT_USERtomcat # Set JAVA_HOME to working JDK or JRE # JAVA_HOME/op…

【QGIS入门实战精品教程】4.5:QGIS打开Excel中的点坐标,并生成矢量文件

QGIS中可以很方便添加Excel或其他文本格式的点坐标,并将其转为矢量等多种格式的文件。 扩展阅读: 【ArcGIS风暴】ArcGIS 10.2导入Excel数据X、Y坐标(经纬度、平面坐标),生成Shapefile点数据图层 文章目录 1. 数据准备2. 添加数据3. 保存文矢量文件1. 数据准备 本实验使用…

[NOI2014]起床困难综合症

从高位往地位贪心即可 # include <bits/stdc.h> # define IL inline # define RG register # define Fill(a, b) memset(a, b, sizeof(a)) using namespace std; typedef long long ll; const int _(1e5 10);IL ll Read(){RG char c getchar(); RG ll x 0, z 1;for(;…

腾讯云EKS 上部署 eshopondapr

腾讯云容器服务&#xff08;Tencent Kubernetes Engine&#xff0c;TKE&#xff09;基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务。腾讯云容器服务完全兼容原生 kubernetes API &#xff0c;扩展了腾讯云的云硬盘、负载均衡等 kubernetes 插件&…

[转]一往无前 | 小米十周年,雷军公开演讲全文

2020年8月11日19:30&#xff0c;小米十周年&#xff0c;雷军公开演讲如约而至。在近3小时的演讲中&#xff0c;雷军用20个故事回顾了小米过去的热血10年&#xff0c;也展望了新的10年&#xff1a; - 创新之火将会照亮每个疯狂的想法&#xff0c;小米将成为工程师向往的圣地。 -…

JAVA单例之我见

为什么80%的码农都做不了架构师&#xff1f;>>> 单例模式作为设计模式中最简单的一种&#xff0c;是一个被说烂了的东西。但是在项目中还是会发现关于单例模式的一些错误实现&#xff0c;可见单例也并不是我们想象的那么简单。最近陆陆续续看了几篇关于单例的博客&…

「刘一哥GIS」系列专栏《QGIS入门实战精品教程(配套案例数据)》

「刘一哥GIS」系列专栏《QGIS入门实战精品教程&#xff08;配套案例数据&#xff09;》全新上线了&#xff0c;欢迎广大GISer朋友关注&#xff0c;一起探索GIS奥秘&#xff0c;分享GIS价值&#xff01; 本专栏以实战案例的形式&#xff0c;深入浅出地介绍了QGIS的基本使用方法&…

MyEclipse的Git配置

1.下载&#xff1a;git的插件egit 并解压 插件 下载地址&#xff1a;http://www.eclipse.org/egit/download/ 所有版本&#xff1a;http://wiki.eclipse.org/EGit/FAQ#Where_can_I_find_older_releases_of_EGit.3F 2.在MyEclipse安装目录下的dropins文件夹下创建egit文件夹 3.…

ASP.NET Core 定时刷新第三方 Token

前言在《ASP.NET Core 自动刷新JWT Token》中我们实现了为客户端自动提供最新的Token。但是&#xff0c;当我们的 ASP.NET Core 应用需要调用第三方 API 时&#xff0c;如何更优雅地刷新第三方提供的 Token 呢&#xff1f;思路我们可以在启动时就获取第三方提供的 Token 并保存…

VSCode 插件开发实例(WebView):微信读书 ^-^边撸代码边看小说^-^

最终效果 主要代码 package.json {"name": "WeReadForVSCodeJackieZheng","repository": {"type": "git","url": "https://github.com/JackieZheng/WeReadForVSCode.git"},"displayName": &q…

【QGIS入门实战精品教程】4.7:QGIS如何将矢量数据转为GeoJSON格式?

本文以案例的形式,讲述在QGIS专业软件中,将矢量数据转为GeoJSON的方法。 扩展阅读: 【ArcGIS风暴】如何将矢量数据(点、线、面)折点坐标转为GeoJSON格式? 在QGIS中,可以直接将数据导出为GeoJSON格式。具体操作方法是:右键矢量数据图层→导出图层→到文件,如下图所示:…

Git的纯命令操作,Install,Clone , Commit,Push,Pull,版本回退,撤销更新,分支的创建/切换/更新/提交/合并,代码冲突...

Git的纯命令操作&#xff0c;Install&#xff0c;Clone , Commit&#xff0c;Push&#xff0c;Pull&#xff0c;版本回退&#xff0c;撤销更新&#xff0c;分支的创建/切换/更新/提交/合并&#xff0c;代码冲突 这篇是接着上篇分布式版本库——Windows下Git的环境部署以及在Git…

掌握jQuery插件开发

在实际开发工作中&#xff0c;总会碰到像滚动&#xff0c;分页&#xff0c;日历等展示效果的业务需求&#xff0c;对于接触过jQuery以及熟悉jQuery使用的人来说&#xff0c;首先想到的肯定是寻找现有的jQuery插件来满足相应的展示需求。目前页面中常用的一些组件&#xff0c;都…