Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get handle to desktop / shell window

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 to GetForegroundWindow().

This approach is working until someone changes the desktop wallpaper, but as soon as the wallpaper is changed the handle from GetShellWindow() doesn't match the one from GetForegroundWindow() anymore and I don't quite get why that is. (OS: Windows 7 32bit)

Is there a better approach to check if the desktop is focused? Preferably one that won't be broken if the user changes the wallpaper?

EDIT: I designed a workaround: I'm testing the handle to have a child of class "SHELLDLL_DefView". If it has, the desktop is on focus. Whilst it's working at my PC that doesn't mean it will work all the time…

like image 678
MFH Avatar asked Dec 03 '11 01:12

MFH


People also ask

What is window handle C#?

This is called window handle and is used to identify browser windows. Since the id is unique, it is used by the Selenium WebDriver to switch between different windows (or tabs). The id is retained till the closure of the Selenium WebDriver session via WebDriver. Quit or manual killing of the process.

What is Hwnd?

HWND is a "handle to a window" and is part of the Win32 API . HWNDs are essentially pointers (IntPtr) with values that make them (sort of) point to a window-structure data. In general HWNDs are part an example for applying the ADT model. If you want a Control's HWND see Control. Handle property.


1 Answers

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.

like image 64
tklepzig Avatar answered Sep 23 '22 05:09

tklepzig