Problem with closing just the window not the app on Win32 app.

Started by
5 comments, last by Empirical 19 years, 7 months ago
Hi, I'm new on Win32 programming.. so I'm having some problems with it. I have a Win32 with 2 windows and when I close the second one, the app is closing. But I want just the window being closed. How to do this? Here is the code:

// INCLUDES ///////////////////////////////////////////////
#define WIN32_LEAN_AND_MEAN  // just say no to MFC

#include <windows.h>   // include all the windows headers
#include <windowsx.h>  // include useful macros

// FUNCTIONS //////////////////////////////////////////////
LRESULT CALLBACK WindowProc(HWND hwnd, 
						    UINT msg, 
                            WPARAM wparam, 
                            LPARAM lparam)
{
    // this is the main message handler of the system
    PAINTSTRUCT		ps;		// used in WM_PAINT
    HDC				hdc;	// handle to a device context
    
    // what is the message 
    switch(msg)
    	{	
    	case WM_CREATE: 
            {
    		// do initialization stuff here
    
            // return success
    		return(0);
    		} break;
    
    	case WM_PAINT: 
    		{
    		// simply validate the window
    		hdc = BeginPaint(hwnd,&ps);	 
    		// you would do all your painting here
            EndPaint(hwnd,&ps);
    
            // return success
    		return(0);
       		} break;
    
    	case WM_DESTROY: 
    		{
    		// kill the application, this sends a WM_QUIT message 
    		PostQuitMessage(0);
    
            // return success
    		return(0);
    		} break;
    
    	default:break;
    
        } // end switch
    
    // process any messages that we didn't take care of 
    return (DefWindowProc(hwnd, msg, wparam, lparam));

} // end WinProc

// WINMAIN ////////////////////////////////////////////////
int WINAPI WinMain(	HINSTANCE hinstance,
					HINSTANCE hprevinstance,
					LPSTR lpcmdline,
					int ncmdshow)
{
    const char* names[] = { "WINCLASS1", "WINCLASS2" };
    WNDCLASSEX winclass, winclass2; // this will hold the classes we create
    HWND	   hwnd, hwnd2;	        // generic window handle
    MSG		   msg;		            // generic message
    
    // first fill in the window class stucture
    winclass.cbSize         = sizeof(WNDCLASSEX);
    winclass.style			= CS_DBLCLKS | CS_OWNDC | 
                              CS_HREDRAW | CS_VREDRAW;
    winclass.lpfnWndProc	= WindowProc;
    winclass.cbClsExtra		= 0;
    winclass.cbWndExtra		= 0;
    winclass.hInstance		= hinstance;
    winclass.hIcon			= LoadIcon(NULL, IDI_APPLICATION);
    winclass.hCursor		= LoadCursor(NULL, IDC_ARROW);
    winclass.hbrBackground	= (HBRUSH)GetStockObject(BLACK_BRUSH);
    winclass.lpszMenuName	= NULL;
    winclass.lpszClassName	= names[0];
    winclass.hIconSm        = LoadIcon(NULL, IDI_APPLICATION);
    
    // Second window
    winclass2 = winclass;
    winclass2.lpszClassName = names[1];
    
    // register the window classes
    if (!RegisterClassEx(&winclass) || !RegisterClassEx(&winclass2))
    	return(0);
    
    // create the first window
    if (!(hwnd = CreateWindowEx(0,                  // extended style
                                names[0],     // class
    						    "Window 1 Based on WINCLASS1", // title
    						    WS_OVERLAPPEDWINDOW | WS_VISIBLE,
    					 	    0,0,	    // initial x,y
    						    400,400,  // initial width, height
    						    NULL,	    // handle to parent 
    						    NULL,	    // handle to menu
    						    hinstance,// instance of this application
    						    NULL)))	// extra creation parms
    return(0);
    
    // create the second window
    if (!(hwnd2 = CreateWindowEx(0,                  // extended style
                                names[1],     // class
    						    "Window 2 Based on WINCLASS2", // title
    						    WS_OVERLAPPEDWINDOW | WS_VISIBLE,
    					 	    100,100,  // initial x,y
    						    400,400,  // initial width, height
    						    NULL,	  // handle to parent 
    						    NULL,	  // handle to menu
    						    hinstance,// instance of this application
    						    NULL)))	// extra creation parms
    return(0);
    
    // enter main event loop, but this time we use PeekMessage()
    // instead of GetMessage() to retrieve messages
    while(true)
    {
        // test if there is a message in queue, if so get it
    	if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
 	    { 
    	   // test if this is a quit
           if (msg.message == WM_QUIT)
               break;
    	
    	   // translate any accelerator keys
    	   TranslateMessage(&msg);
    
    	   // send the message to the window proc
    	   DispatchMessage(&msg);
  	    } // end if
        
        // main game processing goes here
    	
    } // end while
    
    // return to Windows like this
    return(msg.wParam);

} // end WinMain

///////////////////////////////////////////////////////////


* Ah.. the forum is messing up the code.
Alfred Reinold Baudisch[Game Development Student] [MAC lover] [Ruby, Ruby on Rails and PHP developer] [Twitter]
Advertisement
WM_DESTORY is PostQuitMessage()ing.

that means when one of those windows gets closed, your app shuts down.

fix that.
I've added a windows counter. So, when there is no windows anymore (winCount = 0), WM_DESTROY calls PostQuitMessage(0);

Is there other way to do this? Or this is the solution?

Here it is:
#define WIN32_LEAN_AND_MEAN  // just say no to MFC#include <windows.h>   // include all the windows headers#include <windowsx.h>  // include useful macros// GLOBALS ////////////////////////////////////////////////// windows countingint winCount = 0;// FUNCTIONS //////////////////////////////////////////////LRESULT CALLBACK WindowProc(HWND hWnd,                             UINT Msg,                             WPARAM wParam,                             LPARAM lParam){    // this is the main message handler of the system    PAINTSTRUCT     ps;     // used in WM_PAINT    HDC             hdc;    // handle to a device context    // what is the message     switch(Msg)    {           case WM_CREATE:         {            winCount++;            // do initialization stuff here            // return success            return(0);        } break;        case WM_PAINT:         {            // simply validate the window            hdc = BeginPaint(hWnd,&ps);              // you would do all your painting here            EndPaint(hWnd,&ps);            // return success            return(0);        } break;        case WM_DESTROY:         {            winCount--;                        // No windows left, so send WM_QUIT            if(!winCount)            {                // kill the application, this sends a WM_QUIT message                 PostQuitMessage(0);            }                // return success            return(0);        } break;        default:            break;        } // end switch    // process any messages that we didn't take care of     return (DefWindowProc(hWnd, Msg, wParam, lParam));} // end WinProcint WINAPI WinMain( HINSTANCE hInstance,                    HINSTANCE hPrevInstance,                    LPSTR lpCmdLine,                    int nCmdShow){    const char* names[] = { "WINCLASS1", "WINCLASS2" };    WNDCLASSEX winclass, winclass2; // this will hold the class we create    HWND       hWnd, hWnd2;     // generic window handle    MSG        Msg;      // generic message    // first fill in the window class stucture    winclass.cbSize         = sizeof(WNDCLASSEX);    winclass.style          = CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW;    winclass.lpfnWndProc    = WindowProc;    winclass.cbClsExtra     = 0;    winclass.cbWndExtra     = 0;    winclass.hInstance      = hInstance;    winclass.hIcon          = LoadIcon(NULL, IDI_APPLICATION);    winclass.hCursor        = LoadCursor(NULL, IDC_ARROW);    winclass.hbrBackground  = (HBRUSH)GetStockObject(BLACK_BRUSH);    winclass.lpszMenuName   = NULL;    winclass.lpszClassName  = names[0];    winclass.hIconSm        = LoadIcon(NULL, IDI_APPLICATION);        winclass2 =  winclass;    winclass2.lpszClassName = names[1];        // register the window class    if (!RegisterClassEx(&winclass) || !RegisterClassEx(&winclass2))        return(0);    // create the first window    if (!(hWnd = CreateWindowEx(0,                  // extended style                                names[0],     // class                                "Window 1 Based on WINCLASS1", // title                                WS_OVERLAPPEDWINDOW | WS_VISIBLE,                                0,0,        // initial x,y                                400,400,  // initial width, height                                NULL,       // handle to parent                                 NULL,       // handle to menu                                hInstance,// instance of this application                                NULL))) // extra creation parms    return(0);    // create the second window    if (!(hWnd2 = CreateWindowEx(0,                  // extended style                                names[1],     // class                                "Window 2 Based on WINCLASS2", // title                                WS_OVERLAPPEDWINDOW | WS_VISIBLE,                                100,100,  // initial x,y                                400,400,  // initial width, height                                NULL,     // handle to parent                                 NULL,     // handle to menu                                hInstance,// instance of this application                                NULL))) // extra creation parms    return(0);    // enter main event loop, but this time we use PeekMessage()    // instead of GetMessage() to retrieve messages    while(true)    {        // test if there is a message in queue, if so get it        if (PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE))        {             // test if this is a quit            if (Msg.message == WM_QUIT)            {                break;            }                    // translate any accelerator keys            TranslateMessage(&Msg);            // send the message to the window proc            DispatchMessage(&Msg);        } // end if                // main game processing goes here            } // end while    // return to Windows like this    return(Msg.wParam);} // end WinMain
Alfred Reinold Baudisch[Game Development Student] [MAC lover] [Ruby, Ruby on Rails and PHP developer] [Twitter]
Quote:Original post by Maquiavel
Is there other way to do this?
Yes. Give the two window classes separate window procedures. If they have the exact same definition, then you obviously need only one window class. If so, then move the code to terminate the application out of the window procedures and into the main loop.

Master window messaging.
here's a question for ya. Why are you
#define WIN32_LEAN_AND_MEAN

??

what does this do, i've never seen it. im sure it has nothing to do with your prob, but just curious.
Quote:Original post by AckPacket
here's a question for ya. Why are you
#define WIN32_LEAN_AND_MEAN

??

what does this do, i've never seen it. im sure it has nothing to do with your prob, but just curious.

by putting that before including "windows.h", it cuts out some of the stuff automatically included, reducing compile time. i just found the following quickly (so there may be more to it):

#ifndef WIN32_LEAN_AND_MEAN#include <cderr.h>#include <dde.h>#include <ddeml.h>#include <dlgs.h>#include <lzexpand.h>#include <mmsystem.h>#include <nb30.h>#include <rpc.h>#include <shellapi.h>#include <winperf.h>#include <winsock.h>...#endif /* WIN32_LEAN_AND_MEAN */


if you do need some of those headers (i.e. winsock.h for networking) you can still manually include them.
--- krez ([email="krez_AT_optonline_DOT_net"]krez_AT_optonline_DOT_net[/email])
Quote:Original post by AckPacket
#define WIN32_LEAN_AND_MEAN
what does this do, i've never seen it.


I'll tell you what id does, at bloody annoys me ;). All my new projects start with that. It restricts certain headers that are classed as 'advanced stuff'. Presumably to lower compile time. PCH surly makes this redundant and 99% of the time I need something which it restricts. And i never remeber to remove it till my app fails to compile!

In fact whilst im moaning I may as well ask, im using VC6 is there anyway to edit the "Win32 App" wizard generator?Ive never found the source code anywhere. Do i have to create my own from scratch?

This topic is closed to new replies.

Advertisement