Created
July 29, 2021 07:52
-
-
Save jjbrunton/8b167c981eedf89f9c4a5c6e1e3eb479 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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