I have created a hook for mouse. I wanted to get mouse click coordinates, but the GET_X_LPARAM() gives me negative value (and always the same when clicking on different places). My problem becomes solved with GetCursorPos(), but I wonder why it is not working with GET_X_LPARAM/GET_Y_LPARAM. Here's the code:
LRESULT CALLBACK Recorder::mouseHook( int code, WPARAM wParam, LPARAM lParam ) {
if( code < 0 )
return CallNextHookEx( m_mouseHook, code, wParam, lParam );
switch( wParam ) {
case WM_LBUTTONDOWN:{
int _hereIsANegativeNumber = GET_X_LPARAM( lParam );
break;}
}
return CallNextHookEx( 0, code, wParam, lParam );
}
This is how I set the hook:
m_mouseHook = SetWindowsHookEx( WH_MOUSE_LL, &mouseHook, GetModuleHandle( NULL ), 0 );
In a WH_MOUSE_LL hook, lParam is not the mouse coordinates - instead it is a pointer to a MSLLHOOKSTRUCT.
So, to get coordinates:
POINT pt = reinterpret_cast<MSLLHOOKSTRUCT*>(lParam)->pt;
See LowLevelMouseProc for more details.
Because for the WH_MOUSE_LL in the LowLevelMouseProc procedure what you get as the LPARAM variable is a pointer to a MSLLHOOKSTRUCT structure and use the pt member of it for getting the mouse coordinates
Related
I'm trying to write a dll to intercept a window from being resized, but i cant understand how to correctly specify the lParam in this case.
From the docs:
HCBT_MOVESIZE: Specifies a long pointer to a RECT structure containing
the coordinates of the window. By changing the values in the
structure, a CBTProc hook procedure can set the final coordinates of
the window.
Current code:
#include "pch.h"
#include <Windows.h>
extern "C" __declspec(dllexport) LRESULT CALLBACK CBTProc(
_In_ int nCode,
_In_ WPARAM wParam,
_In_ LPARAM lParam
)
{
if (nCode < 0) return CallNextHookEx(nullptr, nCode, wParam, lParam);
switch(nCode)
{
case HCBT_MOVESIZE: // A window is about to be moved or sized.
/*
For operations corresponding to the following CBT hook codes, the return value must be 0 to allow the operation, or 1 to prevent it.
HCBT_ACTIVATE
HCBT_CREATEWND
HCBT_DESTROYWND
HCBT_MINMAX
HCBT_MOVESIZE
HCBT_SETFOCUS
HCBT_SYSCOMMAND
*/
/*
switch(LOWORD(lParam)) //
{
case EVENT_SYSTEM_MOVESIZESTART:
return 1; // Prevent
}
*/
}
return 0;
}
In the case of HCBT_MOVESIZE, the lParam contains the memory address of a RECT, so simply typecast the lParam to a RECT* pointer, eg:
extern "C" __declspec(dllexport) LRESULT CALLBACK CBTProc(
_In_ int nCode,
_In_ WPARAM wParam,
_In_ LPARAM lParam
)
{
if (nCode < 0) return CallNextHookEx(nullptr, nCode, wParam, lParam);
switch(nCode)
{
case HCBT_MOVESIZE: // A window is about to be moved or sized.
{
HWND hwnd = reinterpret_cast<HWND>(wParam);
RECT *rc = reinterpret_cast<RECT*>(lParam);
// use hwnd and *rc as needed...
if (should not resize)
return 1;
break;
}
...
}
return 0;
}
LPARAM is a pointer-sized value. It can hold any value that fits into a pointer. The meaning of the value commonly depends on context.
When handling a HCBT_MOVESIZE callback it designates
a long pointer to a RECT structure
To use it, client code needs to convert the value into a value of the respective type. In C++ this is done using a cast, e.g.
switch(nCode)
{
case HCBT_MOVESIZE: {
auto pRect{ reinterpret_cast<RECT*>(lParam) };
// Use `pRect` to read from or write to the rectangle
}
break;
// ...
}
I need to somehow set the cursor to the "Select Precision" pointer (the horizontal and vertical cross-over) for a C++ application.
Does anyone know how this would be integrated using the WinApi protocol?
Somewhere in initialization code:
HCURSOR precision_cursor = LoadCursor( NULL, IDC_CROSS );
And window procedure:
LRESULT CALLBACK YourWindowProc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam )
{
switch ( msg )
{
case WM_SETCURSOR:
// If you omit test below, you will change cursor also for scrollbars, frames, etc.
if ( LOWORD( lparam ) == HTCLIENT )
{
SetCursor( precision_cursor );
return TRUE;
}
break;
}
// This will also handle cursor for scrollbars and frames.
return DefWindowProc( hwnd, msg, wparam, lparam );
}
I'm trying to create a hook to a keyboard event but the hook is never called on a key stroke. I set the hook with:
HHOOK hookRes = SetWindowsHookEx( WH_KEYBOARD, &KeyStrokeHook, NULL, GetCurrentThreadId() );
And the callback function is:
LRESULT CALLBACK KeyStrokeHook( _In_ int code, _In_ WPARAM wParam, _In_ LPARAM lParam )
{
if( code < 0 )
return CallNextHookEx( NULL, code, wParam, lParam );
if( lParam & 0x80000000 == 0 ) // If key pressed, not released
{
keyStroke = wParam;
SetEvent( keyEvent );
}
return CallNextHookEx( NULL, code, wParam, lParam );
}
hookRes has a valid hook, but the hook function is never called.
Can the hook be triggered if the thread that set the hook is currently blocked on a mutex?
When a user clicks on window B the window C becomes visible.
Situation 1 : While window C is visible and user clicks anywhere on window A or B or any other child windows of window A, window C becomes invisible.
Situation 2 : While window C is visible and user clicks on window C then program does few things and makes window C invisible. [window C has more child windows]
How do I achieve this functionality ?
The SetCapture won't work for Situation 2.
In the window B this is what I got, it works for Situation 1, but obviously not for Situation 2.
LRESULT WindowB::LButtonDown ( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )
{
if ( !capture )
{
::SetCapture ( hwnd );
capture = true;
windowC->show ( );
}
else
{
::ReleaseCapture ( );
capture = false;
windowC->hide ( );
}
return 0;
};
P.S : I am using pure winapi with oop c++, and my own wrapper for windows and message handling.
EDIT: More code added as requested.
LRESULT WindowC::lButton ( UINT message, WPARAM wParam, LPARAM lParam )
{
doStuff ( );
::PostMessage ( hParent, WM_COMMAND, WPARAM ( BN_CLICKED ), LPARAM ( hwnd ) );
return 0;
};
This might be a dumb question, but can you register multiple WndProc functions in Win32? e.g. a framework catches some messages and my app is interested in other ones - how do I catch them without modifying the framework code?
If I understand your intention correctly, you can do that by setting a hook. Assuming you know the thread whose message loop you'd like to hook, you can do something along these lines (unchecked):
SetWindowsHookEx(WH_CALLWNDPROC, yourHOOKPROC, NULL, theThreadId);
You can chain multiple message handling functions by using the function CallWindowProc instead of DefWindowProc.
Here is an example:
pfOriginalProc = SetWindowLong( hwnd, GWL_WNDPROC, (long) wndproc1 ); // First WNDPROC
pfOriginalProc2 = SetWindowLong( hwnd, GWL_WNDPROC, (long) wndproc2); // Second WNDPROC, WILL EXECUTE FIRST!!
LRESULT wndproc1( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
switch ( uMsg )
{
...
default:
return CallWindowProc( pfOriginalProc, hwnd, uMsg, wParam, lParam );
}
}
LRESULT wndproc2( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
switch ( uMsg )
{
...
default:
return CallWindowProc( pfOriginalProc2, hwnd, uMsg, wParam, lParam );
}
}