[BlueLeaf1336]> PROBLEMS> ClickThereItIs!>
history | TOP |
2004/01/09:作成
2004/01/10:更新
2004/01/22:更新
2004/01/24:更新
overview | TOP |
WindowsのダイアログのClassNameは(今のところ)"#32770"のようなのでこのClassNameをもつウィンドウの出現と消滅に反応するプログラムを作ります。
ただ、「開く/保存」ダイアログ - とりあえずこの2種類のダイアログをタゲるのですが(以下タゲアログ) - を含む全てのダイアログが同じClassNameを持つらしいので、他のダイアログとタゲアログを区別する必要があります。
たぶんですが、このボタンとこのコンボボックスとこのリストビューと...を部品に持つから...みたいに泥臭く判定することになります。ですので、タゲアログが共通的に持つ部品を調べる必要があります。
方針 | TOP |
タイマーなどでEnumWindowなんとかいうAPIで定期的に見張るか、DLLを使ってなんとかフックを仕掛けてウィンドウの作成と破棄を見張るかどっちかになりそうです。当初の目標としてはDLLなんぞ使わん、と思ってましたが、タゲアログがアクティブになったかとかアクティブでなくなったか(≒他のウィンドウがアクティブになったか)、つまりアクティブなウィンドウの切り替わりを見張るために、DLLフックが必要なような気がしなくもないので、どうせ最終的にDLL使わなアカンなら最初から使ってみよう、な気がしています。
というわけで、このページではDLLフックによるダイアログの生成・破棄の監視と、ダイアログとタゲアログ(それからもちろんその他のウィンドウ達)を見分ける為の足掻きを記録していきます。
とりあえず、このシリーズでテストしたことのあるDLLフックから手をつけることになりそうです。
方針-再考 | TOP |
CBTフックを行います。何故か?このフックでは、ウィンドウの作成される瞬間・破棄される瞬間・アクティブなウィンドウの切り替わる瞬間(...他いろいろ)を取得できるためです。「方針」のクセにこのあたりでPlatform SDK等を引用してみます。えー、取得できる情報についてだけにしときます。(about to ... を ...されつつある、と訳しています。自信はないですがそれっぽい感じがします)
Microsoft Platform SDK February 2003 / CBTProc Function
HCBT_ACTIVATE
- overview:
システムはウィンドウをアクティブにしそう- wParam:
アクティブになりそうなウィンドウのハンドル- lParam:
CBTACTIVATESTRUCT構造体へのロングポインタtypedef struct { BOOL fMouse; HWND hWndActive; } CBTACTIVATESTRUCT, *LPCBTACTIVATESTRUCT;fMousehWndActive
- アクティブになりそうなウィンドウが、マウスクリックによるものかどうか。TRUEならそう。FALSEならそうでない。
- アクティブなウィンドウのハンドル(wParamとは違うんだろうねぇ。直前にアクティブな...だといいな)
HCBT_CREATEWND
- overview:
ウィンドウが作られかけ。ウィンドウがWM_CREATEやWM_NCCREATEメッセージを受け取る前に、フック関数が呼ばれる。フック関数が非0値を戻したら、システムはウィンドウを破棄する。0ならウィンドウは普通に作られる。 HCBT_CREATEWND通知時にはウィンドウは既に作成されているが、最終的なサイズ・位置は決定されておらず、その親ウィンドウはestablishedされていない(???)。新しく作られたウィンドウは、WM_NCCREATE/WM_CREATEメッセージを受け取ってないけども、メッセージを受け取ることができるし、CBT_CREATEWND構造体内のhwndInsertAfterフィールドを修正すればZオーダーを変更することもできる。- wParam:
新しいウィンドウのハンドル- lParam:
CBT_CREATEWND構造体へのポインタ。typedef struct { LPCREATESTRUCT lpcs; HWND hwndInsertAfter; } CBT_CREATEWND, *LPCBT_CREATEWND;lpcshwndInsertAfter
- 作られつつあるウィンドウの初期化パラメータを含むCREATESTRUCT構造体へのポインタ。
typedef struct tagCREATESTRUCT { LPVOID lpCreateParams; HINSTANCE hInstance; HMENU hMenu; HWND hwndParent; int cy; int cx; int y; int x; LONG style; LPCTSTR lpszName; LPCTSTR lpszClass; DWORD dwExStyle; } CREATESTRUCT, *LPCREATESTRUCT;lpCreateParamshInstance
- 新しく作られるウィンドウの追加情報。(大きく略)
hMenu
- 新しいウィンドウを所有するモジュールのハンドル
hwndParent
- 新しいウィンドウが使用するメニューのハンドル
cy
- そのウィンドウが子ウィンドウなら親ウィンドウへのハンドル。所有されているウィンドウなら所有しているウィンドウへのハンドル(???)。どっちでもなければNULL
cx
- 新しいウィンドウのピクセル単位の高さ
y
- 新しいウィンドウのピクセル単位の幅
x
- 新しいウィンドウの左上のY座標。親を持つなら親からの相対座標。でなければスクリーン座標。
style
- 新しいウィンドウの左上のX座標。親を持つなら親からの相対座標。でなければスクリーン座標。
lpszName
- 新しいウィンドウのウィンドウスタイル
lpszClass
- 新しいウィンドの名前(NULLで終わる文字列のポインタ)
dwExStyle
- 新しいウィンドのクラス名(NULLで終わる文字列のポインタ)
- 新しいウィンドウの拡張ウィンドウスタイル
- Handle to the window whose position in the Z order precedes that of the window being created.(訳不可。分からん。)
HCBT_DESTROYWND
- overview:
ウィンドウが破棄されそう- wParam:
破棄されつつあるウィンドのハンドル- lParam:
未定義。0でないとだめ。
全く分かりにくいまとめになりました。Platform SDKってリンク張りすぎ。まあでもこれだけの情報があれば、タゲアログの生成と破棄を見張れるでしょうな。余裕で。ややこしそうなアクティブウィンドウの切り替わりは置いときましょう。それから、破棄の方は(言われれば当然だが)ウィンドウハンドルだけしか教えてもらえないので、気をつける必要がありそうです。
ウィンドウの生成・破棄の監視 | TOP |
早くテストプログラム作りたいけど、DLLとかフックとかメモリマップドファイルとかあれとかこれとかするのが邪魔くさいので、とりあえず簡単そうなところからイメージトレーニングします。
実は、このシリーズで全種類フックを試すヘナチョコなプログラム(DLLはフックをするだけ。全て呼び出し側のEXEにフックしたメッセージに1対1対応するユーザ定義メッセージをPostMessageするような奴。具体的なアクションを全てEXE側にコーディングしたいなぁ...というコンセプトで)を作成したんですが、それを使ってちょっと試したところ、PostMessageで受けたLPARAMをたとえばCBTACTIVATESTRUCT(のWindows.pas版)でEXE側でキャストして構造体のフィールドにアクセスするとAccess Violationでエラーになってしまうんです。
少し考えてみたんですが、フック直後とPostMessageを介していくらかのタイムラグの後受けた場合とでLPARAMの中身の構造体がどうにかなるんではないかと。もしくはプログラムのバグかと(ただ、フックなんてのは本当に決まりきった形でしか書けないのでバグではないような気がします...可能性はあるにしても)。
さあ、そういうわけで、EXEとDLLのとりあえずのフックを書いてみましょう。
2004/01/22
書いてみました。というかホッポリだしといたのを反省して再開しました。とはいえ、今の段階ではクラス名が"#32770"のウィンドウが生まれた場合と、殺されかけている場合をDLL内のCBTフック関数で判定してインストールしたEXEに通知しているだけです。
つまり、ダイアログの生成と破棄だけを監視できた状態です。
本当は1対1で生まれて死ぬだけなんですが、ZoneAlarmのAbout画面を出したタイミングで、なぜか図の上から3行分さらに隠れてしまった何行か分の「死にかけ」メッセージが飛んできました。が、まあフックする前に作成されていたダイアログが何らかの原因でどうにかなったんだろうということにしておきます。
次は、ただのダイアログ(クラス名だけで見分けられる)とタゲアログ(Windows標準のファイル開きダイアログあるいはファイル保存ダイアログ)を見分けることができるか?に手を付けたいと思います。
多分判別方法が、このクラスを子ウィンドウに持っているとかになりそうなので、とりあえず指定したウィンドウのクラス名とかテキストとかスタイルとかを簡単に確認できるようなツールを作ってみたりして。もちろん既に世の中には大量に存在しているツールであるのは間違いないのですが...たとえば
でも、作ります。もっともっとヘチョイ奴を。
ツール - 参考URL用HTML出力ツール | TOP |
2004/01/25
こんなツールを作りました。
同じプロセスに属していないウィンドウの属性を ( SetWindowLong() で ) 変更するには?
http://techtips.belution.com/ja/vc/0026/
フォルダを選択するダイアログ(後編)
http://www.kab-studio.biz/Programing/Codian/ShellExtension/04.html
「開く」と「保存」ダイアログボックス
http://www.interq.or.jp/www-user/wanderer/program/memo/msdn_jp/User_Interface_Services/Windows_User_Interface/User_Input/Common_Dialog_Box_Library/Common_Dialog_Box_Library_Overviews/OpenAndSaveAsDialogBoxes.html
"コモンダイアログの表示位置を変更"
http://forum.nifty.com/fdelphi/samples/00490.html
VB テクニック編31 - サブクラスコントロール、フックプロシジャ、メッセージ処理
http://homepage2.nifty.com/sak/w_sak3/doc/sysbrd/vb_t31.htm
サブクラス化
http://black.sakura.ne.jp/~third/system/winapi/win64.html
共有メモリを利用するには?
http://techtips.belution.com/ja/vc/0001/
上記のようなテキストファイルがある、あるいはクリップボードにこんなテキストがコピーされている場合に(具体的には、1行目がタイトル、2行目がURL、3行目がタイトル、4行目がURL、...と続く)
上記の表示になるようなHTMLを出力するツールを作りました。作った理由は、参考URLをメモ帳か何かでタイトルとURLをぼこぼことコピーしてためていた場合に、サイトに参考文献として掲載する際にそのリンクを再構成するのが邪魔くさいなぁと思ったからですが、このプログラムをわざわざ立ち上げるのもなぁという今日この頃です。
20040124MaeterLink.zip(10,927bytes)※ソースコードと実行ファイルです。
が、HrefBuilderの方がまだマシです。(2004/10/27)
次ページへ続く | TOP |
2004/01/29
ウィンドウ覗き見ツール作る予定でしたが、あとまわし。adrenalineをみてもらえば分かると思いますが、一番難しいと思っていた箇所が試せそうです。先に試します。
EOF | TOP |