tags:

views:

787

answers:

2

Is there any way to draw on the desktop background in WIN32 and also receive notifications when the desktop background is repainted?

I tried this:

desk = GetDesktopWindow();
dc = GetDC(desk);
MoveToEx(dc,0,0,NULL);
LineTo(dc,1680,1050);
ReleaseDC(desk,dc);

But it draws on the whole screen, even over windows that are on the screen.

+1  A: 

Just quoting MSDN:

The GetDesktopWindow function returns a handle to the desktop window. The desktop window covers the entire screen. The desktop window is the area on top of which other windows are painted.

So you are getting a Window with nested windows on them. I'm not quite a WIN32 user, but I think the approach here is get to the lower level, take control of the graphic object that is painting the background picture, and draw there.

ONi
+3  A: 

You can use Spy++ to find which window is the desktop background window.

On my system I see the following hierarchy:

  • Window 000100098 "Program Manager" Progman
    • Window 0001009E "" SHELLDLL_DefView
      • Window 00100A0 "FolderView" SysListView32

I guess you are referring to the SysListView32 - the window with all the icons. You can use FindWindowEx to find this window.

Edit You should use a combination of FindWindowEx and EnumerateChildWindows. The code presented below can be compiled in a command line box like this: cl /EHsc finddesktop.cpp /DUNICODE /link user32.lib

#include <windows.h>
#include <iostream>
#include <string>

BOOL CALLBACK EnumChildProc(HWND hwnd, LPARAM lParam)
{
  std::wstring windowClass;
  windowClass.resize(255);

  unsigned int chars = ::RealGetWindowClass(hwnd, &*windowClass.begin(), windowClass.size());
  windowClass.resize(chars);

  if (windowClass == L"SysListView32")
  {
    HWND* folderView = reinterpret_cast<HWND*>(lParam);
    *folderView = hwnd;

    return FALSE;
  }

  return TRUE;
}

int wmain()
{
  HWND parentFolderView = ::FindWindowEx(0, 0, L"Progman", L"Program Manager");
  if (parentFolderView == 0)
  {
    std::wcout << L"Couldn't find Progman window, error: 0x" << std::hex << GetLastError() << std::endl;
  }

  HWND folderView = 0;
  ::EnumChildWindows(parentFolderView, EnumChildProc, reinterpret_cast<LPARAM>(&folderView));

  if (folderView == 0)
  {
    std::wcout << L"Couldn't find FolderView window, error: 0x" << std::hex << GetLastError() << std::endl;
  }
  HWND desktopWindow = ::GetDesktopWindow();

  std::wcout << L"Folder View: " << folderView << std::endl;
  std::wcout << L"Desktop Window: " << desktopWindow << std::endl;

  return 0;
}

Here are the results after running finddesktop.exe

Folder View: 000100A0
Desktop Window: 00010014

As you can see the window handles are quite different.

Cristian Adam
I change the first line with desk = FindWindowEx(NULL,NULL,L"SysListView32",NULL); but I think it gets the same window as GetDesktopWindow as it has the same effect.
Razvi