I'm currently hooking window activations with the following code:
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);
HWND hwnd = reinterpret_cast<HWND>(wParam);
switch (nCode)
{
case HCBT_ACTIVATE: // The system is about to activate a window.
{
return 0; // 0 - Allow 1 - Deny
}
}
return 0;
From the docs:
https://learn.microsoft.com/en-us/previous-versions/windows/desktop/legacy/ms644977(v=vs.85)
lParam
Specifies a long pointer to a CBTACTIVATESTRUCT structure containing the handle to the active window and specifies whether the activation is changing because of a mouse click.
How I could interpret the value of lParam and distinguish it?
As the documentation says, for HCBT_ACTIVATE the lParam specifies a pointer to a CBTACTIVATESTRUCT, so simply typecast it accordingly, just like you are doing with the wParam, 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_ACTIVATE: // The system is about to activate a window.
{
HWND hwnd = reinterpret_cast<HWND>(wParam);
CBTACTIVATESTRUCT* cbt = reinterpret_cast<CBTACTIVATESTRUCT*>(lParam);
// use hwnd, cbt->fMouse, and cbt->hWndActive as needed...
return 0; // 0 - Allow 1 - Deny
}
}
return 0;
}
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 apologize if I'm overlooking something, but I'm trying to just create a placeholder window within an ATL dialog, which will be used to host a preview handler. I thought placing a custom control might be the thing to do, since it's blank and would occupy a designated place, but that's causing the dialog to crash, and I get the feeling doing something with a custom control is more complicated than I'm looking for. So is there a way to just put a dummy window inside a dialog for use as a host site? Thanks for any input.
Update: I seem to have achieved the desired result using a simple blank picture control. But I'm still wondering if there's a more official way of doing this.
for placeholder we need use exactly custom control. the point - need specify window class name. and this class must be registered.
let name of class will be MyClass
so in .rc file must be
CONTROL "Custom1",IDC_CUSTOM1,"MyClass",...
and we need register "MyClass", minimal code
class MyWndCls
{
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_NCDESTROY:
delete this;
break;
}
return DefWindowProcW(hwnd, uMsg, wParam, lParam);
}
static LRESULT CALLBACK _WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
return reinterpret_cast<MyWndCls*>(GetWindowLongPtrW(hwnd, GWLP_USERDATA))->WindowProc(hwnd, uMsg, wParam, lParam);
}
static LRESULT CALLBACK StartWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
if (uMsg == WM_NCCREATE)
{
if (MyWndCls* p = new MyWndCls)
{
SetWindowLongPtrW(hwnd, GWLP_USERDATA, (LONG_PTR)p);
SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (LONG_PTR)_WindowProc);
return p->WindowProc(hwnd, uMsg, wParam, lParam);
}
return 0;
}
return DefWindowProcW(hwnd, uMsg, wParam, lParam);
}
inline static const WCHAR clsname[] = L"MyClass";
public:
static ULONG Register()
{
WNDCLASS wndcls = {
0, StartWindowProc, 0, 0, (HINSTANCE)&__ImageBase, 0,
LoadCursorW(0, IDC_HAND), (HBRUSH)(COLOR_INFOBK + 1), 0, clsname
};
return RegisterClassW(&wndcls) ? NOERROR : GetLastError();
}
static ULONG Unregister()
{
return UnregisterClassW(clsname, (HINSTANCE)&__ImageBase) ? NOERROR : GetLastError();
}
};
of course we need call MyWndCls::Register(); before create any dialog with this custom control
Anyone know how to call non-static member from WndProc?
Here is my WndProc prototype:
LRESULT CALLBACK System::Windows::Forms::Control::WndProc(HWND hWnd,
UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
this->OnCreate(new EventArgs(hWnd, message, wParam, lParam));
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
break;
}
return 0;
}
And defination:
class LIBMANAGED_API Control
{
protected:
HWND hWnd;
static LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
...
};
This is wrong on so many levels. What do you really want to achieve? Just from this piece of code, there's not enough info.
First, you declare this method using a mixture of C and managed C++. It either
protected virtual void WndProc(Message m) // Managed C++
as you see, NOT static method, LRESULT, HWND and so on, or
LRESULT CALLBACK WindowProc(
_In_ HWND hwnd,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
);
as you can see, no System namespace.
Second, where are your clases defined? I suspect you should override your method, using Managed C++, see MSDN.
You were not that far as you are already processing the WM_CREATE message.
The trick is to pass an object pointer at creation time and store it in the Window itself with SetWindowLongPtr in the WM_CREATE or WM_NCCREATE message. The you can extract it with GetWindowLongPtr and access your object from the window procedure.
Window creation (say MyWnd myWnd is the C++ object that will represent the window):
HWND hWnd = CreateWindow( m_pszClassName, "Name", WS_VISIBLE | WS_OVERLAPPED,
x, y, w, h, NULL, NULL, hInst, &myWnd);
Window procedure:
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
MyWnd *myWnd;
myWnd = (MyWnd *) GetWindowLongPtr(hWnd, GWLP_USERDATA); /* to use it outside WM_CREATE */
switch (message)
{
case WM_CREATE:
CREATESTRUCT * pcs = (CREATESTRUCT*)lParam;
MyWnd* myWnd= (MyWnd*) pcs->lpCreateParams;
SetWindowLongPtr( hwnd, GWLP_USERDATA, (LONG_PTR) myWnd);
myWnd->OnCreate(new EventArgs(hWnd, message, wParam, lParam));
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
break;
}
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 );
}
}
I'm trying to send a duplicate message to an editbox window in this code:
extern "C" HOOK_DLL_API LRESULT CALLBACK GetMsgHookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode < 0)
{
CallNextHookEx(gMsgHook, nCode, wParam, lParam);
}
KBDLLHOOKSTRUCT *lpk = (KBDLLHOOKSTRUCT*) lParam;
ghServerWnd; // ghServerWnd == Edit1. that defined..
if (wParam == WM_KEYDOWN)
{
// case1: this code working.. but, unicode(IME character) no sent;;
SendMessageW(ghServerWnd, WM_CHAR, (WPARAM)lpk->vkCode, 0);
// case2: this code - not working.. T_T
SendMessageW(ghServerWnd, wParam, lParam, 0);
}
return CallNextHookEx(gMsgHook, nCode, wParam, lParam);
}
I need help with "case2" as marked in the code.
Thanks for reading.
Well i'm not surprised case 2 does not work. You are sending KBDLLHOOKSTRUCT as the wParam.
I would have thought.
SendMessage( ghServerWnd, wParam, (WPARAM)lpk->vkCode, (LPARAM)lpk->scanCode );
Would work better (Though I'm not 100% convinced my LPARAM is complete).