Thread: Window appears in a flash! But also disappears as fast...

  1. #1
    Student legit's Avatar
    Join Date
    Aug 2008
    Location
    UK -> Newcastle
    Posts
    156

    Window appears in a flash! But also disappears as fast...

    Hey, so I got round to making a non-compile-time error framework for a window to hold my DX applications later on in my programming life... BUT I've came across a problem, as most coders do, life isn't life without problems. :P Anyways, I build and debug my application, but it disappears as soon as it has executed... I've came across this in pure C++ programming, but never in Win32... I suppose I'll post the relevant code now:

    DXEngine.h
    Code:
    #include "D3D.h"
    
    #ifndef DXENGINE_H /*Inclusion guards*/
    #define DXENGINE_H
    
    namespace DXE /*Create a namespace to hold our functions and class*/
    {
    	LRESULT CALLBACK lcWindowProc(HWND, UINT, WPARAM, LPARAM); /*Function to handle events that our window recieves*/
    
    	class DXEngine: public D3D
    	{
    	public:
    	    DXEngine(); /*Constructor*/
    	    void vSetWindowCharacteristics(HINSTANCE); /*Function to fill out windows class parameters*/
    	    bool bCreateWindow(HINSTANCE); /*Function for creating the window*/
    	    void vShowWindow(int); /*Function for showing the window*/
    	    void vUpdateWindow(); /*Function for updating the window*/
    	    bool bRegisterClass(); /*Function to register the window class*/
    	    int iRunMessageLoop(); /*Function to wrap the message loop*/
    	private:
    	    WNDCLASSEX m_WndClassEx; /*Private member variable*/
    	};
    }
    
    #endif /*DXENGINE_H*/
    All of the above functions were defined in a separate source file.

    WinMain.cpp
    Code:
    #include "DXEngine.h"
    
    int WINAPI WinMain(HINSTANCE TemphInstance, /*Window instance*/
    				   HINSTANCE hPrevIntance, /*Isn't used in Win32 programming*/
    				   LPSTR CmdLine,
    				   int nShowCmd)
    {
    	DXE::DXEngine EngineInstance;
    
    	EngineInstance.vSetWindowCharacteristics(TemphInstance); /*Set the windows characteristics*/
    	EngineInstance.bRegisterClass(); /*Register the windows class*/
    	EngineInstance.bCreateWindow(TemphInstance); /*Create the window*/
    	EngineInstance.vShowWindow(nShowCmd); /*Show the window*/
    	EngineInstance.vUpdateWindow(); /*Update the window*/
    
    	return EngineInstance.iRunMessageLoop();
    }
    I'm not sure if I need to post the definition of my class, so I'll leave it out for now. Although holla if I need to. :P
    MSDN <- Programmers Haven!

  2. #2
    int x = *((int *) NULL); Cactus_Hugger's Avatar
    Join Date
    Jul 2003
    Location
    Banks of the River Styx
    Posts
    902
    Iam gonna holla.

    All that you've shown us is 6 function calls, and a call to a constructor, but no lines of code that actually do anything... Post Your Code.

    And those member function names. Ew. Hungarian was bad on variables... don't abuse the functions too...
    long time; /* know C? */
    Unprecedented performance: Nothing ever ran this slow before.
    Any sufficiently advanced bug is indistinguishable from a feature.
    Real Programmers confuse Halloween and Christmas, because dec 25 == oct 31.
    The best way to accelerate an IBM is at 9.8 m/s/s.
    recursion (re - cur' - zhun) n. 1. (see recursion)

  3. #3
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    You have not shown your main message loop which is where I suspect the problem is.

  4. #4
    Student legit's Avatar
    Join Date
    Aug 2008
    Location
    UK -> Newcastle
    Posts
    156
    Quote Originally Posted by Bubba View Post
    You have not shown your main message loop which is where I suspect the problem is.
    I've retrieved my message loop for y'all! Here it is:

    DXEngine.cpp
    Code:
    ... /*Some Definitions here*/
    
    int DXE::DXEngine::iRunMessageLoop() /*Function Definition*/
    {
    	MSG TempMessage; /*Create a temporary instance of the MSG struct*/
    	ZeroMemory(&TempMessage, /*Where to start filling with zero's*/
    		sizeof(MSG)); /*The size of the block of memory to fill with zero's*/
    
    	while(PeekMessage(&TempMessage, /*Message instance with the required information*/
    		0, /*Window handle, if NULL, then retrieve all messages belonging to the current thread*/
    		0, /*Specifies the first value in the message queue to be examined, if NULL, then return all available messages*/
    		0, /*Specifies the last value in the message queue to be examined, if NULL, then return all available messages*/
    		PM_REMOVE)) /*Remove the messages after they have been processed*/
    	{
    		TranslateMessage(&TempMessage); /*Function to translate virtual key messages into character messages*/
    		DispatchMessage(&TempMessage); /*Function to dispatch a message to the windows procedure*/
    	}
    
    	return TempMessage.wParam;
    }
    
    ... /*Some more definitions here*/
    MSDN <- Programmers Haven!

  5. #5
    train spotter
    Join Date
    Aug 2001
    Location
    near a computer
    Posts
    3,868
    Can we see the main callback?
    If the window flashes then it has been created and shown.
    Could be an error in the callback causes it to close immediately.

    Also I did not think you could use non static methods as callbacks as the 'this' pointer was passed invisibly (but expect the IDE to throw an error C2664).
    "Man alone suffers so excruciatingly in the world that he was compelled to invent laughter."
    Friedrich Nietzsche

    "I spent a lot of my money on booze, birds and fast cars......the rest I squandered."
    George Best

    "If you are going through hell....keep going."
    Winston Churchill

  6. #6
    Student legit's Avatar
    Join Date
    Aug 2008
    Location
    UK -> Newcastle
    Posts
    156
    Quote Originally Posted by novacain View Post
    Can we see the main callback?
    You sure can:

    DXEngine.cpp
    Code:
    LRESULT CALLBACK DXE::lcWindowProc(HWND hwnd, /*Handle to the window*/
    				 UINT iTempMessage, /*Specifies the message*/
    				 WPARAM wParam, /*Specifies additional message info*/
    				 LPARAM lParam) /*Specifies additional message info*/
    {
    	switch(iTempMessage) /*Pass in the message into the a switch statement*/
    	{
    	case WM_DESTROY: /*If the destroy message is recieved*/
    		PostQuitMessage(0); /*Post the value "0" as an exit code*/
    		break; /*Return an error value to the application*/
    	}
    
    	return DefWindowProc(hwnd, /*Handle to the window*/
    		iTempMessage, /*Message variable*/
    		wParam, /*Specifies any additional message info*/
    		lParam); /*Specifies any additional message info*/
    }
    MSDN <- Programmers Haven!

  7. #7
    train spotter
    Join Date
    Aug 2001
    Location
    near a computer
    Posts
    3,868
    Quote Originally Posted by novacain View Post
    Also I did not think you could use non static methods as callbacks as the 'this' pointer was passed invisibly (but expect the IDE to throw an error C2664).
    Are you using an MS IDE (Visual Studio)?

    I would do some research on non static member functions as callbacks (CALLBACK == PASCAL == __stdcall)
    "Man alone suffers so excruciatingly in the world that he was compelled to invent laughter."
    Friedrich Nietzsche

    "I spent a lot of my money on booze, birds and fast cars......the rest I squandered."
    George Best

    "If you are going through hell....keep going."
    Winston Churchill

  8. #8
    Student legit's Avatar
    Join Date
    Aug 2008
    Location
    UK -> Newcastle
    Posts
    156
    Ahh thanks for that. I did a few changes, and removed my namespace. My callback function is now static. Although the problem isn't fixed.
    MSDN <- Programmers Haven!

  9. #9
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Here is your problem:

    Code:
    int DXE::DXEngine::iRunMessageLoop() /*Function Definition*/
    {
    	MSG TempMessage; /*Create a temporary instance of the MSG struct*/
    	ZeroMemory(&TempMessage, /*Where to start filling with zero's*/
    		sizeof(MSG)); /*The size of the block of memory to fill with zero's*/
    
    	while(PeekMessage(&TempMessage, /*Message instance with the required information*/
    		0, /*Window handle, if NULL, then retrieve all messages belonging to the current thread*/
    		0, /*Specifies the first value in the message queue to be examined, if NULL, then return all available messages*/
    		0, /*Specifies the last value in the message queue to be examined, if NULL, then return all available messages*/
    		PM_REMOVE)) /*Remove the messages after they have been processed*/
    	{
    		TranslateMessage(&TempMessage); /*Function to translate virtual key messages into character messages*/
    		DispatchMessage(&TempMessage); /*Function to dispatch a message to the windows procedure*/
    	}
    
    	return TempMessage.wParam;
    }
    You should not return from this function until your game is over.


    Code:
    void App::EnterMessageLoop()
    {
        MSG msg;
        float timeDelta = 0.0f;
        LARGE_INTEGER freq;
        LARGE_INTEGER nowTime;
        LARGE_INTEGER lastTime;
    
        QueryPerformanceFrequency(&freq);
        QueryPerformanceCounter(&lastTime);
        m_isRunning = true;
        while (m_isRunning)
        {
            if(::PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
            {
                ::TranslateMessage(&msg);
                ::DispatchMessage(&msg);
            }
    
            QueryPerformanceCounter(&nowTime);
            float timeDelta = (nowTime.QuadPart - lastTime.QuadPart) * (1.0f / freq.QuadPart);
            
            Update(timeDelta);
            Render();
            
            lastTime = nowTime;
        }
    }
    The code I just posted will keep the loop running until m_isRunning is false. m_isRunning would be set by the user exiting the game. After this loop returns you should then allow the game to cleanup. Here is my main function:

    Code:
    SomeGameApp g_App;
    
    int APIENTRY WinMain(HINSTANCE hInstance,
                           HINSTANCE hPrevInstance,
                           LPTSTR    lpCmdLine,
                           int       nCmdShow)
    {
        unsigned int screenWidth = 800;
        unsigned int screenHeight = 600;
        bool windowed = true;
        
        g_App.InitApp(screenWidth,screenHeight,true,0,windowed);
        bool result = g_App.Setup();
        if (!result)
        {
            ::MessageBox(0,"Application setup FAILED - exiting.","ERROR",MB_OK | MB_ICONEXCLAMATION);
        }
        else
        {
            g_App.EnterMessageLoop();
            g_App.Cleanup();
        }
    
        return 0;
    }
    SomeGameApp is derived from App which has 4 pure virtual functions. Setup(), Render(), Update(float timeDelta), and Cleanup(). EnterMessageLoop() is part of the base class. Base class InitApp() will setup Direct3D or whatever rendering API you are using. InitApp() can create it's own window or it can simply use an HWND that is passed to it. This allows the rendering engine to be used inside of an editor and the editor then passes the HWND to the engine.

    Note that the window width, height is hard-coded and would not be in a release. At this point you could read in the height/width from XML or and ini file or some type of data file that had the necessary data in it.
    Last edited by VirtualAce; 07-04-2009 at 10:43 AM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. C or C++
    By AcerN30 in forum Game Programming
    Replies: 41
    Last Post: 05-30-2008, 06:57 PM
  2. Just starting Windows Programming, School me!
    By Shamino in forum Windows Programming
    Replies: 17
    Last Post: 02-22-2008, 08:14 AM
  3. 6 measly errors
    By beene in forum Game Programming
    Replies: 11
    Last Post: 11-14-2006, 11:06 AM
  4. Replies: 10
    Last Post: 01-14-2005, 01:07 PM
  5. 'Hello World' - window disappears as soon as I run.
    By GandyCobra in forum C Programming
    Replies: 16
    Last Post: 09-15-2004, 11:38 AM