Basics
Hook (HOOK), is a platform for Windows message handling mechanism, the application can set a hook, to monitor a specified window of some kind of message when the message arrives, deal with it before being processed target window, the window can be monitored other the process of being created.
Specific in-depth knowledge, can refer to this article Windows Hook Hook comprehensive summary
Hook according to the range to intercept the message can be divided into
- Global hook, a message thread will block all the windows
- Thread the hook, it will only block specific thread message
Related interface function introduction:
HHOOK SetWindowsHookEx(
int idHook, //钩子类型,如 WH_MOUSE_LL, WH_MOUSE
HOOKPROC lpfn, //拦截回调函数
HINSTANCE hmod, // dll句柄
DWORD dwThreadId // 线程Id,当为0时表示全局钩子
);
This function is used to install the hook. Global hook to intercept the other thread message, must be triggered by the dll callback function, improper handling causing system crashes, not recommended for novice to use, it is recommended to use the thread hook.
In this demand, we focus on the mouse hook, hook the mouse following two:
- WM_MOUSE: ordinary mouse hook, hook can intercept mouse events where the module.
- WM_MOUSE_LL: low-level mouse hook can intercept mouse events of the entire system.
In the current scenario, we use WM_MOUSE
the hook can be. Note that the WM_MOUSE_LL
hook can only be applied to the global hook type, to monitor the specified thread, the injection stage will be prompted to 1429 error, error information 此挂接程序只可整体设置
.
LRESULT CALLBACK MouseProc(
_In_ int nCode,
_In_ WPARAM wParam,
_In_ LPARAM lParam
);
This function defines the interface mouse hook callback function,
LRESULT CallNextHookEx(
HHOOK hhk,
int nCode,
WPARAM wParam,
LPARAM lParam
);
This function is used to hook a hook information is passed to the next in the chain hook current.
BOOL UnhookWindowsHookEx(
HHOOK hhk
);
This function is used to uninstall the hook.
The overall design
The overall design of this function is as follows:
The key functions of the business logic of two things:
- Registration mouse hook
- Intercepting a message converted message to the roller
Registration mouse hook
Registration WM_MOUSE
mouse hook type enough, note that here, for the official document WM_MOUSE
callback function prototype types of messages are:
LRESULT CALLBACK MouseProc(
_In_ int nCode,
_In_ WPARAM wParam,
_In_ LPARAM lParam
);
Representative mouse wParam message identifier, e.g., WM_MOUSEWHEEL
, WM_MOUSEMOVE
and the like.
Representative lParam pointing mouse callback message type of structure MOUSEHOOKSTRUCT
, the structure declaration is as follows:
typedef struct tagMOUSEHOOKSTRUCT {
POINT pt;
HWND hwnd;
UINT wHitTestCode;
ULONG_PTR dwExtraInfo;
} MOUSEHOOKSTRUCT, *LPMOUSEHOOKSTRUCT, *PMOUSEHOOKSTRUCT;
From the above structure, we are concerned about is pt (based on the current mouse position coordinates of the screen coordinate system), also need to have a mouse wheel to scroll the distance, after some search, I found two places have the parameters:
- Low-level mouse hook (WM_MOUSE_LL) callback function lParam, the type
MSLLHOOKSTRUCT
, the following statement:
typedef struct tagMSLLHOOKSTRUCT {
POINT pt;
DWORD mouseData;
DWORD flags;
DWORD time;
ULONG_PTR dwExtraInfo;
} MSLLHOOKSTRUCT, *LPMSLLHOOKSTRUCT, *PMSLLHOOKSTRUCT;
When intercepted message to the mouse wheel, mouseData
the high-order byte represents the distance the mouse wheel. But low-level hooks need global hooks, not suitable for use.
- Common message callback hook structure extension
MOUSEHOOKSTRUCTEX
, the explanation MSDN:
This is an extension of the MOUSEHOOKSTRUCT structure that includes information
about wheel movement or the use of the X button.
typedef struct tagMOUSEHOOKSTRUCTEX {
DWORD mouseData;
} MOUSEHOOKSTRUCTEX, *LPMOUSEHOOKSTRUCTEX, *PMOUSEHOOKSTRUCTEX;
Obviously, this structure is to expand on the general message structure, the expansion of the mouseData
field, exactly what we need.
Intercepting a message converted message to the roller
According to the above analysis, we need to do now is to convert the message as an ordinary roller wheel hook message.
The document MSDN understood, the wParam roller hook mouse message is a message identifier, such as WM_MOUSE_WHEEL like. lParam roller hook message is converted as follows:
MOUSEHOOKSTRUCTEX const &eventInfo = *(MOUSEHOOKSTRUCTEX*)lParam;
// eventInfo.mouseData <-- 鼠标滚轮距离
// eventInfo.pt <-- 鼠标当前坐标
By GET_WHEEL_DELTA_WPARAM
macro from the mouseData
extraction wheel scrolling distance members, ordinary message roller WM_MOUSEWHEEL
wParam except roller scrolling distance, further comprising a low byte virtual key message. The hook is no message, it also complement the virtual key messages need to use this step GetAsyncKeyState
function.
The final step, is based on the current mouse coordinates, obtain current location window handle, Windows provides WindowFromPoint
functions to achieve this function.
This, based on the hook to achieve a non-active window scroll mouse response function points have all been introduced completed.
demo reference links
Overload message preprocessing implementation
Another way to find online, see the non-active window in response to the mouse wheel
The core idea is to use the current mouse wheel messages received in PreTranslateMessage
interception, the processing directly to the window at the current mouse-over position. This solution is very simple, but the problem may be caused by, the mouse will send a message to a window created by a non-current thread, there may be a problem, need more testing.
summary
Both implementations are given more ideas for your reference.
Experience: In this world, if you do one kind of thing, only one way, it would be too boring.