Link to home
Start Free TrialLog in
Avatar of Hep_Cat
Hep_Cat

asked on

Sending a "quit" message

I have an endless loop that collects data from a port and displays it, but I have no way for the user to exit the program.

Is there some way to have the user click a button or something and have the loop terminate?  The normal handler functions don't work because execution never leaves my "Get/Display" loop.
Avatar of mblat
mblat

There are couple ways to do that

1. Start worket thread ( Let's say using _beginthread or any other way) and run you loop in that thread calling Sleep(1) in a loop to let main aplication some time for processing.

2. Incorporate messsage pump into you loop

something like
while(1)
{
   MSG msg;

   while( GetMessage( &msg, NULL, 0, 0 ) )
   {
     TranslateMessage( &msg );
     DispatchMessage( &msg );
   }
  / do your stuff here....
}

I like first method.

Hope it helps...
@ mblat:

Your code doesn't work: the "do your stuff here..." is called after a WM_QUIT-message has been posted - this is the only case in which GetMessage returns FALSE. I also doubt that this type of message-loop is accessible in an MFC-application. P.S.: The correct use of the Sleep()-call would be: Sleep( 0 ) which passes all remaining time from the thread's time slice to other threads running in the same process.

@ Hep_Cat:

You have two alternatives, an easy-but-dirty-hack or the clean way to go:
* dirty-hack: use
exit( 0 );
and your application will terminate instantly. If you use this on win 9x systems it will get unstable after a while since no memory clean-up is performed and resources aren't freed at program termination.
* Put your Get/Display-loop on a second thread and terminate this thread when the user wants to exit your program. The easiest way to approach this would be to create an event (look up CreateEvent in MSDN). If the user wants to terminate your application put it in signalled state. In your Get/Display-loop put a WaitForSingleObject-call to see whether program termination was requested and act accordingly. After you signalled the event upon user request to terminated wait for your Get/Display-thread to terminate and finally exit the application.
2 fll0yd - you right it should be

while(1)
{
        if (PeekMessage (&wmsg, NULL, 0, 0, PM_REMOVE))
        {
        if(wmsg.message == WM_QUIT)
            return;
           
        TranslateMessage(&wmsg);
        DispatchMessage(&wmsg);
        }

// do the stuff here....
}

as far as it being correct usage in MFC type apps - while it is not "clean" way - ( an I mentioned that I prefer way with threads ) I've seen it done all over the place.  It works.
This type of message-loop is *CLEAN* coding style and is being used in the majority of games, I'd say. It doesn't work with MFC though and needs to be adjusted:
* the "return;"-statement should be replaced by a "break;" to make the code cleaner, ie process clean-up directly after the 'infinite' loop.
* you need to initialize your wmsg-structure if you want to be safe
* you need to replace "if( PeekMessage( ..." by "while( PeekMessage( ..." otherwise your application can expose awkward behaviour [handling one message at a time and interleaving it with your own -- possibly computationally expensive -- code]

summary:

MSG wmsg = { 0 };
while( true ) {
    while( PeekMessage( &wmsg, NULL, 0, 0, PM_REMOVE ) ) {
        if( WM_QUIT == wmsg.message )
            break;
        TranslateMessage( &wmsg );
        DispatchMessage( &wmsg );
    }
    // do the stuff here...
}
// perform clean-up code

This is the way to go. Might sound like nitpicking and marginal changes, but they certainly have immense impact on the application's behaviour.
ASKER CERTIFIED SOLUTION
Avatar of DanRollins
DanRollins
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Hep_Cat

ASKER

This was the simplest.  And it had the most complete code examples.  Worked very well.