4

事前にプログラムされたプロセスを強制終了したり、何かを起動したりできるように、ユーティリティ キーストローク アプリを作成しようとしています。どのアプリでもcmdを押したままにしてから、4桁のコマンドキーを入力して、プログラミング中、ビデオの視聴中などのデバッグ中に何かをすばやく起動または強制終了できるようにする必要があると考えています.

キーボードのコールバックを取得する方法を見つけましたが、何らかの理由で別のアプリをクリックすると、キーストローク util がそれ以上キーを受け取りません。クリックしてコンソール ウィンドウまたは msvc に戻っても、何も入力されません。これはグローバルでない限り、フックをグローバルに設定するにはどうすればよいですか?

私のコードは

int main()
{
    hook = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, GetModuleHandle(0), 0);
    MSG msg;
    while(GetMessage(&msg, NULL, 0, 0) > 0)
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    UnhookWindowsHookEx(hook);
}
4

5 に答える 5

15

キーボードフックにすべてのプロセスからアクセスできるようにするには、DLLに配置してから、各プロセスのアドレス空間にロードする必要があります。覚えておくべき重要なことの1つは、DLLの各インスタンスが別々のプロセスでロードされるため、それぞれがDLL内のグローバル変数の独自のコピーを持つことです。これらのインスタンス間でデータを共有する必要がある場合、最も簡単な方法は、DLLに共有データセグメントを作成することです。次のコードは、私が作成したRSI監視プログラムからのものです。

//
// some data will be shared across all
// instances of the DLL
//
#pragma comment(linker, "/SECTION:.SHARED,RWS")
#pragma data_seg(".SHARED")
int iKeyCount = 0;
HHOOK hKeyboardHook = 0;
HHOOK hMouseHook = 0;
#pragma data_seg()

//
// instance specific data
//
HMODULE hInstance = 0;

//
// DLL load/unload entry point
//
BOOL APIENTRY DllMain(HANDLE hModule, 
                      DWORD  dwReason, 
                      LPVOID lpReserved)
{
   switch (dwReason)
   {
   case DLL_PROCESS_ATTACH :
      hInstance = (HINSTANCE) hModule;
      break;

   case DLL_THREAD_ATTACH :
      break;

   case DLL_THREAD_DETACH :
      break;

   case DLL_PROCESS_DETACH :
      break;
   }
   return TRUE;
}

//
// keyboard hook
//
LRESULT CALLBACK KeyboardProc(int code,       // hook code
                              WPARAM wParam,  // virtual-key code
                              LPARAM lParam)  // keystroke-message information
{
   if ((lParam & 0x80000000) != 0)
   {
      ++iKeyCount;
   }
   return CallNextHookEx(hKeyboardHook, code, wParam, lParam);
}

//
// mouse hook
//
LRESULT CALLBACK MouseProc(int code,       // hook code
                           WPARAM wParam,  // message identifier
                           LPARAM lParam)  // mouse coordinates
{
   switch (wParam)
   {
   case WM_LBUTTONDOWN :
   case WM_MBUTTONDOWN :
   case WM_RBUTTONDOWN :
   case WM_LBUTTONDBLCLK :
   case WM_MBUTTONDBLCLK :
   case WM_RBUTTONDBLCLK :
      ++iKeyCount;
      break;
   }
   return CallNextHookEx(hMouseHook, code, wParam, lParam);
}

//
// install keyboard/mouse hooks
//
void KBM_API InstallHooks(void)
{
   hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, hInstance, 0);
   hMouseHook = SetWindowsHookEx(WH_MOUSE, MouseProc, hInstance, 0);
}

//
// remove keyboard/mouse hooks
//
void KBM_API RemoveHooks(void)
{
   UnhookWindowsHookEx(hKeyboardHook);
   UnhookWindowsHookEx(hMouseHook);
   hKeyboardHook = hMouseHook = 0;
}

//
// retrieve number of keystrokes
//
int KBM_API FetchKeyCount(bool bClear)
{
   int kc = iKeyCount;
   if (bClear)
      iKeyCount = 0;
   return kc;
}
于 2009-01-18T02:09:57.103 に答える
5

コードプロジェクトのサンプルは避けてください。(多数のバグ、MSDN の不良コピー)

MSDN on hooks (MSDN、SDK、KB など) で多数の完全なサンプルを参照してください。

DLL は必要ありません。LL フックを使用するだけです。

于 2009-01-18T11:40:01.053 に答える
0

Win32ガイドのフックの概要を読み直してください。(開始するのに適した場所はここです。)

具体的には、他のプロセスでイベントをフックする場合は、コールバックをDLLに配置する必要があります。これは、Win32によって他のプロセスに挿入されます。あなたが提供したコードから、KeyboardProcがDLLにあるのかメインプログラムにあるのかわかりません。あなたが通過しているHINSTANCEを考えると、それはそれのようには見えません。

于 2009-01-18T02:03:01.797 に答える
0

「PictureinPicture」のようなアプリを書いているときに、グローバルフックをいじらなければなりませんでした。この記事とサンプルコードは私を大いに助けてくれました:

http://www.codeproject.com/KB/system/WilsonSystemGlobalHooks.aspx

于 2009-01-18T02:03:50.593 に答える