Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Modal Dialog and processing messages from other window. 1

Status
Not open for further replies.

Vorlath

Programmer
May 7, 2003
31
CA
I have an application where I need to keep processing 2 messages (WM_USER and WM_USER+1) from WSAASyncSelect() while displaying modal dialogs.

Basically, I can't stop processing socket messages while modal dialogs are shown. Right now, it seems that the best way is to not make the dialog modal and check when it loses focus if the app is still active. If so, bring the dialog back into focus.

The messages are sent to the main window. Is there a way to make the messages sent to the app (globally) instead?


A programmer is a device for converting Coke into software.
 
What about using a thread to monitor your events?
 
Yep, a separate thread is the best(only?) solution. Threads are pretty easy.

Use the File->New->Other and create a Thread Object.

Include the thread header in your main program, then create it VCL style.

In your private section of your form, add TMyThread *MyThread;

Then in the OnCreate section for the form:
MyThread = new TMyThread(false);
Here, false means to not create the thread in a suspended state. Threads can be suspended and resumed at any time by the main VCL thread (which is usually your main form). You just call MyThread->Suspend() and MyThread->Resume(). It stops the thread no matter what it is doing, so be careful with that. You don't want to do something like that when you are querying a serial port for instance, because certain timeouts and events aren't handled properly by Windows. I don't recommend using suspend and resume.

You can get around that by creating a new thread when you need it and terminating it when you don't. Termination is another tricky one. The thread has a property, FreeOnTerminate. You don't really want to use this if you are going to make more than one thread in an application instance. I'll explain more in a minute.

The main execution of the thread is in the Execute function, which you will fill with your own execution routines. Typically, and this is left up to you, you want to put a while (!Terminated) loop in the execute function. When your main thread (the main form) calls MyThread->Terminate(), ALL it does is set the property "Terminated" to true. So your while loop will come back to the top and see that it is terminated and finally exit the thread's execute function.

The typical way to terminate and destroy the thread is like follows:

if (MyThread)
{
MyThread->Terminate();
MyThread->WaitFor(); // waits for the thread to finish the execute function.
delete MyThread;
MyThread = NULL;
}

Don't forget to always set MyThread back to NULL after deleting it.

The property "FreeOnTerminate", if it is true, will destroy the thread after it finishes the Execute function. The above code "if(MyThread)" will still be true, but pointing to an invalid location in memory. That's why I say you probably don't want to use the FreeOnTerminate in most cases, and always set MyThread back to NULL.

If MyThread needs to run code in the main form's thread, code that the main form will be running itself at some point, be careful. You need to use a function called Synchronize if you do this. The reason is, the main form could be running some function "UpdateDisplay" and then your thread comes along and tries to run the same function, and BOOM, everything goes bad. The synchronize function will wait for the main form to finish processing that method (if it currently is) and then process the thread's method. Don't want to use it on lengthy time-consuming functions though, for obvious reasons.

Hope this helps get you started!
Chris
 
Thanks for the reply. However, I fail to understand how I'm supposed to retrieve only certain messages. If I synchronize Application->ProcessMessages(), won't it block my thread if it tries to pop up another modal dialog?

I really don't know how to check for certain messages and leave others in the queue. Do I use PeekMessage() Windows API call? If I do use PeekMessage, how do I pass that info to the correct window procedure? GetWindowLong() with GWL_WNDPROC? Seems like a whole lot of work.

For now, I made all my dialogs modeless and put a variable in my main form holding which dialog is active. I also use the application's OnActivate and OnDeactivate to set/remove the StayOnTop flag on the current dialog with SetWindowPos() but the window still stays on top. Not sure what I should do at this point.

 
Maybe you could show the modal dialog box from MyThread instead. Then only MyThread would be hung up while the main thread continues to pump.

Chris
 
That's brilliant! I will definitely try that.

Thank you so much!


A programmer is a device for converting Coke into software.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top