スポンサーリンク

グローバルフック マウスフック

グローバルフックをするには、DLLにする必要がある。

また、イベントがあったことを知るために、FindWindowで送信先のウィンドウクラス名を指定してSendMessageしている。

マウスフックの時は、SetWindowsHookExに渡す引数はWH_MOUSEとなる。また、フックプロシージャのwParamにはイベントが入っている。

 

DLL側

dllmain.h

#pragma once
#include <Windows.h>
BOOL APIENTRY DllMain(HMODULE hModule,
  DWORD  ul_reason_for_call,
  LPVOID lpReserved
);
HINSTANCE GetDllInstance();

dllmain.cpp

HINSTANCE hDLLInstance = nullptr;
BOOL APIENTRY DllMain(HMODULE hModule,
  DWORD  ul_reason_for_call,
  LPVOID lpReserved
)
{
  hDLLInstance = hModule;

  return TRUE;
}
HINSTANCE GetDllInstance() {
  return hDLLInstance;
}

フックをかけるときにインスタンスハンドルが必要になるので、DllMainの中で保存しておく。

 

DLLDefs.h

DLL側にはプリプロセッサにDLL_EXPORT_DOをセットする。

#ifdef  DLL_EXPORT_DO
/*  DLLを作る場合   */
#define  __DLL_PORT  extern "C" __declspec(dllexport)
#define  __DLL_PORT_CLS __declspec(dllexport)
#else
/*  DLLを使う場合   */
#define  __DLL_PORT  extern "C" __declspec(dllimport)   
#define  __DLL_PORT_CLS __declspec(dllimport)
#endif

このファイルは次のMouseHook.hでincludeされるが、結果的にexe側でもincludeされることになるので、両方のプロジェクトから読める必要がある。

 

 

MouseHook.h

#pragma once
#include <Windows.h>
#include "../DLLDefs.h"

//マウスがクリックされたら、本体のプログラムへこのメッセージを送信する
constexpr UINT WM_HOOKED_MOUSEDOWN = WM_USER + 2;

class __DLL_PORT_CLS CMouseHook {
  static HHOOK hHook;
  static LRESULT CALLBACK MouseProcedure(int p_nCode, WPARAM p_wParam, LPARAM p_lParam);
public:
  BOOL Set();
  BOOL Unset();
  ~CMouseHook();
};

フック関数とフックハンドルはstaticにする。

 

MouseHook.cpp

#include "MouseHook.h"
#include "dllmain.h"
#include <tchar.h>

#pragma warning(disable:4996)
#pragma data_seg( ".CMouseHookHandle" )
HHOOK CMouseHook::hHook = nullptr;
#pragma data_seg()

BOOL CMouseHook::Set() {//フックをセットする関数
  hHook = ::SetWindowsHookEx(WH_MOUSE //種類はマウスフック
    , (HOOKPROC)CMouseHook::MouseProcedure
    , GetDllInstance(), 0);//このDLLのインスタンスハンドルを指定

  if (!hHook)
    return FALSE;

  return TRUE;
}

BOOL CMouseHook::Unset() {//フックを外す
  BOOL ret = FALSE;

  if (hHook)
    ret = ::UnhookWindowsHookEx(hHook);

  hHook = nullptr;
  return ret;
}

//フックの処理
LRESULT CALLBACK CMouseHook::MouseProcedure(int p_nCode, WPARAM p_wParam, LPARAM p_lParam) {
  if (p_nCode < 0)
    return ::CallNextHookEx(hHook, p_nCode, p_wParam, p_lParam);

  if (p_nCode == HC_ACTION) {

    MOUSEHOOKSTRUCT *pmh = (MOUSEHOOKSTRUCT *)p_lParam;

    if (pmh) {
      if (p_wParam == WM_LBUTTONDOWN || p_wParam == WM_NCLBUTTONDOWN) {
                                  //このNU_WND_CLASS_NAMEは、exe側で作成するウィンドウのウィンドウクラス名
        PostMessage(FindWindow(_T("NU_WND_CLASS_NAME"), nullptr), WM_HOOKED_MOUSEDOWN, p_wParam, p_lParam);
                                                                   //exe側にWM_HOOKED_MOUSEDOWNを送る
      }
    }
  }
  return ::CallNextHookEx(hHook, p_nCode, p_wParam, p_lParam);;
}
CMouseHook::~CMouseHook() {
  Unset();
}

 

MouseHook.def

SECTIONS
 .CMouseHookHandle	READ WRITE SHARED

 

exe側

#pragma comment(lib, "MouseHook.lib")
#include "../MouseHook/MouseHook.h"
#include<windows.h>
#include <tchar.h>
//ウィンドウプロシージャ
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) {
  switch (msg) {
  case WM_DESTROY:
    DestroyWindow(hwnd);
    PostQuitMessage(0);
    return 0;
  case WM_HOOKED_MOUSEDOWN:
    OutputDebugString(_T("どこかの窓でマウスがクリックされました\n"));
    return 0;
  }
  return DefWindowProc(hwnd, msg, wp, lp);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
  PSTR lpCmdLine, int nCmdShow) {
  HWND hwnd;
  MSG msg;
  WNDCLASS winc;

  //ウィンドウクラスの登録
  winc.style = CS_HREDRAW | CS_VREDRAW;
  winc.lpfnWndProc = WndProc;
  winc.cbClsExtra = winc.cbWndExtra = 0;
  winc.hInstance = hInstance;
  winc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  winc.hCursor = LoadCursor(NULL, IDC_ARROW);
  winc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
  winc.lpszMenuName = NULL;
  winc.lpszClassName = TEXT("NU_WND_CLASS_NAME");

  if (!RegisterClass(&winc)) return 0;


  //フックをかける
  CMouseHook hm;
  hm.Set();

  //ウィンドウ作成
  hwnd = CreateWindow(
    TEXT("NU_WND_CLASS_NAME"), TEXT("test"),
    WS_OVERLAPPEDWINDOW | WS_VISIBLE,
    100, 100, 200, 200, NULL, NULL,
    hInstance, NULL
  );

  if (hwnd == NULL) return 0;

  while (GetMessage(&msg, NULL, 0, 0)) DispatchMessage(&msg);

  //フックを外す
  hm.Unset();

  return msg.wParam;
}

 

 

コメントを残す

メールアドレスが公開されることはありません。

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)


この記事のトラックバックURL: