Как сделать глобальную клавиатуру для приложения Electron. NET в C#? Я полагаю, что пока оно работает в консольном приложении, оно должно работать должным образом в приложении Electron. Net.
Я нашел «решение» для этой проблемы, но он имеет тенденцию использовать много ЦП (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 и затем ссылаться на эту DLL в моем коде C#, чтобы, надеюсь, сделать хук клавиатуры, который функционировал должным образом и не выполнялся. не вызывает какой-либо заметной задержки ввода, но это тоже не сработало.
Хук клавиатуры работал отлично, когда запускался как .exe в C ++, но когда я скомпилировал его как DLL и запустил в C# это вызвало ту же проблему, что и раньше - большая задержка ввода и функция обратного вызова, по-видимому, не вызывается.
Вот код, если кто-то захочет его попробовать:
KeyboardHook. 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);
}
KeyboardHook.h
#include <Windows.h>
HHOOK keyboardHook;
namespace Hooks
{
class KeyboardHook
{
public:
__declspec(dllexport) void Install();
__declspec(dllexport) void Uninstall();
};
}
Program.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();
}
}
}