【发布时间】:2020-09-23 20:32:47
【问题描述】:
我正在尝试创建一个将对全局热键做出反应的 C# 应用程序; ALT+H 然后当我释放 ALT 键时。这实际上工作得很好,但我的问题是,当我的应用程序完成了它应该使用热键做的任何事情时,它应该阻止这个热键被其他应用程序处理。我从 StackOverflow 帖子 Global keyboard capture in C# application 获得了下面的大部分代码,但我在其他地方看到 return (IntPtr)1; 应该能够停止对密钥的进一步处理。
但是...当我在例如Word 或写字板,然后我按ALT+H 然后 Word 会显示各种菜单 - 我不希望它显示,因为我只希望我的应用程序做某事:-)
我很抱歉这段相当长的代码,但我认为它很重要,因此您可以获得完整的概述。我用return (IntPtr)1;的地方只有1个。
我的代码:
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Windows.Input;
namespace MyNewProgram
{
static class Program
{
// Enable hotkeys
// https://stackoverflow.com/a/604417/2028935
private const int WH_KEYBOARD_LL = 13;
private const int WM_KEYDOWN = 0x0100;
private const int WM_KEYUP = 0x0101;
private const int WM_SYSKEYUP = 0x0105;
private const int VK_SHIFT = 0x10;
private const int VK_MENU = 0x12;
private static LowLevelKeyboardProc _proc = HookCallback;
private static IntPtr _hookID = IntPtr.Zero;
// Other variables
public static bool isAltPressedInThisApp = false;
private static MainWindow MyMainWindow;
// --------------------------------------------------------------------------------------
[STAThread] // STAThreadAttribute indicates that the COM threading model for the application is single-threaded apartment, https://stackoverflow.com/a/1361048/2028935
static void Main()
{
// Hook application to keyboard
_hookID = SetHook(_proc);
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
MyMainWindow = new MainWindow();
Application.Run(MyMainWindow);
// Unhook application from keyboard
UnhookWindowsHookEx(_hookID);
}
// --------------------------------------------------------------------------------------
// Required functions for globally hooking the keyboard
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern short GetKeyState(int keyCode);
[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);
private delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);
// --------------------------------------------------------------------------------------
// Hook the keyboard - action
private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
// React on KEYDOWN
if (nCode >= 0 && ((wParam == (IntPtr)WM_KEYDOWN) || (wParam == (IntPtr)WM_SYSKEYUP)))
{
int vkCode = Marshal.ReadInt32(lParam);
// H
if ((Keys)vkCode == Keys.H)
{
isAltPressedInThisApp = true;
// Is ALT pressed down
if ((GetKeyState(VK_MENU) & 0x8000) != 0)
{
Console.WriteLine("ALT + H");
return (IntPtr)1; // do not allow others to hook this key combo
}
}
}
// React on KEYUP
if (nCode >= 0 && wParam == (IntPtr)WM_KEYUP)
{
int vkCode = Marshal.ReadInt32(lParam);
// Is ALT not pressed down
if ((Keys)vkCode == Keys.LMenu)
{
Console.WriteLine("ALT UP");
}
}
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
// --------------------------------------------------------------------------------------
// Hook the keyboard
private static IntPtr SetHook(LowLevelKeyboardProc proc)
{
using (Process curProcess = Process.GetCurrentProcess())
using (ProcessModule curModule = curProcess.MainModule)
{
return SetWindowsHookEx(WH_KEYBOARD_LL, proc, GetModuleHandle(curModule.ModuleName), 0);
}
}
}
}
我不是一个可靠的 C# 开发人员,因为我在这里开始了我的前几个婴儿步骤 - 那么为什么我会把自己作为第一件事之一投入到全局热键的深水中 ;-) 有没有人可以提供一些提示在这里,因为我可能在某个地方犯了一个愚蠢的错误?
【问题讨论】:
-
"但是...当我在例如 Word 中并按 ALT+H 时,Word 会显示所有类型的菜单 - 我不希望它显示,因为我只想让我的应用程序执行某些操作"当您单独按下 Alt 时,Word 会做出反应。在 H 也被击中之前,您不会知道最终的组合是否是 Alt-H。不幸的是,到那时,Word 已经显示了它的菜单。此外,您可以阻止 Alt-H 在您之后到达链中的其他键盘挂钩,但您不知道在您之前的链中有多少人已经处理了它。
-
我可以理解
ALT最初会显示菜单,但是当我按下H时,我的应用程序不能释放ALT键,因此 Word 会认为它从未被按下?我有另一个应用程序,它的工作原理就是这样。如果我在那里重新创建完全相同的设置,那么当我在 Word 中时,它会首先进入 Word 菜单,但是当我按下H时,它会再次释放ALT并且光标回到Word 中的编辑 - 至少看起来这是正在发生的事情? -
修改它,它应该给你想要的:docs.microsoft.com/en-gb/windows/win32/dxtecharts/…。郑重声明,这是一个可怕的功能,它基本上会在您的应用程序运行时破坏其他应用程序。