2011-12-03 42 views
4

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

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

是否有更好的方法来检查桌面是否集中?如果用户更换壁纸,最好不要破坏一个?

编辑:我设计了一种解决方法:我正在测试句柄以拥有类“SHELLDLL_DefView”的子类。如果有的话,桌面上的焦点。虽然它在我的电脑上工作,但并不意味着它会一直工作...

+0

你试过了GetDesktopWindow吗? –

+0

我想我没有。我可能弄错了,但我想我曾经读过ShellWindow是真正的桌面(自Win95以来的桌面),而DesktopWindow是之前已经可用的桌面,并且实际上存在于ShellWindow之后... – MFH

+2

是的,你是对的,GetShellWindow是正确的。 http://blogs.microsoft.co.il/blogs/pavely/archive/2011/06/18/getshellwindow-vs-getdesktopwindow.aspx那么更改壁纸后,你会得到哪个过程窗口? –

回答

5

由于在Windows 7中提供了幻灯片作为壁纸,因此事情有所改变。 您正对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);得到顶层窗口,检查是否是前台窗口。

+0

谢谢,我已经有一个解决方法我自己。我认为你的答案不是100%正确的,因为我没有幻灯片,但GetShellWindow()失败... – MFH

+0

来源:http://www.codeproject.com/Articles/639486/Save-and-restore-icon-位置上桌面 –

3

下面是一个使用GetClassName()检测如果桌面是活动的一种变通方法:

  • 当Windows首次启动时,桌面的类别是“普罗格曼”
  • 更改墙纸后,桌面的班会“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 
     } 
    } 
}