2011-12-03 40 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 
     } 
    } 
}