que unirán de código que encontré en Internet mí clase WH_KEYBOARD_LL
ayudante:El uso de gancho de teclado globales (WH_KEYBOARD_LL) en WPF/C#
Coloque el código siguiente a algunos de sus bibliotecas utils, que sea YourUtils.cs:
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;
using System.Windows.Input;
namespace MYCOMPANYHERE.WPF.KeyboardHelper
{
public class KeyboardListener : IDisposable
{
private static IntPtr hookId = IntPtr.Zero;
[MethodImpl(MethodImplOptions.NoInlining)]
private IntPtr HookCallback(
int nCode, IntPtr wParam, IntPtr lParam)
{
try
{
return HookCallbackInner(nCode, wParam, lParam);
}
catch
{
Console.WriteLine("There was some error somewhere...");
}
return InterceptKeys.CallNextHookEx(hookId, nCode, wParam, lParam);
}
private IntPtr HookCallbackInner(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0)
{
if (wParam == (IntPtr)InterceptKeys.WM_KEYDOWN)
{
int vkCode = Marshal.ReadInt32(lParam);
if (KeyDown != null)
KeyDown(this, new RawKeyEventArgs(vkCode, false));
}
}
return InterceptKeys.CallNextHookEx(hookId, nCode, wParam, lParam);
}
public event RawKeyEventHandler KeyDown;
public event RawKeyEventHandler KeyUp;
public KeyboardListener()
{
hookId = InterceptKeys.SetHook((InterceptKeys.LowLevelKeyboardProc)HookCallback);
}
~KeyboardListener()
{
Dispose();
}
#region IDisposable Members
public void Dispose()
{
InterceptKeys.UnhookWindowsHookEx(hookId);
}
#endregion
}
internal static class InterceptKeys
{
public delegate IntPtr LowLevelKeyboardProc(
int nCode, IntPtr wParam, IntPtr lParam);
public static int WH_KEYBOARD_LL = 13;
public static int WM_KEYDOWN = 0x0100;
public 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);
}
}
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr SetWindowsHookEx(int idHook,
LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode,
IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr GetModuleHandle(string lpModuleName);
}
public class RawKeyEventArgs : EventArgs
{
public int VKCode;
public Key Key;
public bool IsSysKey;
public RawKeyEventArgs(int VKCode, bool isSysKey)
{
this.VKCode = VKCode;
this.IsSysKey = isSysKey;
this.Key = System.Windows.Input.KeyInterop.KeyFromVirtualKey(VKCode);
}
}
public delegate void RawKeyEventHandler(object sender, RawKeyEventArgs args);
}
que utilizo como esto:
App.xaml:
<Application ...
Startup="Application_Startup"
Exit="Application_Exit">
...
App.xaml.cs:
public partial class App : Application
{
KeyboardListener KListener = new KeyboardListener();
private void Application_Startup(object sender, StartupEventArgs e)
{
KListener.KeyDown += new RawKeyEventHandler(KListener_KeyDown);
}
void KListener_KeyDown(object sender, RawKeyEventArgs args)
{
Console.WriteLine(args.Key.ToString());
// I tried writing the data in file here also, to make sure the problem is not in Console.WriteLine
}
private void Application_Exit(object sender, ExitEventArgs e)
{
KListener.Dispose();
}
}
El problema es que deja de funcionar después de golpear las teclas de un tiempo. No se genera ningún error de todos modos, simplemente no obtengo nada después de un tiempo. No puedo encontrar un patrón sólido cuando deja de funcionar.
La reproducción de este problema es muy simple, toca algunas teclas como un loco, por lo general fuera de la ventana.
Sospecho que hay algún mal problema de subprocesamiento detrás, ¿alguien tiene idea de cómo mantener esto funcionando?
lo que ya intentado:
- Sustitución
return HookCallbackInner(nCode, wParam, lParam);
con algo sencillo. - Reemplazando con llamada asincrónica, tratando de poner Sleep 5000ms (etc.).
La llamada asincrónica no hizo que funcionara mejor, parece detenerse siempre cuando el usuario mantiene una sola letra hacia abajo por un tiempo.
podemos interceptar la clave y enviar una clave diferente en lugar del prensado? Por ejemplo, al presionar a se envía la tecla e. – Thunder
Completo, utilizable y documentado. Esto es lo que me gusta en StackOverflow – mico
Quizás esta es una nueva versión, con código agregado para convertir las claves virtuales en cadena, justo lo que estaba por agregar. Al menos, si el interés que obtuve de Google es correcto. http://mureakuha.com/koodikirjasto/1166 – mico