如何在 C# 中为 Electron.NET 应用程序制作全局键盘挂钩?我相信只要它在控制台应用程序中工作,它就应该在 Electron.Net 应用程序中正常工作。
我为这个问题做了一个“解决方案”,但它往往会消耗大量的 CPU(7-10%)。如果没有其他选择,也许有人能够以某种方式使其真正有效:
using System;
using System.Runtime.InteropServices;
using System.Threading;
[DllImport("User32.dll")]
public static extern short GetAsyncKeyState(int vKey);
// Other VKey codes: https://docs.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes
public enum VKeys {
LBUTTON = 0x01, // Left mouse button
RBUTTON = 0x02, // Right mouse button
KEY_0 = 0x30, // 0 key
KEY_1 = 0x31, // 1 key
KEY_2 = 0x32, // 2 key
KEY_3 = 0x33, // 3 key
KEY_4 = 0x34, // 4 key
KEY_5 = 0x35, // 5 key
KEY_6 = 0x36, // 6 key
KEY_7 = 0x37, // 7 key
KEY_8 = 0x38, // 8 key
KEY_9 = 0x39 // 9 key
}
public void Start()
{
Thread HookThread = new Thread(delegate ()
{
var keys = Enum.GetValues(typeof(VKeys));
while (true)
{
foreach (int key in keys)
{
var ks = GetAsyncKeyState(key);
if (ks < 0)
{
Console.WriteLine($"pressed {key}");
//Thread.Sleep(100);
}
//Thread.Sleep(1); // Even sleeping for '1ms' will delay it too much
}
}
});
HookThread.Start();
}
我发现的很多东西只有在我使用 WinForms 或 WPF 时才有效。
编辑:
我尝试了 hanabanashiku 的这个答案,以及我在网上找到的许多其他答案,但它们似乎都只是滞后于键盘输入,而且它们的回调函数似乎永远不会被调用。
我决定用 C++ 编写键盘钩子,编译为 DLL,然后在我的 C# 代码中引用该 DLL,以希望制作一个可以正常工作并且不会导致任何明显输入延迟的键盘钩子,但这也不起作用。
键盘钩子在 C++ 中作为 .exe 运行时完美运行,但是当我将其编译为 DLL 并在 C# 中运行时,它导致了与以前相同的问题 - 大量输入延迟和回调函数似乎没有被调用。
如果有人想尝试,这是代码:
键盘钩子.cpp
#include "KeyboardHook.h"
#include <iostream>
#define __event void KeyDown(int key), KeyUp(int key);
using namespace Hooks;
void KeyDown(int key)
{
std::cout << "KeyDown\n";
}
void KeyUp(int key)
{
std::cout << "KeyUp\n";
}
LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode == HC_ACTION)
{
PKBDLLHOOKSTRUCT p = (PKBDLLHOOKSTRUCT)lParam;
switch (wParam)
{
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
KeyDown(p->vkCode);
break;
case WM_KEYUP:
case WM_SYSKEYUP:
KeyUp(p->vkCode);
break;
}
}
// Not processing keys so always return CallNextHookEx
return(CallNextHookEx(NULL, nCode, wParam, lParam));
}
void KeyboardHook::Install() {
// Install keyboard hook
keyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardProc, 0, 0);
std::cout << "Installed\n";
}
void KeyboardHook::Uninstall() {
// Unhook keyboard hook
UnhookWindowsHookEx(keyboardHook);
}
键盘钩子.h
#include <Windows.h>
HHOOK keyboardHook;
namespace Hooks
{
class KeyboardHook
{
public:
__declspec(dllexport) void Install();
__declspec(dllexport) void Uninstall();
};
}
程序.cs
using System;
using System.Runtime.InteropServices;
namespace HelloMyNameIsSpindiNiceToMeetYou
{
class Program
{
private const string hooksPath = @"C:\Path\To\Hooks.dll";
// If EntryPoint doesn't work, yours might be different
// https://docs.microsoft.com/en-us/dotnet/framework/interop/identifying-functions-in-dlls
//
// "For example, you can use dumpbin /exports Hooks.dll [...] to obtain function names."
// you need to be in the folder with the dll for above to work in Command Prompt for VS
[DllImport(hooksPath, EntryPoint = "?Install@KeyboardHook@Hooks@@QEAAXXZ", CallingConvention = CallingConvention.Cdecl)]
private extern static void Install();
static void Main(string[] args)
{
Install();
// keep console app running
while (true)
{
continue;
}
// or keep it running with this
// Console.ReadKey();
}
}
}
我现在正在一个 electron.net 应用程序之外测试这些东西,只是在一个控制台应用程序中,但仍然无法正常工作。我发现的一切都导致回到使用我无法使用的 winforms。