WM_PAINT などのメッセージを送らないようにするには,メッセージフックを使用する.
WH_CALLWNDPROC でフックして,スレッド ID に 0 を指定して全てのメッセージを監視とする.ダミーのウィンドウプロシージャを DLL で用意しておき,メッセージを送信したくないときに SetWindowLong() でウィンドウプロシージャを挿げ替える.
(そしてすぐにもとのプロシージャに戻す)
(この方法は,フックに渡されるウィンドウハンドルと実際にメッセージを受け取るウィンドウが同じ場合に有効である.WH_GETMESSAGE は必ずしもウィンドウハンドルと同じウィンドウにメッセージが送られるわけではない)
SetWindowsHookEx() で第4パラメータの dwThreadId に 0 を設定して,DLL のデータセグメントを共有すれば全てのメッセージをフック可能である.
#pragma data_seg(".GLOBALS")
HHOOK hHook=0
#pragma data_seg()
DLL の DEF ファイル
SECTIONS
.GLOBALS READ WRITE SHARED
あとはリンクの設定に
/SECTION:.GLOBALS,RWS
を追加する.
メッセージフックサンプル
/* ユーザー定義メッセージ */
#define WM_USERMESSAGE_CALLWND (WM_USER + 50)
extern HINSTANCE _hInstance;
/* フックプロシージャで使用する変数は共有メモリにおく */
/* これは Visual C++ の場合 */
/* リンカのオプションに /SECTION:.share,RWS を追加 */
#pragma data_seg(".share")
HHOOK _hHookCallWnd = NULL;
HWND _hWndCallWnd = NULL;
#pragma data_seg()
/* フック プロシージャ */
static LRESULT CALLBACK CallWndProc(int nCode, WPARAM wParam, LPARAM lParam)
{
CWPSTRUCT* pCWP;
if( nCode >= 0 && nCode == HC_ACTION ) {
pCWP = (CWPSTRUCT*)lParam;
if( pCWP->message == WM_PAINT ) {
PostMessage(_hWndCallWnd, WM_USERMESSAGE_CALLWND, wParam, lParam);
}
return CallNextHookEx(_hHookCallWnd, nCode, wParam, lParam);
}
return CallNextHookEx(_hHookCallWnd, nCode, wParam, lParam);
}
/* フックのセット */
/* ここで渡したウィンドウに */
/* メッセージ WM_USERMESSAGE_CALLWND が送られる */
BOOL SetCallWnd(HWND hWnd)
{
/* キーのフック */
_hHookCallWnd = SetWindowsHookEx(WH_CALLWNDPROC, (HOOKPROC)CallWndProc, _hInstance, 0);
/* ここで hInstance は DLL のインスタンス ハンドル */
_hWndCallWnd = hWnd;
return (_hHookCallWnd != NULL);
}
/* アンフック */
/* フックが不必要になったら呼ぶ */
void ResetCallWnd()
{
if(_hHookCallWnd != NULL ) {
UnhookWindowsHookEx(_hHookCallWnd);
_hHookCallWnd = NULL;
}
}
参照
マウスのフック