Jump to content
  • Advertisement
Sign in to follow this  
Frankie68

How does MessageBox(...) store the stack/context?

This topic is 4862 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

Alright, this all might seem a bit theoretical, but at the end, I will give a good reason to think about this. First something small about the typical windows-system way of emptying the message queue and transforming them into events. It's not that I consider myself such a great teacher, but letting me explain might point out some things I have missed. Here it goes: There are two threads of interest here: 1. The OS thread that reads out the mouse position, renders the mouse on the screen en fills the message queue of my window with messages. This can (and will be most likely) be implemented using interrupts, but seeing it as a thread makes it a bit more simple. 2. My process, checking the message queue continuously for some user activity. When there is a message, it sometimes needs some action: when the user clicked on a button, it will read the WM_COMMAND, find the function that is defined as the OnClick-handler and execute that code. When the code is executed, it returns to the the main procedure (the message queue checking code) and checks for new messages. This is more of less the system as I understand it, and I feel I am not far from the truth, but again: if I am wrong, please correct me. Now, my problem: what happens if the OnClick-code contains a call to `MessageBox(...)'? The function will be called, it will call the routine, which will display the MODAL dialog, and it will wait until the user clicks OK. My process (the second thread) is blocked, until the messagebox closed. The OS thread (number 1) still can add new messages to my queue, but they will have to wait until the OnClick function returns. Or will they? As it turns out, it doesn't work this way. To test it (and to let you experience it), I did the following: 1. Using VC, I created a new dialog based MFC project (as simple as possible, we don't need much) 2. I created a button 3. The onclick of the button contains the following code: SetTimer(1000, 1000, NULL); 4. I created an OnTimer event for the window containing this code: CString sOutput; m_iTestInt++; sOutput.Format("%d", m_iTestInt); AfxMessageBox(sOutput); m_iTestInt--; CDialog::OnTimer(nIDEvent); 5. The Dlg-class also needs an int named "m_iTestInt" and I set it to 0 in the ctor 6. I started the app and clicked on the button. I expected to see one messagebox (after about a second) and then the application should be blocked until I pressed its OK button. Then there would be directly an other message box. They all would show the value "1". This didn't happen. What did happen was this: a messagebox appeared showing "1", a second later one that showed "2", second later "3", etc... When I closed one, the next one showed a value one lower than its order (for example: 4 instead of 5). This is hard to explain using my view of the world of the two threads. One explanation might be that there is a thread started for every WM_TIMER message. Seems OK (yet a bit like resources spoiling), but by adding "Sleep(2000)" to the OnTimer, we see that the entire application gets locked for 2 seconds, not just a single thread (in that case the messageboxes would continue uninterrupted). Maybe it exits MessageBox directly? It only shows the dialog and ignores all input to other windows? This seems to make sense, except for one thing: the "m_iTestInt--;". If the system worked like this, the messageboxes all would display the same number ("1"). My hunch is that the stack gets stored somewhere and restored when the user clicks OK (when the modal dialog box is closed). This explains the displayed value and als the behaviour of the Sleep(2000). But I have no idea how this should be implemented. I really, really would like your input on this, I have been thinking about it for a while now and I would really like to find out how this is done. Now, as I promised, my reason: not only is this interesting behaviour, it can also be useful in some fields. I am creating a GUI using OpenGL, and I want to draw the entire Gui every frame (that way the rest of the game can move on, without wainting for the user input). But I also want everything to be in one thread (game logic+GUI+mouse/keyboard handling), so implementing modal dialogs is kind of tricky. I am currently doing it by returning a value to the class that called the ShowModal method. So the calling function needs to leave the class in a coherent way, and the class needs to process the user input (he clicked OK, entered a single value, or whatever), in a special function for all GUI returned actions. A typical example of something that is very simple in MFC and hard in my GUI is this: 1. Ask for connection info to the server (its IP, connection type), user clicks ok 2. Check the IP to find out that he entered an invalid value. 3. Show a messagebox and keep the original window open (with the values). In my case, I need to define a value IPNOTCORRECT_OK that is returned to the GUI handling function and implement the rest of the code in that function (or a function that is being called by the GUI function). The MFC way is way simpler, obviously. Thanx for reading and I hope you can help me with this... :)

Share this post


Link to post
Share on other sites
Advertisement
It was my understanding that all messageboxes are on teh same thread adn therefor the same stack as the thread that creates them. ie if they are modal it will spin in the modal loop but stil have the calling code upto the dialog box on the stack, not removed somewhere as you put.

YOu can always break into a debugger at the dialog box to read the call stack. I think your making seem harder than it is.

CHeers
Chris

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
There aren't any threads being created for the timer. MessageBox internally creates its own message loop, suspending your main app loop. If an HWND is passed to MessageBox, it'll suspend input to that window so WM_TIMER won't get through while the message box is displayed. If NULL is passed for the HWND, MessageBox behaves identical to your main app loop -- it doesn't know what window to filter out. AfxMessageBox tries to find the main window's HWND to pass to MessageBox but I'm guessing this is failing for a dialog-based app. Stick a breakpoint in OnTimer and you're likely to see the following call stack after a few iterations:

... repeat 6-9 ...
9 OnTimer
8 MsgBoxWndProc
7 MessageBox
6 AfxMessageBox
5 OnTimer
4 MsgBoxWndProc
3 MessageBox
2 AfxMessageBox
1 OnClick

Share this post


Link to post
Share on other sites
you're both right, if I just had spend some more time on running the app and checking the stack... ;) Anyways, thanks :)

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!