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 );
}
}
Related
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;
}
I would like to hide a caret from a RichEdit(50W) with ES_READONLY style specified.
It's pretty confusing for the user, when the caret is blinking and the user can't type.
I tried to hide the caret using HideCaret() function,
however it doesn't work for me with following code:
LRESULT CALLBACK ChatMessaegsSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) // Subclassed control
{
LRESULT ret = CallWindowProc(WndProc_ChatMessages, hwnd, msg, wParam, lParam);
switch(msg)
{
//Also tried with EN_SETFOCUS
case WM_SETFOCUS:
{
ret = CallWindowProc(WndProc_ChatMessages, hwnd, msg, wParam, lParam);
HideCaret(ChatMessages); //Returns 5 (Access denied.)
break;
}
//According the documentation:
//If your application calls HideCaret five times in a row,
//it must also call ShowCaret five times before the caret is displayed.
case WM_KILLFOCUS: //The message is called when the RichEdit get focus, however nothing happens.
{
ret = CallWindowProc(WndProc_ChatMessages, hwnd, msg, wParam, lParam);
ShowCaret(ChatMessages);
break;
}
}
return ret;
}
Here is the solution:
LRESULT CALLBACK ChatMessaegsSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
LRESULT ret = CallWindowProc(WndProc_ChatMessages, hwnd, msg, wParam, lParam);
switch(msg)
{
case WM_LBUTTONDOWN:
{
HideCaret(ChatMessages);
break;
}
case WM_KILLFOCUS:
{
ShowCaret(ChatMessages);
break;
}
}
return ret;
}
NOTE this only works when user induces the focus with mouse. Therefore if anyone knows how to deal with it correctly, feel free to answer, I'll be glad.
I am currently facing issues when trying to compile my code that contains this WinProc function which is being used to process messages from our program. For example if a WM_DESTROY message is received via windows I want it to call PostQuitMessage(0) to signal Windows that the application has made a request to quit. Which will cause the WM_QUIT message to cause the WinMain to exit.
I have only been learning C++ a few weeks and don't have the experience or knowledge to fix this and would appreciate any help. I have looked around but so far I cannot find any solutions. I'm pretty new to this so I may have missed something really obvious.
LRESULT WINAPI WinProc (hWnd, msg, UNIT msg, WPARAM wParam, LPARAM lParam )
{
switch( msg )
{
case WM_DESTROY;
// Tell windows to kill the program
PostQuitMessage(0);
return 0;
}
return DefWindowProc (hWnd, msg, wParam, lParam );
}
Below is the errors I experience wit the code that I have provided.
error: 'LRESULT WinProc' redeclared as different kind of symbol
error: previous declaration of 'LRESULT WinProc(HWND__*, UINT, WPARAM, LPARAM)'
error: 'hWnd' was not declared in this scope
error: 'msg' was not declared in this scope
error: 'UNIT' was not declared in this scope
Any help would be greatly appreciated.
Thanks
In the function declaration
LRESULT WINAPI WinProc (hWnd, msg, UNIT msg, WPARAM wParam, LPARAM lParam )
you forgot to set type specifiers for the first two parameters hWnd and msg
There must be
LRESULT WINAPI WinProc ( HWND hWnd, UNIT msg, WPARAM wParam, LPARAM lParam )
Also the label has to be followed by a colon while you placed a semicolon
case WM_DESTROY;
try using the callback calling convention instead of winapi
https://msdn.microsoft.com/en-us/library/windows/desktop/ms633570(v=vs.85).aspx
also note the usage of " : " instead of " ; " on switch statement , also specify a type before the handle and message arguments
LRESULT CALLBACK WinProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch( msg )
{
case WM_DESTROY:
// Tell windows to kill the program
PostQuitMessage(0);
return 0;
}
return DefWindowProc (hWnd, msg, wParam, lParam );
}
LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM )
This should be the function declaration. Your case has a ";" semicolon instead of a ":" colon.
Besides this, I don't see any problems. Try this:
LRESULT CALLBACK WndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
switch( msg )
{
case WM_DESTROY:
// Tell windows to kill the program
PostQuitMessage(0);
return 0;
}
return DefWindowProc (hWnd, msg, wParam, lParam );
}
I have been having trouble with my program trying to gray out ( and disable ) a sub menu item.
What I'm looking for is that the "run" item be disabled unless the required .ini entry is not empty.
My code
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HMENU hmenu = GetMenu(hWnd);
// Reading in ini
if (0 == strcmp(webLocation, "")){
EnableMenuItem(hmenu,ID_WEBSERVICES_RUN,MF_DISABLED | MF_GRAYED);
WritePrivateProfileString(_T("WEBSERVICES"), _T("Location"), _T("Tool Not Found"), WpathStr);
}
I am unsure as to whether I am getting the HMENU correctly and why this code is not working for the desired effect.
Any help with this would be greatly appreciated.
You can't just put this in the WndProc at the top level. WndProc process events, whether the window has been constructed or not. It'll be called many times for many different reasons.
Your WndProc will almost certainly look like a big switch on message. The one you want here is WM_INITDIALOG:
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_INITDIALOG:
// jump to a new function that reads the .ini
// and disables the control etc.
return OnInitDialog(hWnd, wParam, lParam);
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
}