喫茶XRAYトップページ

[スレッド全体
]

[6323] 今度はグローバルフックに返信 削除
2012/9/6 (木) 17:39:23 Taki
マスターこんばんは。Takiです。

今、パソコンのマウス操作を記録するプログラムを作っています。
例えば、スタートボタンをクリックしたら「スタート」、すべてのプログラムを
クリックしたら「すべてのプログラム」・・・のようにです。

その情報を得るのにIAccessibleが非常に役立っています。

ところが問題があります。

「メモ帳」を「閉じる」とメモ帳のウィンドウが消えるので、記録されるのが
「デスクトップ」になってしまうのです。
メニューを選んだ時も同じで、「コピー」をクリックすると、メニューが消えるので
記録は「Edit」になってしまいます。

今はタイマーでif((GetAsyncKeyState(VK_LBUTTON) and $8000) = 0) を監視しています。
この方法では情報を得る前に対象が消えてしまうので、やはりメッセージのフックを
使うべきなのかなと思っています。

マスターの「290_グローバルフック WH_GETMESSAGE」サンプルを教材にして色々と
勉強しましたが、DLLのplHookGetMessageUnit中のMyHookProc関数の中身が分かりません。

nCodeが負の時はCallNextHookEXで処理するとか、nCode=HC_ACTIONの時に処理するとかは
msdnとかにもそのように書かれているので何も考えないようにそのように・・・

分からない所は、wParam=PM_REMOVEの時にメッセージ情報をDLLからアプリケーションに
返して(PostMessageして)ありますよね。
説明には「この関数を通過後メッセージキューからメッセージが削除される」とあります。
「この関数を」の関数はMyHookProcのことですか。

それと、私のメッセージ処理に対するイメージは、メッセージを覗いたら
inherited WndProc(Message)で後処理するといった事なのですが、そうした命令が無いのも
理解できないのです。

上のメッセージフックの仕組みに対する疑問とは別に、メッセージを本来のウィンドウに
届くのを待たせるようなコードが書けるのかという事が最大の問題です。

フックのコールバック関数に重い処理は書くなと書いてあったし、DLLにIAccessibleの
コードを・・・なんて考えたくもありません。

何か良い方法は無いでしょうか。

[6324] Re:今度はグローバルフックに返信 削除
2012/9/6 (木) 17:54:43 Mr.XRAY
▼ちはっ!  Takiさん

> 「メモ帳」を「閉じる」とメモ帳のウィンドウが消えるので、記録されるのが
> 「デスクトップ」になってしまうのです。


そうなんですよね.
「閉じる」を検出したときは,そのウィンドウがないので,
実際には検出できないんですよね.
どうしてこんな仕様になっているんでしょうね.

本来操作の記録には,WH_JOURNALRECORD というフックがあるのですが,
これは,Vista 以降では使えないし.

> 何か良い方法は無いでしょうか。

というわけでがんばってください!! (笑)

>nCodeが負の時はCallNextHookEXで処理するとか、nCode=HC_ACTIONの時に処理するとかは
>msdnとかにもそのように書かれているので何も考えないようにそのように・・・


nCodeが負の時は,Windows が処理するので,そうしておかないと,
まずいようです.
そのため,サンプルでは,わさわざ最初の部分で,この処理をして抜けている
コードにしてあります.

>説明には「この関数を通過後メッセージキューからメッセージが削除される」とあります。
>「この関数を」の関数はMyHookProcのことですか。


後で確認いたしますです.
その他も後で.(^^;

[6325] Re2:今度はグローバルフックに返信 削除
2012/9/6 (木) 20:55:53 Taki
▼ マスター お世話になります。

inherited WndProc(Message)に相当する命令が分かりました。

CallNextHookExなのですね。

http://komina.so.land.to/index.php?Windows%2FAPI%2F%A5%A4%A5%D9%A5%F3%A5%C8%A5%D5%A5%C3%A5%AF

CallNextHookExって何をしているのでしょうね?

msdnによると「現在のフックチェーン内の次のフックプロシージャに、フック情報を渡します。」
登録したフック関数はMyHookProc1個だけだから、次のフックプロシージャって無いのでは?

逆に言えば、複数のフック関数を登録できるということ?
あ〜 踏み込んではいけない領域に踏み込んだみたい。

「何か良い方法・・・」を考えてみました。

メモ帳の「閉じる」をクリックする。
「閉じる」をクリックしたことをメッセージフックで知る。
メモ帳へのメッセージを殺す。
「閉じる」ボタンの情報をIAccessibleで得る。
メモ帳へ「閉じる」のメッセージをねつ造して(こそっと)送る。
メモ帳は消える。めでたし

・・・できそうにないですね。(T_T)

[6326] Re3:今度はグローバルフックに返信 削除
2012/9/6 (木) 23:18:19 Mr.XRAY
▼ Takiさん

本題の方はさて置いて(置くなちゅうの!)

> CallNextHookExって何をしているのでしょうね?

これは,msdnの記事の通りで,
起動中,あるいはこれから起動するアプリも含めて)
Windows のアプリ(目に見えているものとは限らない)にメッセージを送るわけです.
これをしないと,同じフックを使っているアプリが処理できなくなります.
つまり,フックを使っているのは,自分のアプリだけではないということです.
サービスプログラムなんかは,もしかしたらフックのオンパレードかも
知れません.

意識的にCallNextHookEx をしないこともあります.
実は,このサイトにそのようなコードがあるのです.
どれかは,ナイショです(笑)


[6327] Re4:今度はグローバルフックに返信 削除
2012/9/6 (木) 23:20:14 Mr.XRAY
> Windows のアプリ(目に見えているものとは限らない)にメッセージを送るわけです.
> これをしないと,同じフックを使っているアプリが処理できなくなります.


この意味で,フック内でメッセージを処理する場合は
基本的に,PostMessageなんですね.

ためしに,SendMessage を使うと,サンプルによっては,
面白いことになります.


[6328] Re5:今度はグローバルフックに返信 削除
2012/9/7 (金) 18:18:47 Taki
▼ マスター お世話になります。

> つまり,フックを使っているのは,自分のアプリだけではないということです.

そうですか。
他のアプリが先にフックを設定していたら自分のアプリで止めると変なことに
なってしまいますね。
メッセージの内容を途中で変更しても同じことが言えるのでは。

やはり踏み込んではいけない領域ですね。


> この意味で,フック内でメッセージを処理する場合は
> 基本的に,PostMessageなんですね.
>
> ためしに,SendMessage を使うと,サンプルによっては,
> 面白いことになります.


PostMessageはポストに手紙を投函するだけなのでさっさと帰れますが、
Sendmessageは相手の家まで手紙を届けないといけないのでなかなか
帰って来れません。

制御が返ってこないということは「面白いこと」では済まないような気も・・・。

今回の問題はメッセージフックでも解決できない気がしてきました。(;_;)

でも、メッセージフックの勉強にはなりました。
ずーっとメッセージ関係の処理は避けていたので一歩前進できた気分です。

[6329] Re6:今度はグローバルフックに返信 削除
2012/9/7 (金) 21:00:10 Mr.XRAY
▼ Takiさん

> PostMessageはポストに手紙を投函するだけなのでさっさと帰れますが、
> Sendmessageは相手の家まで手紙を届けないといけないのでなかなか
> 帰って来れません。


おおっ! これは使えるフレーズですね.
これから,もし,PostMessage と SendMessage の説明が必要な場面が
あったら使わせていただきます.

Halbow さんのコードをよく見てみると,PostMessage で受ける部分と,
その処理の部分を別のプロシージャーにしています.
こんなのも,ちょっとした「ノウハウ」なんじゃないかと思います.
単なる tips だけでは説明しにくい部分ですね.

ワード,エクセル操作フォームExでは,受けた処理が追いつかない
場合は,フラグを使って処理しています.

[6330] Re7:今度はグローバルフックに返信 削除
2012/9/8 (土) 11:36:16 Taki
▼ マスター 報告です。

マスターのサンプルプログラム 260_グローバルフック(キー・マウス)より
03_WH_MOUSE_LLとWH_KEYBORD_LLをいじってみました。

DLLを使用しないで済むのが良いのと、マウスフックのコールバック関数の
PostMessageをSendMessageに変えたらどんなおもしろいことがあるのかなと
興味がでまして・・・。

それと、フックしたマウス情報を受け取る関数 TForm1.WMApp100に
sleepも入れてみました。

LButtonDownでは両方ともWindowのキャプションはメモ帳でしたが、
LButtonUpでは違う結果になりました。(^_^)v

[▼次のスレッド]
INCM/CMT
Cyclamen v3.82