Reputation: 187
In my application I need to know when the user switches the virtual Desktop, e.g. by pressing Ctrl+Win+→.
I though it'd be a great idea to do this via Hooking. I have listed an example class I wrote to test my idea. I thought when the virtual Desktop changes, I would get a callback. However, there is no callback no matter how I change the virtual Desktop.
I also wrote a test application that creates, opens, switches and closes Desktops. It works fine, but my code below detects none of the Desktop switches.
public class SwitchDesktopMonitor
{
private delegate void CreateHookDelegate();
private delegate void SetWinEventHookCallback(IntPtr hWinEventHook, uint eventType, IntPtr hWnd, uint objectId, int childId, uint dwEventThread, uint dwmsEventTime);
[DllImport("user32.dll")]
private static extern IntPtr SetWinEventHook(uint eventMin, uint eventMax, IntPtr hmodWinEventProc, SetWinEventHookCallback lpfnWinEventProc, uint idProcess, uint idThread, uint dwFlags);
[DllImport("user32.dll")]
private static extern bool UnhookWinEvent(IntPtr hWinEventHook);
[DllImport("user32.dll", SetLastError = true)]
private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint processId);
private IntPtr _setWinEventHook;
private readonly SetWinEventHookCallback _hookingCallback;
private readonly Window _window;
public SwitchDesktopMonitor(Window window)
{
_window = window;
_hookingCallback = (hWinEventHook, eventType, hWnd, objectId, childId, dwEventThread, dwmsEventTime) =>
{
Console.WriteLine("-> _hookingCallback - hWinEventHook = {0}, eventType = {1}, hWnd = {2}, objectId = {3}, childId = {4}, dwEventThread = {5}, dwmsEventTime = {6}",
hWinEventHook, eventType, hWnd, objectId, childId, dwEventThread, dwmsEventTime);
};
}
public void Start()
{
Console.WriteLine("{0}.Start", this);
if (_window == null || _window.Dispatcher == null)
{
return;
}
if (_window.Dispatcher.CheckAccess())
{
CreateHook();
}
else
{
_window.Dispatcher.Invoke(new CreateHookDelegate(CreateHook));
}
}
public void Stop()
{
Console.WriteLine("{0}.Stop", this);
if (_setWinEventHook != null)
{
Console.WriteLine("\tUnhookWinEvent = {0}", UnhookWinEvent(_setWinEventHook));
}
}
private void CreateHook()
{
var windowHandle = new WindowInteropHelper(_window).Handle;
uint processId;
uint threadId = GetWindowThreadProcessId(windowHandle, out processId);
Console.WriteLine("\twindowHandle = {0}, processId = {1}, threadId = {2}", windowHandle, processId, threadId);
_setWinEventHook = SetWinEventHook(0x0020, 0x0020, IntPtr.Zero, _hookingCallback, processId, threadId, 0x0000);
Console.WriteLine("\t_setWinEventHook = {0}", _setWinEventHook);
}
}
I don't have to do this way. I am thankful or other approaches. The only important thing is that I need to detect Windows Desktop switches.
Upvotes: 1
Views: 2114
Reputation: 28499
You install a hook for the event EVENT_SYSTEM_DESKTOPSWITCH
(0x0020). However, the term desktop here does not refer to "virtual desktops" as a feature in Windows 10 to switch between different sets of windows, but to desktops as a system concept in Windows to separate different operating environments (Normal, Logon, Screensaver).
So, you cannot detect a switching of virtual desktops this way.
Instead, use the way as shown in this open source library https://github.com/Grabacr07/VirtualDesktop which uses a currently undocumented VirtualDesktopNotificationService
COM service in the Windows Shell to be notified when the current virtual desktop changes.
Upvotes: 2