Actually you can't flush the keyboard events, but you can prevent the event to be received by the thread's message loop.
You should install a handler for WH_GETMESSAGE
hook. The lParam of your hook procedure is a pointer to an MSG structure. After examining the structure, you can change it to avoid the message to be passed to the calling message processor. You should change the message to WM_NULL.
The actual procedure in .NET is a little long an requires a separate article. But briefly, here is how:
Copy this class exactly as is, in a new C# file in your project:
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
}
This is a helper class that does all you need. My actual class was a little longer and could handle a few more hook types, but I cleared out the code to make it smaller.
After this, your code should look like this:
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;
}
If you encountered any other problem, let me know.