XREA.COM Logo XREA.COM Ad

管理人の雑記

11管理人 ★:06/06/17 02:54 ID:???
WheelRedirect.ahkを使用するとTerapadでマウスホイールが効かなくなる件

がスクリプト質問スレッドで報告されていた。
http://lukewarm.s101.xrea.com/test/read.cgi/bbs/1095764510/143

TreaPadを落としてきて試したところ、SendMessageがFAILになっている。
MouseGetPosではウィンドウのハンドルとコントロールのClassNN(TEditor1)は正しく取得されているはずである。
しかし、VisualStudioに付いていたSpy++でTEditor1に送られるメッセージを監視してみたところ、メッセージが送られていないらしかった。
VxEditorなど他のプログラムではちゃんと送られる。
試しに他のコントロール操作系コマンドでもためしてみたが、いずれもTEditor1の操作には失敗する。

とりあえず、最近追加されたコントロールのウィンドウハンドルを指定して直接操作する機能で代用することに。
MouseGetPosの第5引数に2を足してハンドルを取得するように指定し、SendMessageなどの引数は「%ctrl%」から「,ahk_id %ctrl%」に変更する。
多分正常になった。
http://lukewarm.s101.xrea.com/myscripts/WheelRedirect.zip


さて、コントロール操作系コマンドでTeraPadのTEditorが操作できない問題は、TeraPadの問題ではなくAutoHotkeyの問題のような気がする。
Spy++で調べたところ、TeraPadのウィンドウには「TEdit」コントロールと「TEditor」コントロールが存在しているのだ。
AutoHotkeyのことだから、文字列の比較方法を間違ってTEditをTEditorと誤認識しているのだろう。
他にも「TTeraPadExeName」等という訳の分からないコントロールが配置されていて気味が悪いが、今回は無視する。

とりあえずソースコードを検索して「ClassNN」という記述を探したところ、EnumControlFindという関数をみつけた。
コントロールをリストアップするときに呼ばれて、探しているコントロールかどうかをチェックするという物らしい。
大量にあったコメントを削除したため、やたら行番号が飛んでいる。


881 BOOL CALLBACK EnumControlFind(HWND aWnd, LPARAM lParam)
882 {
883 WindowSearch &ws = *(WindowSearch *)lParam; // For performance and convenience.
884 if (*ws.mCriterionClass) // Caller told us to search by class name and number.
885 {
886 int length = GetClassName(aWnd, ws.mCandidateTitle, WINDOW_CLASS_SIZE); // Restrict the length to a small fraction of the buffer's size (also serves to leave room to append the sequence number).
898 if (length && !strnicmp(ws.mCriterionClass, ws.mCandidateTitle, length)) // Preliminary match of base class name.
899 {
909 _itoa(++ws.mAlreadyVisitedCount, ws.mCandidateTitle, 10); // Overwrite the buffer to contain only the count.
910 // lstrcmpi() is not used: 1) avoids breaking exisitng scripts; 2) provides consistent behavior
911 // across multiple locales:
912 if (!stricmp(ws.mCandidateTitle, ws.mCriterionClass + length)) // The counts match too, so it's a full match.
913 {
914 ws.mFoundChild = aWnd; // Save this in here for return to the caller.

最初のif条件に一致すると、ClassNNによる判別が行われる。
886行目でws.mCandidateTitleに候補ウィンドウのクラス名が代入される。
lengthにはクラス名の長さが返される。(「TEdit」なら「5」)
次が問題で、ws.mCriterionClass(与えられた検索対象ClassNN(今回の場合「TEditor1」))とws.mCandidateTitleを「先頭のlength文字」で比較している。
「TEditor1」の先頭5文字は「TEdit」であり、本当は別物なのに一致とみなされてしまう。
さらに、すぐさま「++ws.mAlreadyVisitedCount」で「見つかった数」を増やして、_itoaで文字列に変換した物をws.mCriterionClassのlength文字目以降と比較している。
本来なら「TEdit3」の「3」の部分と「1」を比較するようなものだが、今回は「TEditor1」の「or1」の部分と「1」を比較してしまう。
当然不一致とみなされ、mAlreadyVisitedCountを間違って増やしたまま関数を抜けてしまう。

そして、本当に探している「TEditor1」を検査するときは、mAlreadyVisitedCountは「2」になってしまうので、やはり不一致とみなされる。
結局一致するコントロールは見つからず、一致コントロール無しということでコマンドは失敗してしまう。
単にTeraPadを操作したいだけなら、直接「TEditor2」と指定してやれば見つかるようだが、WheelRedirect.ahkのように動的にClassNNを扱う場合は通用しない。

そんなわけで、予想通りの問題だった。
面倒だがBug Reportsに報告しておくか。
101KB
名前: E-mail:
ファイル:
0ch BBS 2005-10-08