OrangeMaker_logo
memo アイコン SDK-MFC 備忘録

Windows SDKやMFCに関するメモです。
(記載内容について正しいことを保証するものではありません。MSDN等で確認してください)

Windows7 のデスクトップウィンドウ

2010/1/10 作成

  Windows7ではデスクトップウィンドウのウィンドウ階層扱いが変更になっています。

 従来は、Program Manager/Progmanの配下のウィンドウでFindWindow()などでProgram Managerを指定するとウィンドウハンドルが取得できたのですがWindows7ではウィンドウ名なし/WorkWというウィンドウの配下にDeskTopWindowがいます。
(ちなみに、GetDeskTopWindow()で取得できるウィンドウはすべてのトップレベルウィンドウの親(ルート)ウィンドウで、ここで話題にしているのはデスクトップの背景ウィンドウを管理しているウィンドウです。さらにデスクトップの最下位の実態はリストビューで通常のリストビューの機能をデスクトップアイコンを表示しているようです。)

具体的にSpyで見てみると、

Desktop-CompositON  

となっています。Program Manager/Progmanウィンドウは存在しますが、そこではなく/WorkerWウィンドウの配下にDesktopウィンドウがあります。

ただし、この仕様はCompositON(Aeroが有効)の場合のみのようで、CompositをOFFすると従来どおりの階層になります。(下図参照)

Desktop-CompositOFF  

となると、例えばデスクトップウィンドウを探す場合はSHELLDELL_DefViewクラスのウィンドウを配下に持つトップレベルのウィンドウを探すしか方法がなさそうです。

デスクトップウィンドウかどうかの判定は以下のような感じとなります。

//デスクトップウィンドウか判定する
BOOL IsDesktopWindow(HWND hWnd)
{
    //自身のウィンドウクラスが"Progman"か"WorkerW"で
    //子ウィンドウに"SHELLDLL_DefView"クラスのウィンドウを含むか/で判定する
    TCHAR classname[MAX_PATH];
    ::GetClassName(hWnd, classname, MAX_PATH);
    CString s = classname;
    if( (s==_T("Progman"))||(s==(_T("WorkerW")))){
        //子ウィンドウを確認する
        HWND hDt = ::FindWindowEx(hWnd, NULL, 
                 _T("SHELLDLL_DefView"), NULL);
        if(hDt == NULL){
            return FALSE;
        }
        else{
            //ウィンドウがあった!Desktop
            return TRUE;
        }
    }
    else{
        return FALSE;
    }
}
		

まあ、通常はこのウィンドウの存在はあまり意識するとことはなく大抵はGetDesktopWindow()で取得できるルートウィンドウで事が足りケースがほとんどですが、ChildWindowFromPointEx()などでウィンドウを特定する必要がある場合上記を考慮する必要があります