Win32 , WndProc, and parent-child windows - winapi

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.

Related

CreateWindowEx lpParam for button, etc in WM_NCCREATE

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?.

Access Windows Controls from another class or window

In an MFC program I am trying to access controls that are in one window (class) from another (sibling or daughter) window with code in a different .cpp file. Typically you access a control with a DDX_Control variable defined in the class .cpp file.
DDX_Control(pDX, IDC_STATUS, m_Status);
The code for the other window is in a different file, so I don’t have access to the control variable (m_Status). What I have done is used FindWindow to find the main window, then GetDlgItem to find the control I am interested in:
CWnd * tmpWnd = CWnd::FindWindow(NULL,"MainWindow"); // find the main dialog box
CStatic * tmpStatus = (CStatic*) tmpWnd->GetDlgItem(IDC_Status);
tmpStatus->SetWindowText(“Status Report);
This works fine in the debugger, but fails when executed outside the debugger. FindWindow gets the window ID correctly, but GetDlgItem returns null.
Ideally I’d like to access the control variable (m_Status) from the other window, but I don’ know how to do so. I understand the GetDlgItem is less than ideal under any circumstance.
One solution would be to send a message to the main window class and tell it what to do, but I’d have to have a routine to handle each control and know how to handle whatever kind of data I am sending.
Is there a “right” way to do this?
Thank you
The ultimate answer is to cast to the original class:
((CspDlg *)AfxGetMainWnd())->m_Status.SetWindowText("Report");
Since you created the "main" window you have an object or pointer for it. Or, you can call AfxGetMainWnd() to get a pointer to it. Then you can use that to access a public member such as m_Status. All of your windows are interconnected and it should not be necessary to use FindWindow to find any window in your own program.
The fact that some variables may be defined in another file is not relevant. That can be handled with suitable use of #include "theotherfile.h" and object pointers/references.

Destroying child window without parent WIN32 APi

I have one problem . I am trying to destroy child window ,but it also destroys parent window, so application closes.
I have such code.
HWND cloneWin =FindWindowEx(hWnd, 0, szChildWin, 0);
if (cloneWin) {
MessageBox(NULL,"You are trying to create more than one child window\n Current child window will be destroyed", "Message", MB_OK|MB_ICONINFORMATION);
DestroyWindow(cloneWin);
}
What is wrong ?
THx in advance !
The documentation says:
A thread cannot use DestroyWindow to destroy a window created by a different thread.
Since you are trying to find these windows using FindWindowEx, it seems pretty obvious that the windows were created in a different process, never mind a different thread. In other words, your call to DestroyWindow can never succeed. Hard to know why this is bringing the other application down, but since you are not obeying the rules then I suppose it is reasonable that anything can happen.
It's plausible I suppose that you could send the window a WM_CLOSE message and hope that it will respond by calling DestroyWindow. That would be a valid call to DestroyWindow because it would be made on the thread that created the window. But it all depends on how that other window responds to WM_CLOSE.

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).

Resources