2

I am trying to obtain handle to SHELLDLL_DefView.

So, I have this code.

HWND hProgman = FindWindow(L"Progman", NULL);
HWND hWnd = FindWindowEx(hProgman, 0, L"SHELLDLL_DefView", NULL);

Eveyrtihing works OK, until I change in Windows desktop brackground to slideshow. Then when I search with spy++ hierarchy of the windows, than SHELLDLL_DefView has another parent. Now it is #32769 (Desktop) -> WorkerW -> SHELLDLL_DefView. So I can't find it. Problem is that when I try

HWND desktop = GetDesktopWindow();
HWND hWnd = FindWindowEx(desktop , 0, L"WorkerW", NULL);
HWND hWnd = FindWindowEx(hWnd, 0, L"SHELLDLL_DefView", NULL);

Than SHELLDLL_DefView is not found. WorkerW yes.

Can anybody help?

Jaro Kollár
  • 253
  • 3
  • 15
  • Why do you need to find this? The shell has a rich automation interface. Have you evaluated, that it doesn't meet your requirements? – IInspectable Apr 12 '16 at 08:28
  • I need to finw handle to SHELLDLL_DefView – Jaro Kollár Apr 12 '16 at 08:52
  • *"I need to find X because I need to find X"* is not an answer to the question, why you think you do. – IInspectable Apr 12 '16 at 08:54
  • I give answer below, how to solve my problem. – Jaro Kollár Apr 12 '16 at 08:58
  • But what are you going to do with that HWND once you have it? What is the ultimate goal you are trying to achieve here? More often than not, there is a better way to interact with the shell than through random window handles. – IInspectable Apr 12 '16 at 09:05
  • Than I want to find handle of SysListView32 and then get some information about icons, their position, size and so on – Jaro Kollár Apr 12 '16 at 09:16
  • Well, then, you are doing it wrong. The official and documented way to do this is to use the Shell interfaces. Have a look at [Querying information from an Explorer window](https://blogs.msdn.microsoft.com/oldnewthing/20040720-00/?p=38393/) for related sample code. You'd have to slightly modify it to fit your requirements. – IInspectable Apr 12 '16 at 09:59
  • Even more appropriate: [Manipulating the positions of desktop icons](https://blogs.msdn.microsoft.com/oldnewthing/20130318-00/?p=4933). – IInspectable Apr 12 '16 at 10:04
  • Helpful link with an answer: https://blog.syedgakbar.com/2013/01/19/windows-desktop-listview-handle/ – Paul Feb 11 '23 at 15:20

2 Answers2

4

Your code only works on some Windows versions as "SHELLDLL_DefView" can be found under "WorkerW" or "Progman" and as you discovered there can be many windows under the "WorkerW" class (normal in Win7).

Microsoft Docs report EnumWindows() is more reliable than calling GetWindow()/FindWindowEx() functions in loops, so more universal code (tested on Windows 98/Windows 7) would look like this (say you want to refresh the desktop):

BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam) {
    HWND hNextWin;
    hNextWin = FindWindowExA(hwnd, 0, "SHELLDLL_DefView", 0);
    if ( hNextWin ) {
    // The correct desktop shell window under Progman/WorkerW will have only 1 child window!
        if ( GetNextWindow(hNextWin, GW_HWNDNEXT) || GetNextWindow(hNextWin, GW_HWNDPREV) )
            return true;
    // We found correct handle
        PostMessageA(hNextWin, WM_KEYDOWN, VK_F5, 0);
        return false;
    }
    return true;
}

void main() {
   EnumWindows(&EnumWindowsProc, 0);
}
John Doe
  • 303
  • 1
  • 8
2

I found the answer. Need to iterate through all WorkerW.

HWND destop = GetDesktopWindow();
HWND hWorkerW = NULL;
HWND hShellViewWin = NULL;
do
{
    hWorkerW = FindWindowEx(destop, hWorkerW, L"WorkerW", NULL);
    hShellViewWin = FindWindowEx(hWorkerW, 0, L"SHELLDLL_DefView", 0);
} while (hShellViewWin == NULL && hWorkerW != NULL);
Jaro Kollár
  • 253
  • 3
  • 15
  • Thanks, this solved my problem. I noticed that passing the `desktop` HWND is not necessary though, as this is the default when passing `null` (MSDN: `If hwndParent is NULL, the function uses the desktop window as the parent window. The function searches among windows that are child windows of the desktop.`). – Pieter12345 Dec 19 '19 at 23:56