Skip to content

Instantly share code, notes, and snippets.

@jjbrunton
Created July 29, 2021 07:52
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save jjbrunton/8b167c981eedf89f9c4a5c6e1e3eb479 to your computer and use it in GitHub Desktop.
Save jjbrunton/8b167c981eedf89f9c4a5c6e1e3eb479 to your computer and use it in GitHub Desktop.
public class WindowHook : WindowProcHook
{
static readonly Queue<Action> actionQueue = new Queue<Action>();
static readonly Queue<Delegate> delegateQueue = new Queue<Delegate>();
static readonly Queue<object> returnValueQueue = new Queue<object>();
public enum UserMessage
{
ProcessMessage = 400,
}
[DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, int wMsg, IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll")]
static extern uint GetCurrentThreadId();
public WindowHook(IntPtr handle) : base(handle, "hooker")
{
}
public void RunOnMainThread(Action action)
{
if (GetCurrentThreadId() == System.Diagnostics.Process.GetCurrentProcess().Threads[0].Id)
{
action();
return;
}
this.Invoke(UserMessage.ProcessMessage);
actionQueue.Enqueue(action);
}
public T RunOnMainThread<T>(Func<T> function)
{
try
{
if (GetCurrentThreadId() == System.Diagnostics.Process.GetCurrentProcess().Threads[0].Id)
return function();
delegateQueue.Enqueue(function);
this.Invoke(UserMessage.ProcessMessage);
return (T)returnValueQueue.Dequeue();
}
catch (Exception e)
{
return default(T);
}
}
protected override IntPtr OnWndProc(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam)
{
// ReSharper disable once SwitchStatementMissingSomeCases
switch ((UserMessage)msg)
{
case UserMessage.ProcessMessage:
while (actionQueue.Count > 0)
actionQueue.Dequeue()?.Invoke();
while (delegateQueue.Count > 0)
{
var invokeTarget = delegateQueue.Dequeue();
returnValueQueue.Enqueue(invokeTarget?.DynamicInvoke());
}
return IntPtr.Zero;
}
return base.OnWndProc(hWnd, msg, wParam, lParam);
}
public void Invoke(UserMessage msg)
{
SendMessage(this.Handle, (int)UserMessage.ProcessMessage, IntPtr.Zero, IntPtr.Zero);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment