トップ «前の日記(2002-12-01(Sun)) 最新 次の日記(2002-12-07(Sat))» 編集

K2さんの雑記


2002-12-06(Fri) [長年日記]

[TTBase]atext(ALT+TABのタスクリスト一覧)

naoさんちのatextプラグイン。TTBase用のALT+TAB置換用。もともとは、ここでも紹介したJoeをnaoさんが雑記で紹介したことに端を発する。Joeで、一覧を小さくしたいな、ウィンドウ出っぱなしがいいなと言ってたら、naoさんが作ると言うことになった。そういう小物を簡単に書けるようなぶっこみ常駐ソフトがあったらなとnaoさんがもらした。じゃぁ汎用的なのを書きましょということでTTBaseの初期アイデアができたのでした。

で、その発端となったatext。WindowsのALT+TABって突き詰めて調べると、かなりかしこいのであった。アプリケーションが設定ダイアログを出していた場合、その設定ダイアログにフォーカスがあたる。当たり前のように見えて、これが非常に難しい。そうだなぁ、EnumWindowsでアプリの一覧が欲しいという要望は、わたしの中ではWindows開発を始めた頃から何回もあって、そのたびにいろいろと逃げの手を打ってきたのだが、そろそろ突き詰めてもいいんじゃないかと、ちょっとがんばってみました。オープンソースの場合、誰でもそのソースが修正できるから、気が向いた人が気が向いたときに修正できるのでいいね。

もともと、EnumWindowsで得られたトップウィンドウ一覧から、どうやってゴミのウィンドウをふるい落とすかをいろいろ試行錯誤していたのだけども、どうしてもうまくいかない。一つのアプリで2つ以上のウィンドウが一覧されてみたり、それがいやでふるい落とす条件を厳しくすると表示されないものが出てきたり、いい落としどころがない。

その後、先ほど書いたことだが、モーダルダイアログなどがメインウィンドウの上に出ている場合は、そのモーダルダイアログにフォーカスを当てないといけないことが判明。フォーカスを当てようとするときに、もう一度EnumWindowsをやって、そのウィンドウの上にあるウィンドウを探そうとしたが、それもすべてのアプリについてはなかなかいい条件がわからなくて。

だいたい、Delphi製のアプリがまず例外の一番手。Delphi製のアプリには、見えないTApplicationというサイズ0のウィンドウがいることは結構有名な話なんだが、これとメインフォームとの区別がなかなか付かない。OSはどうやって区別しているか、いろいろ調べているがわからない。

Winampは、メインパネルがオーナーで、その下にプレイリストとかイコライザーとかがぶら下がっているが、親子関係はない。これも例外の一つ。

ウィンドウには、オーナーと親子関係という2つの関係が存在することをここで書いておくが、この辺が、タスクボタンが出るかとか、ALT+TABで表示されるかどうかとかに密接に絡んでくるのだ。

で、いろいろ調べて、だいたいわかった結論が以下。

タスクボタンに表示されるのは、EnumWindowsで得られるトップウィンドウのうち、オーナーと親ウィンドウがないウィンドウで、ウィンドウスタイルにWS_DISABLEDがなく、WS_VISIBLEであり、拡張ウィンドウスタイルにWS_EX_TOOLWINDOWがないもの。

ALT+TABで表示されるのは、上記のウィンドウをオーナーに持つウィンドウのうち、EnumWindowsで一番最初に列挙されるフォーカシング可能なウィンドウ。

ここには例外があって、オーナーと親を持たないウィンドウがWS_EX_TOOLWINDOWの場合、そのウィンドウがダイアログを所有すると、そのダイアログはALT+TABに表示される。

わかってみれば、そんなに複雑なロジックではない。で、ALT+TABのリストを得るためには、具体的にはどうするか。

まず、EnumWindowsで、親もオーナーも持たないウィンドウ(つまり最上位のオーナーウィンドウ)の一覧を取得する。その際、WS_EX_TOOLWINDOWを持つものはタスクボタンが出ないので、除去する。例外として、ダイアログを見つけたら、その最上位オーナーを捜して、それがWS_EX_TOOLWINDOWだったら、それは一覧に追加しておく。

次に、その最上位オーナー一覧を保存しておいて、もう一度EnumWindowsを行う。その際、WS_DISABLEDでなくWS_VISIBLEであり、WS_EX_TOOLWINDOWでないウィンドウを見つけたら、その最上位オーナーを捜し、最上位オーナー一覧のオーナーウィンドウをそのウィンドウで置き換える。一度置き換えたら、一番最初のウィンドウを優先するため、そのウィンドウは固定する(もう入れ替えない)。ただし、最上位オーナーウィンドウがフォーカスを得られる場合(つまりWS_DISABLEじゃなくWS_VISIBLEな場合)、そのウィンドウを優先する。

最後に、2回目のEnumWindowsで置き換えられなかったウィンドウは、フォーカシング可能なウィンドウがないということだから、オーナーウィンドウ一覧から除去する。(最上位オーナーウィンドウが条件にマッチして結果的に置き換えられなかったものは除去しない)

これで、ALT+TABの一覧を得ることができる。ただし、これでもDelphiのTApplicationウィンドウを避けることができないので、2回目のEnumWindowsで、サイズが0のウィンドウははじくようにする。OSがサイズ0のウィンドウを特別扱いしているとはわたしには思えないので、この部分のロジックがわたしの中では未解決。

というわけで、これでだいたい完全なALT+TABリストを得ることができました。ちょい疲れたけど、なかなかいい勉強でした。

[追記]

文章をまとめていて気づいたが、TApplicationは、もしかしてEnumWindowsで列挙されるウィンドウ順で、必ずメインウィンドウより後ろに列挙されるのではないか。そうだとしたら、上記のロジックでウィンドウ一覧を集める場合、サイズ0のウィンドウをはねる必要がなくなるな。確かにSpy++などで見ていると、TApplicationは、たいていメインウィンドウのいくつか後ろにいる。

なるほどそういうことか。最後の謎も氷解。ALT+TABを見切らせていただきました。

[追記2]

だめだ。追記は間違い。最上位オーナーは優先するから、TApplicationの列挙順序が後ろでも優先されちゃうんだよなぁ。やっぱ、ここは謎のまま。


1965|09|
2002|09|10|11|12|
2003|01|02|04|05|06|07|08|09|10|11|12|
2004|01|02|03|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|07|08|09|10|11|12|
2011|01|02|03|04|05|06|07|08|09|10|11|12|
2012|01|03|04|05|08|
2014|01|02|03|04|05|08|09|10|11|12|
2015|01|02|03|04|05|06|07|08|09|10|11|12|
2016|01|02|03|04|05|06|07|08|09|11|
2017|01|03|05|06|07|08|10|11|12|
2018|01|02|03|04|05|08|09|10|12|
2020|01|07|




2002年
12月
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
//
自己紹介
自己紹介
広告
計るだけダイエット
つっこみリスト
TrackBacks
日記仲間
/ / /
最近の日記