Sign in to follow this  

Question on Multiple windows with Win32

This topic is 4072 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hey guy, I am sorry, this might be a stupid question, and has, possibly, been asked before. I searched but couldn't find any help. My question is, I want to make a program where the first window that opens asks a user for input. Then when they have put in their input and click a button, I would like that window to close and depending on the input selected, I would like one of two other windows to open. What is the best way to accomplish this? I *could* write code to open the second window after the first windows message loop, but that seems kind of stupid and I figured making each window in their own .cpp file would be the best method. I just have no clue on how to do it. Any help or opinions would be appreciated. Thanks.

Share this post


Link to post
Share on other sites
Quote:
What is the best way to accomplish this? I *could* write code to open the second window after the first windows message loop, but that seems kind of stupid and I figured making each window in their own .cpp file would be the best method. I just have no clue on how to do it.

Any help or opinions would be appreciated


You could put the CreateWindow call inside the WM_DESTROY message handler of the first window. That way the input data is still around if you stored it with the window, which is the only reason I can think of that you don't want to do it the way you mentioned. Then have the setup code inside the WM_CREATE handler of the window being opened.

Share this post


Link to post
Share on other sites
Well, I was over thinking the whole thing. I was thinking I would have to write a lot more code to do it that way than I actually do. The WNDCLASSEX just needs modified instead of making a completely new one, or I could just use the DialogBox() function. I also forgot about the extern keyword to include functions from other files.

Thank you for your reply rsood, I appreciate the time you spent reading the post and offering your ideas. That was something I hadn't thought of, but would also be a good solution for some other programs I have been wanting to make.

Thanks again.

Share this post


Link to post
Share on other sites
Managing multiple windows isn't quite so hard as you might think. There's several ways to do it, depending on how snazzy you want the program to be (and what you need it to do).

You can create multiple windows with different parameters to CreateWindowEx(), using the same windows class. This method is kind of limited, because you'll have two nearly identical windows! (with the exception of the few parameters changed in the call) Also, it's important to note that any actions in either of the created windows will call the same message handler, so either keep track of these windows or pay the conciquences!

You can also create multiple windows classes and multiple windows! This is only about as hard as writing more message handlers! It's not so hard to use multiple message handlers, you'll just have to use GetMessage() (or PeekMessage()) for each active window handle (I'm not sure if a call to a window that's been destroyed will fail, but it's not hard to fix if it does. ^.~) and the translate() and dispatch() functions as well. Well, at least I'm 90% sure you need to call them for each, but it's not hard to test and fix a few lines of code...

Other then that, it's your imagination as to what you can do! Just use your different window handles to draw in and create as many things as you want and keep in mind during all the events that you may have multiple windows open, and you'll be dandy! ^.^

Share this post


Link to post
Share on other sites
Also note that if you are just looking for other window procedures and don't want to have a new WNDCLASS for each and every window you could go with the SetWindowLong method. MSDN link here. This method can simply replace the current window procedure of specified window by another, specified, windowprocedure. As such, you don't have to create three different classes if the windows aren't going to change that much.

Share this post


Link to post
Share on other sites
Thank you all for all your help and ideas. All I had to do was after the first window's message loop, I change the WNDCLASSEX class name and window procedure. I tested it, and it all seems to work great.

@rogierpennink -- I have used SetWindowLong to alter a lot of things, but I wasn't sure you could use it to change the window procedure or class name or the window. Thank you for the link.

@Motocrossdoug -- Thank you for the response and ideas. I think I have it figured out now with all of the help.


Thank you all again for all the responses and ideas, it has been very helpful and I appreciate it.



#include <windows.h>
#include "resource.h"

HWND hMainButtonClose;
HWND hMainButtonExit;
HWND hMainText;

LRESULT CALLBACK MainProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); //window procedure for main window
LRESULT CALLBACK SecondProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); //window procedure for second window

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLine, int iCmdShow)
{
WNDCLASSEX wnd;
wnd.cbClsExtra = 0;
wnd.cbSize = sizeof(WNDCLASSEX);
wnd.cbWndExtra = 0;
wnd.hbrBackground = (HBRUSH)GetStockObject(LTGRAY_BRUSH);
wnd.hCursor = LoadCursor(NULL, IDC_ARROW);
wnd.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wnd.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
wnd.hInstance = hInstance;
wnd.lpfnWndProc = MainProc;
wnd.lpszClassName = "WindowOne";
wnd.lpszMenuName = NULL;
wnd.style = NULL;

RegisterClassEx(&wnd);

HWND hWndOne = CreateWindowEx(WS_EX_WINDOWEDGE, "WindowOne", "First Window", WS_SYSMENU|WS_CAPTION,100,100,100,100,NULL,NULL,hInstance,NULL);

ShowWindow(hWndOne,iCmdShow);
UpdateWindow(hWndOne);

MSG msg;
while(GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}

wnd.lpfnWndProc = SecondProc;
wnd.lpszClassName = "WindowTwo";

RegisterClassEx(&wnd);

HWND hWndTwo = CreateWindowEx(WS_EX_WINDOWEDGE, "WindowTwo", "Second Window", WS_SYSMENU|WS_CAPTION,100,100,100,100,NULL,NULL,hInstance,NULL);
ShowWindow(hWndTwo,iCmdShow);
UpdateWindow(hWndTwo);

while(GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}

}

LRESULT CALLBACK MainProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_CREATE:
HWND hBtn1,hBtn2;
hBtn1 = CreateWindowEx(WS_EX_CLIENTEDGE, "BUTTON", "Ok", WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,4,4,50,20,hWnd,(HMENU)1001,GetModuleHandle(NULL),NULL);
hBtn1 = CreateWindowEx(WS_EX_CLIENTEDGE, "BUTTON", "Exit", WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,4,28,50,20,hWnd,(HMENU)1002,GetModuleHandle(NULL),NULL);
break;
case WM_COMMAND:
if(HIWORD(wParam)==BN_CLICKED)
{
if(LOWORD(wParam)==1001) //OK
{
MessageBox(NULL, "OK -- FirstWindow", "Button Clicked", MB_OK);
}
else if(LOWORD(wParam)==1002) //Close
{
MessageBox(NULL, "Exit -- First Window", "Button Clicked", MB_OK);
SendMessage(hWnd, WM_CLOSE,NULL,NULL);
}
}
break;
case WM_CLOSE:
CloseWindow(hWnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}

LRESULT CALLBACK SecondProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_CREATE:
HWND hBtn1,hBtn2;
hBtn1 = CreateWindowEx(WS_EX_CLIENTEDGE, "BUTTON", "Ok", WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,4,4,50,20,hWnd,(HMENU)1001,GetModuleHandle(NULL),NULL);
hBtn1 = CreateWindowEx(WS_EX_CLIENTEDGE, "BUTTON", "Exit", WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,4,28,50,20,hWnd,(HMENU)1002,GetModuleHandle(NULL),NULL);
break;
case WM_COMMAND:
if(HIWORD(wParam)==BN_CLICKED)
{
if(LOWORD(wParam)==1001) //OK
{
MessageBox(NULL, "OK -- Second Window", "Button Clicked", MB_OK);
}
else if(LOWORD(wParam)==1002) //Close
{
MessageBox(NULL, "Exit -- Second Window", "Button Clicked", MB_OK);
SendMessage(hWnd, WM_DESTROY,NULL,NULL);
}
}
break;
case WM_CLOSE:
PostQuitMessage(0);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}

Share this post


Link to post
Share on other sites
Nice! ^.^

I just have two questions, though.

1. Do you need to use UpdateWindow() and ShowWindow()? I don't remember ever using them and all my prog's worked. o.O

2 GetMessage() will exit out of the while() loop itself? Interesting... I guess I always used PeekMessage(), so... =] I guess Peek needs it's own exit command monitoring? (sorry, it's been a while sense I've messed with the older windows stuff)

Share this post


Link to post
Share on other sites
Motocrossdoug:
From what I understand, you can bypass ShowWindow() and UpdateWindow() with the WS_VISIBLE window style. The book I have been reading say it's mainly used if the int iCmdShow (or however you named it) is passed into the program to start it, incase you don't want it to show I suppose.

Also, (again not a definite, just what I have heard) GetMessage and PeekMessage work fairly similarly. However, in a normal Windows application GetMessage will use less resources because it waits for messages on the stack, while PeekMessage will keep looking for incoming messages.

I believe once a message is received they both work the same, just that unless you need to look for messages constantly (such as games) to use GetMessage.

GetMessage doesn't exit the while loop automatically, it won't end until WM_DESTROY or WM_CLOSE is called in the first window procedure. That form just has 2 buttons, an "OK" and "Exit" button. Exit calls WM_CLOSE which, in turn, calls CloseWindow(). Then it exits that while loop and proceeds to the next one.

Share this post


Link to post
Share on other sites
Ahh, I think I see what you mean by using ShowWindow() and UpdateWindow(), I guess it's kind of an extraneous minor detail...

As for PeekMessage() and GetMessage(), I guess I never looked at GetMessage() well, it returns false if the app is terminated I suppose. (I guess I could take five seconds and make sure that's correct but meh...)

Also, PeekMessage() is many times better then GetMessage() for games. GetMessage() will wait for a message to show up, holding up any game code you need to execute. Using PeekMessage(), you can take a look into the queue every frame (or how often you call it, I guess...) and if nothing is there, the game will chug on... here's the code snippet of what I mean...

     /* create your window, display it... */
while(true)
{
if(PeekMessage(&msg,hwnd,0,0,PM_REMOVE))
{
if(msg.message == WM_QUIT)
break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}

GameLogic(); // remember to return back or messages won't be proccessed. The best way is per frame...
}
/* program termination code */
}

Share this post


Link to post
Share on other sites

This topic is 4072 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

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