如何检测已切换的台式机?

时间:2019-08-05 13:42:27

标签: c# desktop

在我的应用程序中,我需要知道用户何时切换虚拟桌面,例如通过按 Ctrl + Win +

尽管通过Hooking这样做是一个好主意。我列出了我编写的示例类以测试我的想法。我以为虚拟桌面更改时,我会得到回调。但是,无论如何更改虚拟桌面,都没有回调。

我还编写了一个测试应用程序,用于创建,打开,切换和关闭桌面。它工作正常,但下面的代码无法检测到任何桌面开关。

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);
    }
}

我不必这样做。我很感激或其他方式。唯一重要的是,我需要检测Windows桌面开关。

1 个答案:

答案 0 :(得分:1)

您为事件EVENT_SYSTEM_DESKTOPSWITCH(0x0020)安装了一个钩子。但是,此处的术语“台式机”在Windows 10中并未将“虚拟台式机”作为在不同窗口集之间进行切换的功能,而是将desktops as a system concept in Windows分隔为不同的操作环境(“正常”,“登录”,“屏幕保护程序”)。

因此,您无法以这种方式检测到虚拟桌面的切换。

相反,请使用此开源库https://github.com/Grabacr07/VirtualDesktop中所示的方法,该库使用Windows Shell中当前未记录的VirtualDesktopNotificationService COM服务在当前虚拟桌面更改时得到通知。