На самом деле вы не можете сбросить события клавиатуры, но вы можете запретить получение события циклом сообщений потока.
Вы должны установить обработчик для WH_GETMESSAGE
hook. LParam вашей подключаемой процедуры - это указатель на структуру MSG. Изучив структуру, вы можете изменить ее, чтобы избежать передачи сообщения обработчику вызывающих сообщений. Вам следует изменить сообщение на WM_NULL.
Сама процедура в .NET немного длинна и требует отдельной статьи. Но вкратце вот как:
Скопируйте этот класс точно так, как есть, в новый файл C # в вашем проекте:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace Unicorn
{
public static class HookManager
{
#region Fields
private delegate int HookDelegate(int ncode, IntPtr wParam, IntPtr lParam);
private static HookDelegate getMessageHookProc;
private static IntPtr getMessageHookHandle;
private static List<EventHandler<GetMessageHookEventArgs>> getMessageHandlers =
new List<EventHandler<GetMessageHookEventArgs>>();
#endregion
#region Private Methods - Installation and Uninstallation
private static void InstallGetMessageHook()
{
if (getMessageHookProc != null)
return;
getMessageHookProc = new HookDelegate(GetMessageHookProc);
getMessageHookHandle = SetWindowsHookEx(WH_GETMESSAGE, getMessageHookProc, 0, GetCurrentThreadId());
}
private static void UninstallGetMessageHook()
{
if (getMessageHookProc == null)
return;
UnhookWindowsHookEx(getMessageHookHandle);
getMessageHookHandle = IntPtr.Zero;
getMessageHookProc = null;
}
#endregion
#region Public Methods - Add and Remove Handlers
public static void AddGetMessageHookHandler(EventHandler<GetMessageHookEventArgs> handler)
{
if (getMessageHandlers.Contains(handler))
return;
getMessageHandlers.Add(handler);
if (getMessageHandlers.Count == 1)
InstallGetMessageHook();
}
public static void RemoveGetMessageHookHandler(EventHandler<GetMessageHookEventArgs> handler)
{
getMessageHandlers.Remove(handler);
if (getMessageHandlers.Count == 0)
UninstallGetMessageHook();
}
#endregion
#region Private Methods - Hook Procedures
[DebuggerStepThrough]
private static int GetMessageHookProc(int code, IntPtr wParam, IntPtr lParam)
{
if (code == 0) // HC_ACTION
{
MSG msg = new MSG();
Marshal.PtrToStructure(lParam, msg);
GetMessageHookEventArgs e = new GetMessageHookEventArgs()
{
HWnd = msg.hwnd,
Msg = msg.message,
WParam = msg.wParam,
LParam = msg.lParam,
MessageRemoved = (int)wParam == 1,
ShouldApplyChanges = false
};
foreach (var handler in getMessageHandlers.ToArray())
{
handler(null, e);
if (e.ShouldApplyChanges)
{
msg.hwnd = e.HWnd;
msg.message = e.Msg;
msg.wParam = e.WParam;
msg.lParam = e.LParam;
Marshal.StructureToPtr(msg, (IntPtr)lParam, false);
e.ShouldApplyChanges = false;
}
}
}
return CallNextHookEx(getMessageHookHandle, code, wParam, lParam);
}
#endregion
#region Win32 stuff
private const int WH_KEYBOARD = 2;
private const int WH_GETMESSAGE = 3;
private const int WH_CALLWNDPROC = 4;
private const int WH_MOUSE = 7;
private const int WH_CALLWNDPROCRET = 12;
[StructLayout(LayoutKind.Sequential)]
public class MSG
{
public IntPtr hwnd;
public uint message;
public IntPtr wParam;
public IntPtr lParam;
public uint time;
int x;
int y;
}
[DllImport("USER32.dll", CharSet = CharSet.Auto)]
private static extern IntPtr SetWindowsHookEx(int idHook, HookDelegate lpfn, int hMod, int dwThreadId);
[DllImport("USER32.dll", CharSet = CharSet.Auto)]
private static extern int CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("USER32.dll", CharSet = CharSet.Auto)]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("kernel32.dll", ExactSpelling = true, CharSet = CharSet.Auto)]
private static extern int GetCurrentThreadId();
#endregion
}
#region EventArgs
public class GetMessageHookEventArgs : EventArgs
{
public uint Msg { get; set; }
public IntPtr HWnd { get; set; }
public IntPtr WParam { get; set; }
public IntPtr LParam { get; set; }
public bool MessageRemoved { get; set; }
public bool ShouldApplyChanges { get; set; }
}
#endregion
}
Это вспомогательный класс, который делает все, что вам нужно. Мой настоящий класс был немного длиннее и мог обрабатывать еще несколько типов ловушек, но я очистил код, чтобы сделать его меньше.
После этого ваш код должен выглядеть следующим образом:
private static void GetMessageProcHook(object sender, Unicorn.GetMessageHookEventArgs e)
{
if (e.Msg == 0x100 && (Keys)e.WParam == Keys.Return) // WM_KEYDOWN
{
// swallow the message
e.Msg = 0; // WM_NULL
e.WParam = IntPtr.Zero;
e.LParam = IntPtr.Zero;
e.ShouldApplyChanges = true; // This will tell the HookManager to copy the changes back.
}
}
private static ResultMsgBox MsgResultBaseNoEnter(string msg, string caption, uint options)
{
ResultMsgBox res;
Unicorn.HookManager.AddGetMessageHookHandler(GetMessageProcHook);
try
{
res = MessageBox(GetForegroundWindow(), msg, caption, options);
}
finally
{
Unicorn.HookManager.RemoveGetMessageHookHandler(GetMessageProcHook);
}
return res;
}
Если вы столкнулись с какой-либо другой проблемой, дайте мне знать.