如何创建全局热键?

2023-12-28

我想创建一个热键,因此当您按下时,它应该将一些字节写入我附加的进程中的内存地址。 到目前为止,我有这段代码,但似乎只有当我专注于主应用程序时它才有效,否则它将无法工作。 我想让它工作,所以它会做我想做的事,即使我不关注主应用程序。

       private void MainPage_KeyDown(object sender, KeyEventArgs e)
        {
                if (e.KeyCode == Keys.F1)
                {
                 //my code here
                }
        }

我有一门课:

/// <summary>
/// Hook del teclado.
/// </summary>
public class KeyboardHook : IDisposable
{
    /// <summary>
    /// Identificador del hook de teclado.
    /// </summary>
    private static IntPtr _hookId;

    /// <summary>
    /// Número de hooks asociados.
    /// </summary>
    private static readonly List<KeyboardHook> HooksObjects = new List<KeyboardHook>();

    public KeyboardHook()
    {
        OnCreateKeyboardHook(this);
    }

    public KeyboardHook(Form form)
    {
        OnCreateKeyboardHook(this);

        form.Closed += (sender, e) => this.Dispose();
    }

    /// <summary>
    /// Ocurre al pulsar una tecla.
    /// </summary>
    public event EventHandler<KeyEventArgs> KeyDown;

    /// <summary>
    /// Ocurre al soltar una tecla.
    ///  </summary>
    public event EventHandler<KeyEventArgs> KeyUp;

    public void Dispose()
    {
        HooksObjects.Remove(this);

        if (HooksObjects.Count == 0)
        {
            UnhookWindowsHookEx(_hookId);
        }
    }

    /// <summary>
    /// Invocado al crear un objeto <see cref="KeyboardHook"/>.
    /// </summary>
    /// <param name="obj">Objeto <see cref="KeyboardHook"/>.</param>
    private static void OnCreateKeyboardHook(KeyboardHook obj)
    {
        if (HooksObjects.Count == 0)
        {
            _hookId = SetHook(KeyboardProc);
        }

        HooksObjects.Add(obj);
    }

    /// <summary>
    /// Establece el hook de teclado.
    /// </summary>
    /// <param name="proc">Función a invocar cuando se pulsa una tecla.</param>
    /// <returns>El identificador del hook.</returns>
    private static IntPtr SetHook(LowLevelKeyboardProc proc)
    {
        using (var curProcess = Process.GetCurrentProcess())
        using (var curModule = curProcess.MainModule)
        {
            var modHandle = GetModuleHandle(curModule.ModuleName);
            return SetWindowsHookEx(WH_KEYBOARD_LL, proc, modHandle, 0);
        }
    }

    /// <summary>
    /// Mantenemos una referencia para evitar una excepción.
    /// </summary>
    private static readonly LowLevelKeyboardProc KeyboardProc = HookCallback;

    private delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);

    #region Native

    private const int WH_KEYBOARD_LL = 13;

    private const int WM_KEYDOWN = 0x0100;

    private const int WM_KEYUP = 0x0101;

    private const int WM_SYSKEYDOWN = 0x0104;

    private const int WM_SYSKEYUP = 0x0105;

    private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
    {
        if (nCode >= 0)
        {
            var keyDown = wParam == (IntPtr)WM_KEYDOWN || wParam == (IntPtr)WM_SYSKEYDOWN;
            if (keyDown || wParam == (IntPtr)WM_KEYUP || wParam == (IntPtr)WM_SYSKEYUP)
            {
                var kbd = (KBDLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(KBDLLHOOKSTRUCT));
                
                var vkCode = kbd.vkCode;
                var key = (Keys) vkCode;

                if (keyDown)
                {
                    if ((Keys) vkCode != Keys.Alt && (Control.ModifierKeys & Keys.Alt) != 0)
                    {
                        key |= Keys.Alt;
                    }

                    if ((Keys) vkCode != Keys.Control && (Control.ModifierKeys & Keys.Control) != 0)
                    {
                        key |= Keys.Control;
                    }

                    if ((Keys) vkCode != Keys.Shift && (Control.ModifierKeys & Keys.Shift) != 0)
                    {
                        key |= Keys.Shift;
                    }
                }
                else
                {
                    var flags = kbd.flags;
                    if (flags == KBDLLHOOKSTRUCTFlags.LLKHF_ALTDOWN)
                    {
                        key = key | Keys.Alt;
                    }
                    else if (flags == 0x00)
                    {
                        key = key | Keys.Control;
                    }
                }

                var e = new KeyEventArgs(key) { Handled = false };

                foreach (var hookObject in HooksObjects)
                {
                    if (keyDown)
                    {
                        hookObject.KeyDown?.Invoke(hookObject, e);
                    }
                    else
                    {
                        hookObject.KeyUp?.Invoke(hookObject, e);
                    }
                }
            }
        }

        return CallNextHookEx(_hookId, nCode, wParam, lParam);
    }

    [StructLayout(LayoutKind.Sequential)]
    public class KBDLLHOOKSTRUCT
    {
        public uint vkCode;
        public uint scanCode;
        public KBDLLHOOKSTRUCTFlags flags;
        public uint time;
        public UIntPtr dwExtraInfo;
    }

    [Flags]
    public enum KBDLLHOOKSTRUCTFlags : uint
    {
        LLKHF_EXTENDED = 0x01,
        LLKHF_INJECTED = 0x10,
        LLKHF_ALTDOWN = 0x20,
        LLKHF_UP = 0x80,
    }

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod,
        uint dwThreadId);

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool UnhookWindowsHookEx(IntPtr hhk);

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);

    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern IntPtr GetModuleHandle(string lpModuleName);

    #endregion
}

您可以使用任何构造函数为键盘创建一个钩子。如果您正在使用表单,请使用该构造函数,当表单关闭时,挂钩将被释放。处理钩子非常重要,因为它适用于操作系统级别。

使用键盘挂钩,您可以在任何应用程序中按下所有按键,无论是否有焦点。

只需创建挂钩并以与在 Form 控件中执行的操作相同的形式设置事件 KeyDown 和/或 KeyUp 即可。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何创建全局热键? 的相关文章

  • 通过 CMIS (dotCMIS) 连接到 SP2010:异常未经授权

    我正在使用 dotCMIS 并且想要简单连接到我的 SP2010 服务器 我尝试用 C 来做到这一点 如下所示http chemistry apache org dotnet getting started with dotcmis htm
  • “构建”构建我的项目,“构建解决方案”则不构建

    我刚刚开始使用VS2010 我有一个较大的解决方案 已从 VS2008 成功迁移 我已将一个名为 Test 的控制台应用程序项目添加到解决方案中 选择构建 gt 构建解决方案不编译新项目 选择构建 gt 构建测试确实构建了项目 在失败的情况
  • ASP.NET MVC:这个业务逻辑应该放在哪里?

    我正在开发我的第一个真正的 MVC 应用程序 并尝试遵循一般的 OOP 最佳实践 我正在将控制器中的一些简单业务逻辑重构到我的域模型中 我最近一直在阅读一些内容 很明显我应该将逻辑放在域模型实体类中的某个位置 以避免出现 贫血域模型 反模式
  • BitTorrent 追踪器宣布问题

    我花了一点业余时间编写 BitTorrent 客户端 主要是出于好奇 但部分是出于提高我的 C 技能的愿望 我一直在使用理论维基 http wiki theory org BitTorrentSpecification作为我的向导 我已经建
  • 在 Windows 窗体中保存带有 Alpha 通道的单色位图会保存不同(错误)的颜色

    在 C NET 2 0 Windows 窗体 Visual Studio Express 2010 中 我保存由相同颜色组成的图像 Bitmap bitmap new Bitmap width height PixelFormat Form
  • 将 VSIX 功能添加到 C# 类库

    我有一个现有的单文件生成器 位于 C 类库中 如何将 VSIX 项目级功能添加到此项目 最终目标是编译我的类库项目并获得 VSIX 我实际上是在回答我自己的问题 这与Visual Studio 2017 中的单文件生成器更改 https s
  • C# 中通过 Process.Kill() 终止的进程的退出代码

    如果在我的 C 应用程序中 我正在创建一个可以正常终止或开始行为异常的子进程 在这种情况下 我通过调用 Process Kill 来终止它 但是 我想知道该进程是否已退出通常情况下 我知道我可以获得终止进程的错误代码 但是正常的退出代码是什
  • 使用 WebClient 时出现 System.Net.WebException:无法创建 SSL/TLS 安全通道

    当我执行以下代码时 System Net ServicePointManager ServerCertificateValidationCallback sender certificate chain errors gt return t
  • 带动态元素的 WPF 启动屏幕。如何?

    我是 WPF 新手 我需要一些帮助 我有一个加载缓慢的 WPF 应用程序 因此我显示启动屏幕作为权宜之计 但是 我希望能够在每次运行时更改屏幕 并在文本区域中显示不同的引言 这是一个生产力应用程序 所以我将使用非愚蠢但激励性的引言 当然 如
  • WCF 中 SOAP 消息的数字签名

    我在 4 0 中有一个 WCF 服务 我需要向 SOAP 响应添加数字签名 我不太确定实际上应该如何完成 我相信响应应该类似于下面的链接中显示的内容 https spaces internet2 edu display ISWG Signe
  • 如何设计以 char* 指针作为类成员变量的类?

    首先我想介绍一下我的情况 我写了一些类 将 char 指针作为私有类成员 而且这个项目有 GUI 所以当单击按钮时 某些函数可能会执行多次 这些类是设计的单班在项目中 但是其中的某些函数可以执行多次 然后我发现我的项目存在内存泄漏 所以我想
  • SolrNet连接说明

    为什么 SolrNet 连接的容器保持静态 这是一个非常大的错误 因为当我们在应用程序中向应用程序发送异步请求时 SolrNet 会表现异常 在 SolrNet 中如何避免这个问题 class P static void M string
  • 转发声明和包含

    在使用库时 无论是我自己的还是外部的 都有很多带有前向声明的类 根据情况 相同的类也包含在内 当我使用某个类时 我需要知道该类使用的某些对象是前向声明的还是 include d 原因是我想知道是否应该包含两个标题还是只包含一个标题 现在我知
  • 如何在 C 中调用采用匿名结构的函数?

    如何在 C 中调用采用匿名结构的函数 比如这个函数 void func struct int x p printf i n p x 当提供原型的函数声明在范围内时 调用该函数的参数必须具有与原型中声明的类型兼容的类型 其中 兼容 具有标准定
  • 垃圾收集器是否在单独的进程中运行?

    垃圾收集器是否在单独的进程中启动 例如 如果我们尝试测量某段代码所花费的进程时间 并且在此期间垃圾收集器开始收集 它会在新进程上启动还是在同一进程中启动 它的工作原理如下吗 Code Process 1 gt Garbage Collect
  • 链接器错误:已定义

    我尝试在 Microsoft Visual Studio 2012 中编译我的 Visual C 项目 使用 MFC 但出现以下错误 error LNK2005 void cdecl operator new unsigned int 2
  • 基于 OpenCV 边缘的物体检测 C++

    我有一个应用程序 我必须检测场景中某些项目的存在 这些项目可以旋转并稍微缩放 更大或更小 我尝试过使用关键点检测器 但它们不够快且不够准确 因此 我决定首先使用 Canny 或更快的边缘检测算法 检测模板和搜索区域中的边缘 然后匹配边缘以查
  • 混合 ExecutionContext.SuppressFlow 和任务时 AsyncLocal.Value 出现意外值

    在应用程序中 由于 AsyncLocal 的错误 意外值 我遇到了奇怪的行为 尽管我抑制了执行上下文的流程 但 AsyncLocal Value 属性有时不会在新生成的任务的执行范围内重置 下面我创建了一个最小的可重现示例来演示该问题 pr
  • 是否可以在 .NET Core 中将 gRPC 与 HTTP/1.1 结合使用?

    我有两个网络服务 gRPC 客户端和 gRPC 服务器 服务器是用 NET Core编写的 然而 客户端是托管在 IIS 8 5 上的 NET Framework 4 7 2 Web 应用程序 所以它只支持HTTP 1 1 https le
  • 使用.NET技术录制屏幕视频[关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 有没有一种方法可以使用 NET 技术来录制屏幕 无论是桌面还是窗口 我的目标是免费的 我喜欢小型 低

随机推荐

  • 除 ctrl-C 之外的另一种退出 IEX 的方法

    我知道我们可以使用 control C 退出 IEX 控制台 我很好奇是否有一个在控制台中输入的命令也可以做同样的事情 我可以想到退出 IEx shell 的 3 种方法 其中提到的
  • Charles Web 调试代理未检测到 VPN 连接

    我有一个 VPN 连接 正在使用 Charles Web 调试代理测试一些网站 但 Charles 似乎没有检测到我的 VPN 连接 因为它没有检测到我在 VPN 网络上运行的网站 有什么帮助吗 谢谢 我在 Mac 上遇到了同样的问题 但能
  • Spring Boot + Spring Security 授权成功审核

    有没有人设法让 Spring Boot 和 Spring Security 来处理 AuthorizedEvent 即审计日志 我已经实现了以下应用程序事件侦听器 Component public class AuthorizationSu
  • Sublime Text 3:从整个项目的任何地方自动完成?

    我想知道是否有任何方法可以从 Sublime 项目中的任何地方获得智能自动完成功能 我发现很酷的包叫全部自动完成 https sublime wbond net packages All 20Autocomplete哪些索引打开选项卡以进行
  • 验证 t-sql 中的日期?

    我只想验证用户的给定输入 Declare UserInput NVARCHAR 20 set UserInput 26 07 2013 select ISDATE UserInput 即使日期有效 也会返回 false 因为日期采用澳大利亚
  • Rails 3 用户时区

    在 Rails 2 x 中 我不需要专门设置任何时区信息 并且用户无论位于哪个时区 都会获得用户在操作系统中指定的日期时间 现在 在 Rails 3 中 所有内容都以 UTC 格式显示 是否可以恢复默认的查看行为 而无需放入一些 js ha
  • Kafka 不会以 PEM 证书启动

    我发现 Kafka 2 7 0 支持 PEM 证书 我决定尝试使用 DigiCert SSL 证书设置代理 我使用了新选项 我做了所有事情 就像示例中的那样KIP 651 https cwiki apache org confluence
  • IE7 Javascript 并使用字符串作为数组

    奇怪的行为 我只是发布这个问题 看看是否有人知道其原因 或者我的代码是否完全错误 string text yip let s take some weird character alert text 0 all major browsers
  • 如何通过OpenCV和python打开IP摄像头URL?

    我已经在 MacX Lion 上安装了支持 ffmpeg 的 opencv import cv2 import cv import base64 import time import urllib2 import numpy as np f
  • 在 Firefox 中加载图像时显示边框和标题

    我的火狐浏览器有问题 我的网站上有很多图片 当我在 Firefox 中浏览页面时 加载图像时边框和图像标题可见 下载完成后 该边框 标题就会消失并被图像取代 这种情况只发生在火狐浏览器中 Chrome 和其他浏览器加载没有任何边框和标题的图
  • Scala + Android 新手

    我正在尝试使用 scala andriod 插件 但在运行和配置 AVD 时遇到问题 我从 sbt 收到以下错误 android 模拟器启动 NexusOne 成功 总时间 0 s 完成 2011年11月18日 7 07 53 PM 模拟器
  • Rabbitmq 使用单个同步调用检索多条消息

    有没有办法使用单个同步调用接收多条消息 当我知道队列中有 N 条消息 N 可以是小于 10 的小值 时 我应该能够执行类似于 channel basic get String queue boolean autoAck int number
  • 通过 Crystal Web 服务以编程方式设置 Crystal Server 上 Crystal Report 的数据源

    如何更改在 Crystal 服务器中运行的 Crystal 报表在运行时使用的数据源 数据库服务器 用户名 密码 我有一台水晶服务器 并上传了具有一组数据源的报告 托管在服务器 A 用户 A 密码 A 上的 SQL Server 2005
  • Cache-Control: max-age=0 和 no-cache 有什么区别?

    标题Cache Control max age 0意味着内容立即被视为过时 并且必须重新获取 这实际上与Cache Control no cache 我有同样的问题 并在搜索中找到了一些信息 您的问题作为结果之一出现 这就是我所决定的 有两
  • sqlcipher - sqlcipher 的安全性如何?它被黑客入侵了吗?

    它在页面级别加密 SQLite 数据库 好吧 没问题 但是你的源代码呢 它已编译 但即使已编译 有人也可以反编译它 检索您的密码并解密数据库吗 SQLCipher 的安全性如何 根据SQLCipher设计文档 http sqlcipher
  • 是否有更快的代码用于向表中添加新行 - Excel VBA

    每当我的代码找到要添加到其中的新值时 我都会向表中添加一个新行 我为此使用的代码Set newRow ProjectTable ListRows Add工作正常 但这使其运行速度非常慢 是否有代码可以完成相同的任务但运行速度更快 Dim P
  • 如何在flutter中自定义标签栏宽度?

    您好 我们可以在 flutter 中自定义标签栏宽度吗 我的标签栏宽度是固定的 所以当我的标签栏中有长文本时 它不会完全显示 我想让我的标签栏宽度根据内容灵活 所以当我的文本只是短文本时 标签栏宽度会很小 当文本是长文本时 选项卡栏宽度大于
  • 来自 github 存储库的 Scala sbt 文件依赖项

    是否可以包含来自 github 的依赖项 存储库没有 jar 文件 只有 build sbt 文件和源文件夹 您可以创建一个新项目 该项目指向您的源代码build sbt然后使用dependsOn lazy val projectIDepe
  • 下标运算符中的逗号运算符?

    我对逗号运算符很困惑 我从来没有见过这样的代码和这样的语法 但我很好奇它在任何地方都有用吗 为什么它在 c 20 中被弃用 include
  • 如何创建全局热键?

    我想创建一个热键 因此当您按下时 它应该将一些字节写入我附加的进程中的内存地址 到目前为止 我有这段代码 但似乎只有当我专注于主应用程序时它才有效 否则它将无法工作 我想让它工作 所以它会做我想做的事 即使我不关注主应用程序 private