【问题标题】:How to detect switched Desktops?如何检测切换的桌面?
【发布时间】:2019-08-05 13:42:27
【问题描述】:

在我的应用程序中,我需要知道用户何时切换虚拟桌面,例如通过按 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 桌面开关。

【问题讨论】:

标签: c# desktop


【解决方案1】:

您为事件EVENT_SYSTEM_DESKTOPSWITCH (0x0020) 安装了一个挂钩。但是,这里的桌面一词并不是指“虚拟桌面”作为 Windows 10 中用于在不同组窗口之间切换的功能,而是指desktops as a system concept in Windows 以分隔不同的操作环境(正常、登录、屏幕保护程序)。

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

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

【讨论】:

  • 我目前正在研究 Grabacr07 的源代码,我将详细测试VirtualDesktopNotificationService。完成后我会通知您,如果有效,请将您的回复标记为答案。非常感谢您对桌面开关挂钩的说明!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多