none
GetWindowで取得したポップアップメニューなどが所属するアプリケーションウィンドウを判定するには? RRS feed

  • 質問

  • 与えられたアプリケーションウィンドウについて、それにかぶさっているウィンドウを列挙しようとしています。そこでGetWindow(hwnd, GW_HWNDFIRST)を使うのですが、IEについてそれを行っていると

    • ボタンバーをクリックしたときに出てくるポップアップメニュー
    • ボタンにマウスを乗せたときに出てくるツールチップ
    • アドレスバーから下にせり出すサジェスト

    などが「かぶさっている」ものとして出てきてしまいます。もちろん、これらは「関係者」ですから除外したいのですが、どのようにそのことを判定可能でしょうか?

    GetWindow( item, GW_OWNER), GetParent( item ), GetAncestor( item, * ), IsChild() のいずれでも、関係者だと判定できませんでした。


    ウィンドウ構造を調べてみようにも、どれも他のアプリに切り換えた途端に消えてしまう表示物なのでSpy++で引っかけることもできず…
    • 編集済み miuras_net 2015年11月10日 5:53 Spy++が使えない理由
    2015年11月10日 5:39

回答

  • GetWindowThreadProcessIdでHWNDからプロセスIDとスレッドIDが取れるので、EnumWindowsでトップレベルウィンドウを列挙して同じプロセスIDなら同じアプリケーションであると判定はできます。
    ポップアップウィンドウはトップレベルウィンドウになるのでEnumWindowsだけでいいはず。
    あとは、スレッドIDも同じウィンドウは関係があるとみなす位までなら判定可能かも。(親子関係があっても別スレッドの可能性はあるので)


    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    • 回答としてマーク miuras_net 2015年11月11日 0:39
    2015年11月10日 9:48
  • 追加情報:

    IEは一般的なWin32アプリに比べてウィンドウ構造が特殊なことがわかってきました。

    • ツールチップおよびメニュー(メニューバーのものも、コンテキストメニューも)が、メインウィンドウと別のプロセスで動いています。これはどうやら32ビット版と64ビット版の協調動作のためのようです。
      これらのウィンドウが出現するのはメインウィンドウがフォアグラウンドのときに限られるので、
      ・IEメインウィンドウがフォアグラウンド
      ・ウィンドウの所有プロセスの実行ファイル名がiexplore.exe
      なら所有があろうと判定できました。
    • スクリプトからalert()やconfirm()で出したダイアログが、一見モーダルダイアログのように見えて、これも別プロセスで動作しています。モーダルダイアログのように偽装(メインウィンドウが触れなく)するために、メインウィンドウの上には同じサイズの透明なウィンドウがかぶせられます(まるでWebデザインにおける疑似モーダルダイアログを作っているようです)。この透明ウィンドウのクラス名は"Alternate Modal Top Most"です。モーダルダイアログはこのAlternate Modal Top Most に所有されています。
      ウィンドウクラス名・位置・サイズから所有関係を推測しました。
    • 回答としてマーク miuras_net 2015年11月11日 8:25
    2015年11月11日 8:25

すべての返信

  • GetWindowThreadProcessIdでHWNDからプロセスIDとスレッドIDが取れるので、EnumWindowsでトップレベルウィンドウを列挙して同じプロセスIDなら同じアプリケーションであると判定はできます。
    ポップアップウィンドウはトップレベルウィンドウになるのでEnumWindowsだけでいいはず。
    あとは、スレッドIDも同じウィンドウは関係があるとみなす位までなら判定可能かも。(親子関係があっても別スレッドの可能性はあるので)


    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    • 回答としてマーク miuras_net 2015年11月11日 0:39
    2015年11月10日 9:48
  • gekkaさん、ありがとうございます。
    試してみてお返事します。

    2015年11月11日 0:32
  • スレッドIDを基準に判定する方法で、いろいろ操作を試してみましたがどれも期待通りの判定ができました。
    2015年11月11日 0:40
  • 追加情報:

    IEは一般的なWin32アプリに比べてウィンドウ構造が特殊なことがわかってきました。

    • ツールチップおよびメニュー(メニューバーのものも、コンテキストメニューも)が、メインウィンドウと別のプロセスで動いています。これはどうやら32ビット版と64ビット版の協調動作のためのようです。
      これらのウィンドウが出現するのはメインウィンドウがフォアグラウンドのときに限られるので、
      ・IEメインウィンドウがフォアグラウンド
      ・ウィンドウの所有プロセスの実行ファイル名がiexplore.exe
      なら所有があろうと判定できました。
    • スクリプトからalert()やconfirm()で出したダイアログが、一見モーダルダイアログのように見えて、これも別プロセスで動作しています。モーダルダイアログのように偽装(メインウィンドウが触れなく)するために、メインウィンドウの上には同じサイズの透明なウィンドウがかぶせられます(まるでWebデザインにおける疑似モーダルダイアログを作っているようです)。この透明ウィンドウのクラス名は"Alternate Modal Top Most"です。モーダルダイアログはこのAlternate Modal Top Most に所有されています。
      ウィンドウクラス名・位置・サイズから所有関係を推測しました。
    • 回答としてマーク miuras_net 2015年11月11日 8:25
    2015年11月11日 8:25