/// <summary> /// Creates a message only window /// </summary> /// <param name="createThread">If true, the window will run on a dedicated thread</param> /// <param name="mouseCallback">Callback to receive mouse messages from the low level mouse hook (WH_MOUSE_LL). set to null to disable mouse hook</param> /// <param name="kbCallback">Callback to receive keyboard messages from the low level keyboard hook (WH_KEYBOARD_LL). set to null to disable keyboard hook</param> /// <param name="monitorDesktops">If true, the DesktopSwitched event will fire whenever the window receives EVENT_SYSTEM_DESKTOPSWITCH from the wineventhook</param> /// <param name="monitorClipboard">If true, ClipboardContentChanged will be fired when clipboard change message is received by the ClipboardFormatListener</param> public void CreateWindow(bool createThread, LLHookCallback mouseCallback, LLHookCallback kbCallback, bool monitorDesktops, bool monitorClipboard) { if (procThread != null) { ISLogger.Write("Warning: Can't create message window: thread already exists"); return; } windowCreatedEvent = new ManualResetEventSlim(false); exitThread = false; if (createThread) { procThread = new Thread(() => WndThread(mouseCallback, kbCallback, monitorDesktops, monitorClipboard)); procThread.SetApartmentState(ApartmentState.STA); procThread.IsBackground = false; procThread.Name = "WindowOnlyMessageThread"; procThread.Start(); } else { WndThread(mouseCallback, kbCallback, monitorDesktops, monitorClipboard); } //We want to wait until the window has actually been created before leaving this method to ensure calls are not made before window //is created properly. 2000ms timeout windowCreatedEvent.Wait(2000); }
private void WndThread(LLHookCallback mouseCallback, LLHookCallback kbCallback, bool monitorDesktops, bool monitorClipboard) { procThreadId = GetCurrentThreadId(); WindowHandle = CreateMessageOnlyWindow(); windowCreatedEvent.Set(); if (mouseCallback != null) { MouseProcID = SetMouseHook(mouseCallback); } if (kbCallback != null) { KeyboardProcID = SetKeyboardHook(kbCallback); } if (monitorDesktops) { StartMonitoringDesktopSwitches(); } if (monitorClipboard) { StartMonitoringClipboard(); } if (WindowHandle == IntPtr.Zero) { ISLogger.Write($"Failed to create window: Win32 error {Marshal.GetLastWin32Error().ToString("X")}"); return; } while (!exitThread) { if (GetMessage(out MSG message, WindowHandle, 0, 0) != 0) { DispatchMessage(ref message); }
static extern IntPtr SetWindowsHookEx(int idHook, LLHookCallback lpfn, IntPtr hMod, uint dwThreadId);