In our application, the WM_CLOSE message processor determines the state of the application, issues all the "Are you sure?" questions, etc. If the close is to be continued, a WM_QUIT message is posted and a value of FALSE is returned. Otherwise a value of TRUE is returned.
The window receiving the WMU_EndTask message handles it by posting a WM_CLOSE message to itself, and letting the WM_CLOSE processing handle it. The only reason it is not translated to a WM_CLOSE within the message loop is allow future use. This message requires no special handling.
The window receiving the WMU_ShutDown message handles it by sending (not posting) a WM_CLOSE message to itself. If the WM_CLOSE message returns TRUE, then a WinCancelShutdown (hmq, FALSE) call is issued to cancel this instance of the shutdown.
If you issue a WinCancelShutdown (hmq, TRUE), a WM_QUIT message will never be sent to your message queue, so will not have an opportunity to stop the shutdown. This is intended for secondary message queues that do not have a message loop.
while (1) { HWND hwndClient; // Get next message from queue if (!WinGetMsg (hab, &qmsg, NULLHANDLE, 0, 0)) { // The WM_QUIT message has three sources: // 1. The task manager 'End task' pulldown // 2. System shutdown from desktop manager // 3. Posted by the application // This is a WM_QUIT message. Check the window handle, if the // handle matches mp2, it is from switch list close if (qmsg.hwnd == HWNDFROMMP (qmsg.mp2)) { // This is from close on the task list, convert to our message qmsg.msg = WMU_EndTask; // Get the intended client's window handle if (!(hwndClient = WinWindowFromID (qmsg.hwnd, FID_CLIENT))) { // Failed to find client. No idea who this belongs to, // give it to default window for processing hwndClient = hwndDefault } // Otherwise, readdress the message to the appropriate client qmsg.hwnd = hwndClient; // We can use mp1 and mp2 for anything we want. // Currently, just clear both qmsg.mp1 = qmsg.mp2 = 0L; } else if (qmsg.hwnd == NULLHANDLE) { // This message is from shutdown, // Address it to default window for processing qmsg.hwnd = hwndDefault; // And set the message to our shutdown message, qmsg.msg = WMU_SysShutdown; } else { // If here, we posted the WM_QUIT message, so break out of // the message loop break; } } // This is not a WM_QUIT message, intercept all other // messages intended for the NULL window if (qmsg.hwnd == NULLHANDLE) { // Pass all NULL window messages to the NULL window handler NullMsg (qmsg.hwnd, qmsg.msg, qmsg.mp1, qmsg.mp2); } else { // This is not a WM_QUIT message, nor is it intended for the NULL // window. Pass this message to the message filter hook for // processing. if (!WinCallMsgFilter (hab, (PQMSG) &qmsg, 0)) { // Filter hook has not cancelled the message, so dispatch // the message to the proper window WinDispatchMsg (hab, &qmsg); } } }
Credit: Matt Osborn