获取桌面/ shell窗口的句柄

在我的一个程序中,我需要testing用户是否正在关注桌面/shell窗口。 目前我使用user32.dll中的GetShellWindow(),并将结果与​​GetForegroundWindow()进行比较。

这种方法是一直工作,直到有人改变桌面墙纸,但一旦墙纸改变GetShellWindow()的句柄不再匹配从GetForegroundWindow()了,我不明白这是为什么。 ( 操作系统: Windows 7 32位)

有没有更好的方法来检查桌面是否集中? 优选地,如果用户改变壁纸,那么不会损坏的那个?

编辑:我devise了一个解决方法:我正在testing的句柄有一个“SHELLDLL_DefView”类的孩子。 如果有的话,桌面上的焦点。 虽然它在我的电脑上工作,但并不意味着它会一直工作。

Solutions Collecting From Web of "获取桌面/ shell窗口的句柄"

由于在Windows 7中有可用的幻灯片作为壁纸,所以事情发生了一些变化。您正好与WorkerW,但是这只适用于壁纸设置为幻灯片效果。

当将壁纸模式设置为幻灯片时,您必须搜索WorkerW类的窗口并检查子WorkerW是否有SHELLDLL_DefView 。 如果没有幻灯片,可以使用旧的GetShellWindow()

几个月前,我遇到了同样的问题,我写了一个获取正确窗口的函数。 不幸的是我找不到它。 但以下应该工作。 只有Win32导入丢失:

 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; } } 

在你的情况下,你会调用GetDesktopWindow(DesktopWindow.SHELLDLL_DefViewParent); 得到顶层窗口来检查它是否是前景窗口。

这是一个解决方法,它使用GetClassName()来检测桌面是否处于活动状态:

  • 当Windows第一次启动时,桌面的类是“Progman”
  • 更换壁纸后,桌面的类将是“WorkerW”

您可以测试这些以查看桌面是否集中。

 [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 } } }