• 締切済み

キーボードフックについて

現在グローバルフックでキーボードからマウスを操作するプログラムを作成中です。 dll内にフックプロシージャを作成し、十字キーが押されたら呼び出し元のウインドウにWM_USERを送るというつくりになっています。 コードを組んだところ、一応動いたのですが、一度だけキーを押したはずなのにWM_USERが2,3回ぐらい送られてきます。 これを回避する方法はあるのでしょうか? どなたかご教授お願いします。 <環境> Windows Vista VC++ 2005 Express Edition

みんなの回答

回答No.1

お疲れ様です。 「WM_KEYDOWN」をフックしていると思って間違いないでしょうか? 参照URLに記載されているようにオートリピート機能で1回の押下で複数のイベントが発生します。 回避方法というか対応方法も参照URLを参照の事。

参考URL:
http://yokohama.cool.ne.jp/chokuto/urawaza/message/WM_KEYDOWN.html
全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • キーボードフックの使い道

    dll のソースの一部です。 LRESULT CALLBACK MyHookProc(int nCode, WPARAM wParam, LPARAM lParam) {  if ( wParam == 0x31 )処理;  return CallNextHookEx(hHook, nCode, wParam, lParam); } 処理の部分では、MessageBox( ) とか MessageBeep( ) ぐらいしか 使えません。 「ぬ」 のキーが押されたら、メインのウインドウのエディットボックスの 文字を書き替えたりしたいんだけど、キーボードフックのプロージャの 中では、文字列の書き替えをすると、アプリケーションが強制終了します。 メモリマップドファイル、グローバルメモリの書き替えもやってみたけど キーボードフックのプロージャの中からはできませんでした。 dll の中なのに、キーボードフックのプロージャの中では 自分自身を LoadLibrary( ) して、GetProcAddress( ) とかしないと メモリの書き換えとかができないんですか? キーボードフックのプロージャの良い活用法を教えてください。

  • グローバルフックについて

    VC++6.0でグローバルフック用のDLLを作っていて、どうしてもわからないので質問させていただきます。 フックの内容は、ウィンドウが最前面にあるかどうか常に監視したいので、状態が変わるメッセージをフックしています。 フック対象はとあるゲームなんですが、テストのためにメモ帳を対象にテストをしました。 まず、spy++でウィンドウの状態を変化させたときに送られてくるメッセージを調べた結果。 WM_ACTIVATEが送られてくるので、これをフックしてみたのですが、spy++だとバックグラウンドに行った時、フォアグラウンドに行った時、最小化したとき、最小化から復帰したときにWM_ACTIVATEが送られてくるんですが、いざフックしてみると最小化するときと最小化から復帰したときにしかフックが作動しません。 spy++ではWM_SETFOCUSも送られてくるようだったので、そちらも試してみたのですが、まったく反応がありません。 逆に、spy++では検知してくれないWM_SHOWWINDOWではバックグラウンドに行った時、フォアグラウンドに行った時、最小化したとき、最小化から復帰したとき、すべてに反応してくれました。 このWM_SHOWWINDOWをフックしたときのようになれば問題無いのですが、フック対象をメモ帳からとあるゲームにしたときに、バックグラウンドに行った時と最小化したときは反応してくれたものの、フォアグラウンドに行った時と最小化から復帰したときは反応してくれません。 それと、WM_SHOWWINDOWのメッセージをフックした時のwparamの値なんですが、ネットで調べてみると 表示されようとしているとき 1 非表示されようとしているとき 0 となっているはずなのですが、自分のをみてみると常に647で固定されています。 どなたか解決策をご教授お願いします。 LRESULT CALLBACK WndProc(int nCode, WPARAM wParam, LPARAM lParam) { if (nCode < 0) { return CallNextHookEx(hHook, nCode, wParam, lParam); } else if (nCode == HC_ACTION) { MSG *lmsg; lmsg = (MSG *)lParam; switch (lmsg->message){ case WM_SHOWWINDOW: MessageBox(NULL,"showwindow","info",MB_OK | MB_TOPMOST); return CallNextHookEx(hHook, nCode, wParam, lParam); break; } } return CallNextHookEx(hHook, nCode, wParam, lParam); }

  • キィーボードをフックしません、何故ですか???

    パソコンを現在人間が実際に操作中であるか否かを判定しながら進めるアプリを作っています 簡易的にキィーボードを操作していれば操作中と判断します(マウス操作も含めますが話を簡単にするため今はキィーだけとします) グローバルフックでKEY_DOWNをフックする為に以下のDLL(主要部分のみ)を作りました キィーが押されるとMW_KEYDOWN_DLLというメッセージをアプリに送ります EXPORT LRESULT CALLBACK HookProc( int nCode, WPARAM wParam, LPARAM lParam) { if(nCode == HC_ACTION) { CWPSTRUCT *pcwp = (CWPSTRUCT *)lParam; if(pcwp->message == WM_KEYDOWN) { SendMessage(g_hWnd, WM_KEYDOWN_DLL, pcwp->wParam, pcwp->lParam); ←(1) } } return (CallNextHookEx(g_hHook, nCode, wParam, lParam)); } MW_KEYDOWN_DLLメッセージを受けたアプリは操作中フラグを立てます(主要部分のみ) LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch(uMsg) { case WM_KEYDOWN_DLL: ここで操作中フラグを立てます ←(2)  このフラグは一定時間後にタイマーが倒します break; default: return DefWindowProc(hWnd, uMsg, wParam, lParam); } return (0L); } 実行してみると(1)に来ません、当然(2)のフラグは立ちません WM_KEYDOWNの代わりにWM_CREATE、WM_CLOSEだときちんとフックします WM_CHAR、MW_KEYUPなどのキィーボード系のメッセージだとフックしません なぜでしょうか??? 多分きわめて初歩的な知識の欠如によるものでしょうが分かりません 宜しくご指導願います

  • VC2005で作成したDLLファイルをVC2008で動的リンク(LoadLibrary)する方法

    「VC2005 Standard Edition」で作成したDLLファイルを、 「VC2008 Express Edition」で作成したコンソールアプリケーション から、LoadLibrary("VC2005で作成したDLLファイル")すると 失敗してしまいます。 GetLastErrorでエラーを取得すると、"36B1"が表示されます。 (このエラーは何か調べても見つかりませんでした) 何が原因かご存知の方がいらっしゃいましたら、 ご教授頂けませんでしょうか。

  • Win32 APIを使ったWindowsプログラミング製作について質問です

    只今、VisualStudio2005のVC++でWin32 APIを使ってWindowsアプリケーション製作の練習をしています。今、ドラゴンクエストIのようなゲームを作りたいと思っており、画面に画像を表示し、キーボードの十字キーで操作できるようにしていますが、ここまでやっていて一つ不思議に思ったことがあります。それは、画像の読み込みや表示・キーボードの入力などすべてをウィンドウプロシージャ内にコーディングしています。WinMain()関数内には、ウィンドウの登録・生成・表示という当たり前の処理しかありません。これから、戦闘の処理なども加えていきますが、それを考えてもWM_PAINTやWM_KEYDOWNなどのメッセージ内で事足りるような気がします。アプリの製作の経験はほとんどない初心者なので、C言語みたいにMain()関数内にほとんど処理を記述しないのが不安に思います。自分の書き方は間違っているのかどうなのか、何か参考になる意見をいただけないでしょうか?どうかよろしくお願い致します。

  • VB6のメッセージフックについて

    VB6SP6、XPの環境で SDI形式のアプリケーションを組んでいます。 MainのフォームがFormLoad()で SetWindowLong()その後、VC++のDLLを起動 そのDLLからWM_USER+XXXが送信されてきます。 標準basでWndProcを書いて SDIのMainフォームのTextを更新するように 設計しているのですが WndProc内にText1.Text="ABC"とコーディングすると Mainのフォームが新たに起動されてしまいます。 WndProc() if msg = WM_USER+XXX Text1.text = "ABC"<<<ここでText1があるMainFrmが新たに起動 end if 此れを防ぐにはどうすればよいでしょうか SDIでなければ(標準EXE)、ならないようなのですが

  • マウスホイールをフックしたい

    かなり突っ込んだ質問かもしれませんが Win32API系の質問です。 マウスホイールをフックするコードを書いています。 フックはDLLが必要なグローバルフックではなく スレッドローカルなフックです。 具体的には 1.SetWindowsHookEx APIでWH_MOUSEタイプをフック 2.MouseProcフックプロシジャーでWM_MOUSEWHELLメッセージはフックできている。 ここまでは良いのですが ホイールの回転方向がわかりません。 MouseProcフックプロシジャーのlParamを MOUSEHOOKSTRUCT構造体へキャストしても dwExtraInfo追加情報には何も入っておらず (オールゼロでした。) 行き詰っています。 試しにフック後に PeekMessageも試みましたがダメでした。 諸事情でグローバルフックは使いたくなくて スレッドローカルなフックで解決したいのですが 良い方法は無いでしょうか? 試しにフックタイプを WH_CALLWNDPROC WH_GETMESSAGE とこれらも試してみましたがNGでした。 なお、WH_JOURNALRECORDフックは ユーザの操作でキャンセルされてしまうので あまり使いたくありません。 経験者の方、アドバイス頂けると助かります。 宜しく御願いします。

  • [c++]#using "user32.dll"でエラー

    VC++ 2008 Express Editionを使用しています。 ソースコード上に#using "user32.dll"を記述したところ 「 fatal error C1113: #using が 'c:\windows\servicepackfiles\i386\user32.dll' で失敗しました。」というエラーが出てしまいコンパイルできません。#using <mscorlib.dll>を記述した場合はコンパイルできます。 どうしたら#using "user32.dll"を使えるようになりますか?なおuser32.dllはちゃんと存在します。

  • Excel VBAでスクリーンキーボードを起動

    Windows XP ホームエディション,Excel2010で作成したファイルでスクリーンキーボードを次のShell関数にて起動させていましたが、この度Windows7 プロフェッショナルに変えたところ「プロシージャーの呼び出し、または引数が不正です」とのことで立ち上がらなくなりました。pathnameを調べましたがWindows XP ホームエディションとWindows7ロフェッショナルは同じでした。 Sub スクリーンキーボードの表示() Shell "C:\Windows\System32\osk.exe", 1 End Sub 本やネットで解決策を調べてみましたが分かりません。どなたかお教えいただけないでしょうか。 よろしくお願いします。

  • キーボードが反応しません

    すみませんが質問させてください。 Microsoft製のキーボード(Model:RT2300)を使用しているのですが、あるキーを押しながら数字キーを入力した場合に、一切反応がありません。 例えば、十字キーの↑と→を押しながら数字を入力しようとすると、1、3、4、6、9、0が反応してくれない状態です。 2、5、7、8は普通に打つことができます。 ↓や←などは問題ないのですが、上記2つのキーを同時押し状態で、これらの数字キーの反応がなくなります。 通常の文書作成以外にも、いろいろとキーボードを使うので、少々困っています。 どなたか原因がわかれば、お答えいただけると助かります。