Sign in to follow this  
VanillaSnake21

[SOLVED]WindowProc for multiple windows?

Recommended Posts

Codeka    1239
Why would you handle two different windows with the same WndProc? Common sense would suggest to me that if the windows are different, use a different WndProc...

Share this post


Link to post
Share on other sites
Codeka    1239
Quote:
Original post by VanillaSnake21
What if I have a window created at runtime (which I do, an error message dialog box)?


Oh, I see what you mean. You might have multiple instances of the same window sharing the same WndProc. That makes sense.

The way I implement such things (and I think this is a common pattern) is you have a C++ class that encapsulates your window so you have one instance of this class per visible window, right?

You simply use the SetWindowLongPtr function to set the GWLP_USERDATA property to a pointer to your class. Then in the WndProc, use GetWindowLongPtr to get that pointer back and call the methods on your class to handle the message.

Share this post


Link to post
Share on other sites
VanillaSnake21    175
Quote:
Original post by Codeka
Quote:
Original post by VanillaSnake21
What if I have a window created at runtime (which I do, an error message dialog box)?


Oh, I see what you mean. You might have multiple instances of the same window sharing the same WndProc. That makes sense.

The way I implement such things (and I think this is a common pattern) is you have a C++ class that encapsulates your window so you have one instance of this class per visible window, right?

You simply use the SetWindowLongPtr function to set the GWLP_USERDATA property to a pointer to your class. Then in the WndProc, use GetWindowLongPtr to get that pointer back and call the methods on your class to handle the message.



Maybe I wasn't clear of what I'm trying to do. I want multiple windows created from the same WINDOWCLASS structure (meaning WndProc handles all of their messages) to be able to lets say paint in their client area.

So inside WindowProc I have

switch(uMsg)
{
case WM_PAINT: TextOut(...)
}

but this outputs the Text on all the windows, and even if I specify the correct window in TextOut(m_MyDialog...) that would still be called even when don't want to draw to this window.

I remeber doing this and it was pretty easy. What I basically want to know is which window the message is being passed to (this is contained in the first param of WindowProc) and then compare that handle to the handle of the window that I have, if they are the same paint in the client of that window.

Share this post


Link to post
Share on other sites
Evil Steve    2017
Quote:
Original post by VanillaSnake21
How can no-one know how this could be done, this is beyond trivial.
You just check the hWnd parameter. I don't quite follow how this isn't working - a HWND refers to one window, unless you're updating all windows with the same data, there shouldn't be a problem.

If you have:

switch(uMsg)
{
case WM_PAINT: TextOut(...)
}


then that will work fine, provided you pass the HDC from BeginPaint() or the HDC from GetDC(hWnd). If that's not working, we'll need to see more code.

EDIT:
Quote:
Original post by VanillaSnake21
What I basically want to know is which window the message is being passed to (this is contained in the first param of WindowProc) and then compare that handle to the handle of the window that I have, if they are the same paint in the client of that window.
If you get a WM_PAINT, you need to paint something. If you ignore it and only handle particular window handles, your windows won't update properly (Not sure if you're doing this already though).

The way I'd do this is by using the method Codeka suggests. That should work fine. Here's some example code that works fine with multiple windows for one class.

Share this post


Link to post
Share on other sites
rethan    149
Might be guessing here but read up on how messages are propagated to child windows. I think Windows will keep pasing the "paste" message to all child windows and the parent until it figures out that one of the child windows handled the event (so you'll need to return the correct value from the WinProc once you find the window that handled the message.)

Also, how are you keeping track of that "MyWindow" variable?

Share this post


Link to post
Share on other sites
VanillaSnake21    175
@EvilSteve

LRESULT CALLBACK WindowManagerExtension::m_MessageProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_CLOSE: PostQuitMessage(0); break;

case WM_PAINT:
{
//*******
//DOESNT WORK
//**********
HDC hDC = GetDC(m_Dialog);

TextOut(hDC, 20, 20, "Hello", 5);
ReleaseDC(m_Dialog, hDC);

//WORKS***
hDC = GetDC(hWnd);
TextOut(hDC, 20, 20, "Hello", 5);
ReleaseDC(m_hWnd, hDC);

} break;

}

return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

Thats my code. Basically when I use m_Dialog (window for the dialog stored in my class) to get the DC there is no output. When I use the window that is passed to WinProc (hWnd) then it works but outputs on both the dialog window and the main window.

Share this post


Link to post
Share on other sites
rethan    149
Also, the WinAPI docs from MSDN mention this:

"An application returns zero if it processes this message." which you seem to not do. In the "Works" case, since you have multiple windows using that same function, each window that gets a paint message will paint "Hello". If you know all your window handles (and get them from CreateWindow() or CreateWindowEx()), then you can switch on that within the WM_PAINT case like so:

case WM_PAINT:
{
switch (hWnd)
{
case m_Dialog:
hDC = GetDC(hWnd);
TextOut(hDC, 20, 20, "Hello", 5);
ReleaseDC(hWnd, hDC);
return 0;
case m_Main:
...
return 0;
}
break;
}

(Or better yet put the drawing code in a function that you can call to make the code cleaner.)


I also noticed that you release on m_hWnd and not hWnd here:ReleaseDC(m_hWnd, hDC);, m_hWnd should be hWnd since you GetDC(hWnd).

Share this post


Link to post
Share on other sites
VanillaSnake21    175
Quote:
Original post by rethan


switch (hWnd)


(Or better yet put the drawing code in a function that you can call to make the code cleaner.)

Thats what I'm talking about, if you read my OP I tried it. I said
if(hWnd == m_Dialog)
but that doesn't work, thats what led me to this question, how do I compare window handles correctly?


Quote:

I also noticed that you release on m_hWnd and not hWnd here:ReleaseDC(m_hWnd, hDC);, m_hWnd should be hWnd since you GetDC(hWnd).


typo

Share this post


Link to post
Share on other sites
Evil Steve    2017
Quote:
Original post by VanillaSnake21
@EvilSteve

//*******
//DOESNT WORK
//**********
HDC hDC = GetDC(m_Dialog);

TextOut(hDC, 20, 20, "Hello", 5);
ReleaseDC(m_Dialog, hDC);

//WORKS***
hDC = GetDC(hWnd);
TextOut(hDC, 20, 20, "Hello", 5);
ReleaseDC(m_hWnd, hDC);
That means that hWnd is not the same as m_Dialog, which means something is getting screwed up and m_Dialog doesn't refer to "this" window.

Quote:
Original post by VanillaSnake21
Thats what I'm talking about, if you read my OP I tried it. I said
if(hWnd == m_Dialog)
but that doesn't work, thats what led me to this question, how do I compare window handles correctly?
That does work. But m_Dialog probably doesn't contain the correct handle.

Can we see the full source where you assign m_Dialog? The code I linked in my last post works fine.

Share this post


Link to post
Share on other sites
VanillaSnake21    175
Quote:
Original post by Evil Steve

Can we see the full source where you assign m_Dialog? The code I linked in my last post works fine.


Wow, thanks, it's a pretty stupid mistake. My dialog assignement had m_Window (which is my main window) insetad of m_Dialog to the left of CreateWindow... Fixed it, everything works :). Thats what happens when you copy and paste code... Thanks everyone.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this