GetDesktopWindow获取的是顶层显示桌面句柄,也就是说,如果应用程序窗口在桌面上,那么它的窗口也算是所获取的窗口的一部分,如果使用GetDC(NULL)作图,则永远是在最顶层。
那么如何获取包含桌面图标的窗口句柄呢?
我们可以用Spy++来查看。
可以看出窗口层次为Progman->SHELLDLL_DefView->SysListView32。于是我们可以这样来获取我们想要的窗口句柄:
HWND hProgMan = ::FindWindow(L"ProgMan", NULL);
HWND hWndDesktop;
if(hProgMan)
{
HWND hShellDefView = ::FindWindowEx(hProgMan, NULL, L"SHELLDLL_DefView", NULL);
if(hShellDefView)
hWndDesktop = ::FindWindowEx(hShellDefView, NULL, L"SysListView32", NULL);
}
然而在Windows7下还会发生另外一种情况(WindowsXP未测试):
其窗口层次为WorkerW-> SHELLDLL_DefView->SysListView32。而且WorkerW还不止一个。此时我们可以这样来获取句柄:
HWND hwndWorkerW=NULL;
HWND hShellDefView=NULL;
HWND hwndDesktop=NULL;
while(hwndDesktop==NULL)//必须存在桌面窗口层次
{
hwndWorkerW=::FindWindowEx(0,hwndWorkerW,L"WorkerW",NULL);//获得WorkerW类的窗口
if(hwndWorkerW==NULL)
break;//未知错误
hShellDefView=::FindWindowEx(hwndWorkerW,NULL,L"SHELLDLL_DefView",NULL);
if (hShellDefView==NULL)
continue;
hwndDesktop=::FindWindowEx(hShellDefView,NULL,L"SysListView32",NULL);
}
注意:上述代码中没有用FindWindowW,这是因为我们需要指定从哪一个窗口往下查找。
在用以上方法获得的桌面窗口句柄上绘图,将会和桌面图标处于同一层次(即会被应用程序窗口覆盖),并且覆盖桌面图标。
那么什么时候会出现后一种情况呢?动态桌面(桌面壁纸定时更换)的环境下便会出现。但是当你在现行环境中更改了此设置后,这种现象并不会立即出现,要想让它“现出原形”,可以注销再登录,或者干脆重启。
我曾试过在动态桌面下绘图,情况会比较糟糕——我的桌面很卡。也可能是我的代码不好。
最后说明一点:这里获得的桌面窗口是一个ListView控件,可以用以ListView_开头的宏操作,具体可查看MSDN文档。