Get handle to desktop / shell window

前端 未结 2 575
灰色年华
灰色年华 2020-12-18 01:03

In one of my programs I need to test if the user is currently focusing the desktop/shell window. Currently I\'m using GetShellWindow() from user32.dll and compare the result

相关标签:
2条回答
  • 2020-12-18 01:51

    The thing changed a little bit since there are slideshows as wallpaper available in Windows 7. You are right with WorkerW, but this works only with wallpaper is set to slideshow effect.

    When there is set the wallpaper mode to slideshow, you have to search for a window of class WorkerW and check the children, whether there is a SHELLDLL_DefView. If there is no slideshow, you can use the good old GetShellWindow().

    I had the same problem some months ago and I wrote a function for getting the right window. Unfortunately I can't find it. But the following should work. Only the Win32 Imports are missing:

    public enum DesktopWindow
    {
        ProgMan,
        SHELLDLL_DefViewParent,
        SHELLDLL_DefView,
        SysListView32
    }
    
    public static IntPtr GetDesktopWindow(DesktopWindow desktopWindow)
    {
        IntPtr _ProgMan = GetShellWindow();
        IntPtr _SHELLDLL_DefViewParent = _ProgMan;
        IntPtr _SHELLDLL_DefView = FindWindowEx(_ProgMan, IntPtr.Zero, "SHELLDLL_DefView", null);
        IntPtr _SysListView32 = FindWindowEx(_SHELLDLL_DefView, IntPtr.Zero, "SysListView32", "FolderView");
    
        if (_SHELLDLL_DefView == IntPtr.Zero)
        {
            EnumWindows((hwnd, lParam) =>
            {
                if (GetClassName(hwnd) == "WorkerW")
                {
                    IntPtr child = FindWindowEx(hwnd, IntPtr.Zero, "SHELLDLL_DefView", null);
                    if (child != IntPtr.Zero)
                    {
                        _SHELLDLL_DefViewParent = hwnd;
                        _SHELLDLL_DefView = child;
                        _SysListView32 = FindWindowEx(child, IntPtr.Zero, "SysListView32", "FolderView"); ;
                        return false;
                    }
                }
                return true;
            }, IntPtr.Zero);
        }
    
        switch (desktopWindow)
        {
            case DesktopWindow.ProgMan:
                return _ProgMan;
            case DesktopWindow.SHELLDLL_DefViewParent:
                return _SHELLDLL_DefViewParent;
            case DesktopWindow.SHELLDLL_DefView:
                return _SHELLDLL_DefView;
            case DesktopWindow.SysListView32:
                return _SysListView32;
            default:
                return IntPtr.Zero;
        }
    }
    

    In your case you would call GetDesktopWindow(DesktopWindow.SHELLDLL_DefViewParent); to get the top-level window for checking whether it is the foreground window.

    0 讨论(0)
  • 2020-12-18 02:02

    Here is a workaround that uses GetClassName() to detect if the desktop is active:

    • When Windows first starts, the desktop's Class is "Progman"
    • After changing the wallpaper, the desktop's Class will be "WorkerW"

    You can test against these to see if the desktop is focused.

    [DllImport("user32.dll")]
    static extern int GetForegroundWindow();
    
    [DllImport("user32.dll")]
    static extern int GetClassName(int hWnd, StringBuilder lpClassName, int nMaxCount);
    
    public void GetActiveWindow() {
        const int maxChars = 256;
        int handle = 0;
        StringBuilder className = new StringBuilder(maxChars);
    
        handle = GetForegroundWindow();
    
        if (GetClassName(handle, className, maxChars) > 0) {
            string cName = className.ToString();
            if (cName == "Progman" || cName == "WorkerW") {
                // desktop is active
            } else {
                // desktop is not active
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题