CreateWindowEx lpParam for button, etc in WM_NCCREATE - winapi

I pass the pointer to the class wrapper instance pointer for controls as lpParam parameter and catch it when receiving WN_NCCREATE.
This message does not get send when creating controls like static or button (so far).
So I create a Window, a static and a button, log the pointers of the instances and only one WN_NCCREATE message is received with the windows pointer.
My question is: How can I get the passed parameter?
In my previous attempt several years ago, I used an std::map hwnd -> ptr which worked fine. In this attempt, I am trying to get a little deeper in WinAPI and try a different approach. Now I'm stuck with this, Google results didn't help much so far.
Should I stick with the map or is there another solution?

To do what you are attempting, you can do the following:
Call GetClassInfo()/GetClassInfoEx() to get the default WNDCLASS/WNDCLASSEX registration details for the pre-existing class you are trying to wrap, such as BUTTON.
Change the WNDCLASS::lpfnWndProc field to point at your own window message handler, and change the WNDCLASS::lpszClassName field to your own custom class name. Change any other WNDCLASS fields as needed.
Call RegisterClass()/RegisterClassEx() with the modified WNDCLASS/EX.
Now you can call CreateWindow/Ex() using your custom class name, and all creation messages, including WM_NCCREATE, will go through your window message handler.
This is how Embarcadero's VCL framework subclasses standard Windows controls.
Also see: How can I make a WNDPROC or DLGPROC a member of my C++ class?.

Related

How do I test if my custom callback is set as the current procedure for a given window?

We have a kiosk mode application for Windows Mobile 5 that was going strong for a year at least in production. It uses window subclassing through the SetWindowLong windows API function to override the behavior of the taskbar to prevent users from ever leaving our application or other explicitly allowed applications.
My callback overrides the handling of a few window messages and calls the default handler for other messages. This is done by storing the previous function pointer returned by SetWindowLong, and using it inside of the new function by calling CallWindowProc on it.
Then we had to update the application to be compatible with Windows Mobile 6.5.3, and started having a bunch of problems. I followed this article to disable the bottom menu buttons which are new on 6.5. On a single application, it works fine and the menu respects my callback. As soon as the user opens up another application through ours, that window seems to be recreated, and I had to devise a mechanism to detect foreground window changes and then "resubclass" the window again.
In my code, I don't have control of when exactly this window is recreated, so my first attempt was to use the GetWindowLong function to obtain the current callback address and test it against my own function address. I learned the hard way that I can't just compare the values like that, since it does not always return the function pointer.
Because I'm not able to test if my method is the current handler that way, I end up sometimes setting my method as the handler, and the previous handler is also my own method (in this case, the window was not recreated and thus already had my method set). This results in an infinite loop, since my callback ends up calling itself indefinitely.
How can I know if my custom function is the one being used by a certain window, so that I can avoid this infinite recursion?
Don't use SetWindowLong(GWL_WNDPROC) to subclass a window. Use SetWindowSubClass() instead (like Raymond Chen said):
Subclassing Controls
Safer subclassing
Amongst providing safer subclassing semantics (such as allowing multiple subclasses at a time), it also allows you to associate user-defined data with each subclass. So you could use GetWindowSubclass() to check if you have already subclassed the window or not.
Or, you could simply keep track of whether or not you have already subclassed the window. A simple boolean variable will suffice. Once your subclass is in place, you MUST remove the subclass before the window is fully destroyed. So, for instance, when the subclass receives the WM_NCDESTROY message, you can remove the subclass and clear your boolean at the same time, and then the next time you see the window again your boolean will tell you that you need to subclass the window.
Send the custom message to window. Handle this message in your custom function to return some value that will indicate that it was your custom handler.. and so on.
if(SendMessage(hwnd, mymsg, 0, 0) != myvalue)
;// It's not your handler

Child windows does not receive WM_DESTROY?

I packaged the winapi CreateWindowEx into a simple class. Since every window sharing a same wndProc(hwnd,msg,wparam,lparam), I put every window created by CreateWindowEx into a map to distribute msg, like this:
wndProc(hwnd, msg, wparam, lparam){
if(map[hwnd]!=nil){
switch(msg){
map[hwnd].wndProc(...)
}
}
}
And each time a window or its parent window being destroyed, remove it from the map:
case WM_DESTROY: delete(map, hwnd)
But things like buttons do not receive WM_DESTROY. I printed all msg in WM_NOTIFY and WM_COMMAND but i got noting.
So how can I remove those child windows form the map at the right time? Or a way distribute the msg without creating a hwnd map?
They certainly do get that message. But their window procedure is inside Windows, not inside your program. So you never see it. Something you can read in the MSDN documentation, note how WM_DESTROY doesn't get any special treatment. Nor generate a notification that your parent window can see.
Short from automatically removing all the child windows when you see the parent window destroyed, subclassing controls is a pretty standard requirement for C++ class library wrappers. Best to not invent your own btw, this has been done many times already.
So how can I remove those child windows form the map at the right time?
You have to subclass every window you create, either with SetWindowLongPtr(GWL_WNDPROC) or SetWindowSubClass(), then you will receive all of the WM_DESTROY messages.
Or a way distribute the msg without creating a hwnd map?
Frameworks like ATL and VCL handle that by dynamically allocating a thunk for each window and putting the object pointer right in the thunk, then use the thunk as the window procedure. That way, whenever the thunk is called, it passes the message directly to its associated object.

How does DispatchMessage decide which WndProc to use?

I'm going through some code for an open source project and this is my first time dealing with a Win32 app (mostly did console stuff). I see that several functions within the code are windows procedures because they return LRESULT CALLBACK.
Is there something the programmer has to do to make sure DispatchMessage invokes the right WndProc or is DispatchMessage coded in a way that it can determine the right WndProc all on its own?
EDIT:
I'm guessing that the way DispatchMessage(const MSG*) chooses between different WndProc's in an application is based on the window handle member (HWND) of the MSG object passed to it.[Hope previous sentence wasn't too confusing.] If the message was for the edit window for an application, for example, (and not for its main window,) then DispatchMessage will choose the WndProc member function for the particular class for which the edit window is an object of. If the message was for the main window, then it would choose the WndProc member function for the class that the main window is an object of (for me, this class would be the Notepad_plus_Window class). This is only a thought, though. I haven't found much to back it up so I'd be glad if anyone could confirm this.
Yes you are right, it uses MSG.hwnd to send the message to the correct window. One thing to be noted, it will use the WndProc associated with the window, not the window class. A window is an instance of a window class.
This article of Microsoft's "Under The Hood" illustrates this with rather detailed pseudo-code of DispatchMessage() that might be worth taking a look as well )

How to subclass Windows Explorer's window

I want to change color of listview of explorer.exe like this
I got the handle of listview window by GetTopWindow function and his family.
To subclass listview window of explorer.exe, I injected my dll code to explorer by following code.
SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc, g_hInstDll,
dwExplorerListviewThreadId);
My dll is loaed by explorer.exe well.
And I subclassed the window procedure by SetClassLongPtr(for global subclass) in injected code.
SetClassLongPtr returns success but my subclass function(SubclassProc) receives only WM_CREATE WM_DESTROY and WM_MOVE messages. What's wrong? I expected to get WM_NOTIFY and NM_CUSTOMDRAW.
The problem is that this is not a ListView in the first place; it's instead using Microsoft's internal "DirectlUI" framework, which is used in several places in explorer. It doesn't use any of the Common Control messages such as NM_CUSTOMDRAW. There's pretty much no reasonable way to change the colors it uses.
(Also, generally it's best to use SetWindowLongPtr instead of SetClassLongPtr for subclassing a HWND: SetClassLong only changes the underlying template that is used for creating new windows, but may not end up changing any instances that were based on that. And you should not be using the same function - GetMsgProc - for both the hook callback and the subclass proc; they need to handle the message in different ways, the hook callback needs to call CallNextHookEx while the subclass proc needs to call CallWindowProc with the original wndproc. But none of this really matters since the control isn't a ListView in the first place...)
I think and suppose that the OS has special protections for the explorer.exe process, because otherwise it would be an easy target for malicious code or just applications that think they are more important than they actually are (if some people insist on putting back a shortcut on their desktop every time you start the application, imagine what they would do when they had this sort of access to explorer.exe - everything in the shell).
EDIT: I was intrigued by the question and did some more research, I think there is a more mundane reason, see http://blogs.msdn.com/b/oldnewthing/archive/2005/09/07/461912.aspx. (basically: explorer.exe is the window manager so doesn't know about message routing yet when it receives certain messages, which is why they can't be intercepted with message hooks).

Win32 , WndProc, and parent-child windows

I'm developing in C code that uses the Win32 Api to create multiple windows.
I used createWindow twice - to create parent and child windows.
I have a message loop
while ( GetMssage (&msg, NULL,0,0)){
.
translate
dispatch
.
}
But I only get the WND_Proc function called once, instead of twice for each of the windows.
What am I doing wrong?
If I'm understanding your question correctly, you should expect your WndProc to receive a single WM_CREATE message for each window created of the window class for which the WndProc is registered.
Your WndProc will not receive a WM_CREATE for a window you create of a different class (like the standard Windows UI controls, for example), even if it is a direct child of a window of the WndProc's class. If you gave us some more specifics on what you are trying to accomplish we could provide suggestions or workarounds.
This question may also shed some more light on your situation.

Resources