App intermittantly fails to quit

Started by
4 comments, last by AngleWyrm 16 years, 1 month ago
I've borked my app, and don't know where to start looking. The app closes from windowed mode every time, but from fullscreen it sometimes does a...partial shutdown. The screen goes black, and I have to hit the escape key several times to get it to shut down. (escape being assigned in the message handler). It happened some time when I created a Painter class to handle windows and DirectX functions. Anyone run into this kind of problem before?
//--------------------------------------------------------------------------------------------------
// Painter class implementation
//--------------------------------------------------------------------------------------------------
#include "painter.hpp"
#include <debug.hpp>
#include <stdio.h>          // sprintf

/* TODO: New problem--end program intermittantly fails */
void painter_class::reset_screen(){
    DBG_MSG("Attempting to reset screen");

    // release resources
    my_font->Release(); /* TODO: might move to a gui object d'tor/asset manager */

    // do screen reset
    screen->Reset(&screen_parameters);

    // recreate released resources
    D3DXCreateFont( screen, 20, 0, FW_BOLD, 0, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
        DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, TEXT("Arial"), &my_font );

};

HRESULT painter_class::render(const float elapsed_seconds)
{
    if(screen == NULL){
        DBG_MSG("No screen available");
        return 1;
    } // else have screen

    //----------------------------------------------------------------------------------------------
    // Handle alt-tab/lost device
    //----------------------------------------------------------------------------------------------
    static HRESULT result;
    result = screen->TestCooperativeLevel();
    switch(result){
        case D3D_OK:
            DBG_MSG("device OK");
            break;

        case D3DERR_DEVICELOST:
            DBG_MSG("device lost"); // alt-tabbed out
            Sleep(100);
            return 1;
        case D3DERR_DEVICENOTRESET: // just returned from alt-tab
            DBG_MSG("device not reset");
            Sleep(1);
            reset_screen();
            return 1;
        case D3DERR_DRIVERINTERNALERROR:
            DBG_MSG("device driver error");
            return 1;
        default:
            DBG_MSG("unknown DirectX error: " << result);
            return 1;
    }

    //----------------------------------------------------------------------------------------------
    // Render the scene
    //----------------------------------------------------------------------------------------------
    DBG_MSG("Begin rendering scene");

    screen->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 8, 16), 1.0f, 0);

    // Begin the scene
    screen->BeginScene();

    /* TODO: These resources should belong in a resource manager */
    // Create a colour for the text - in this case blue
    static D3DCOLOR fontColor = D3DCOLOR_ARGB(255,0,0,255);
    // Create a rectangle to indicate where on the screen it should be drawn
    static RECT rct = {100, 100, 700, 150}; // left,top,right,bottom

    // Draw some text
    static char test[150];
    sprintf(test,"%1.3f mSec/frame; %2.1f frames/sec", 1000 * elapsed_seconds, 1/elapsed_seconds);
    my_font->DrawText(NULL, test, -1, &rct, 0, fontColor );

    DBG_MSG("End rendering, present scene");
    screen->EndScene();
    return screen->Present(NULL, NULL, NULL, NULL); /* TODO: use swapchains to allow NOWAIT/STILLDRAWING */
};

painter_class::painter_class(HINSTANCE instance, const char* app_name, int display_mode, lua_script& settings)
{
    //----------------------------------------------------------------------------------------------
    // Create DirectX interface
    //----------------------------------------------------------------------------------------------
    dx = Direct3DCreate9(D3D_SDK_VERSION);
    if( dx == NULL){
        DBG_MSG("DirectX failed to initialize");
        error = -1;
        return;
    }
    else{
        DBG_MSG("DirectX initialized");
    }

    //----------------------------------------------------------------------------------------------
    // Create main window
    //----------------------------------------------------------------------------------------------
    fullscreen = settings.get_bool("video","fullscreen"); // get initial state from settings file

    dx->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &desktop_display_settings );

    main_window = CreateWindowEx(0, app_name, "Dad Gum Borked App",
           (fullscreen? WS_POPUP|WS_EX_TOPMOST : WS_OVERLAPPEDWINDOW) | WS_VISIBLE,
           0,0,
           (fullscreen? desktop_display_settings.Width  : settings.get_value("video","width") ),
           (fullscreen? desktop_display_settings.Height : settings.get_value("video","height") ),
           HWND_DESKTOP,
           NULL,           /* TODO: Menu */
           instance,
           NULL );

    if(main_window == 0){
        DBG_MSG( "CreateWindowEx() failed" );
        error = -1;
        return;
    }
    else{
        DBG_MSG("Main Window created");
    }

    //----------------------------------------------------------------------------------------------
    // Create DirectX screen for main window
    //----------------------------------------------------------------------------------------------
    ZeroMemory( &screen_parameters, sizeof(screen_parameters) );

    screen_parameters.BackBufferWidth  = desktop_display_settings.Width;
    screen_parameters.BackBufferHeight = desktop_display_settings.Height;
    screen_parameters.BackBufferFormat = desktop_display_settings.Format;
    screen_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;

    //screen_parameters.FullScreen_RefreshRateInHz = settings.get_value("video", "fps");
    //screen_parameters.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;

    screen_parameters.Windowed = !fullscreen;
    screen_parameters.hDeviceWindow = main_window;

    dx->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, main_window,
        D3DCREATE_HARDWARE_VERTEXPROCESSING, &screen_parameters, &screen );

    if(screen == NULL){
        DBG_MSG("DirectX failed to create screen");
        error = -1;
        return;
    }
    else{
        DBG_MSG("DirectX screen created");
    }

    // Create other resources
    /* TODO: Move to a Fragile-Resources manager */
    D3DXCreateFont( screen, 30, 15, FW_BOLD, 0, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
        DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, TEXT("Arial"), &my_font );

    error = 0;

    ShowWindow(main_window, display_mode);
};

painter_class::~painter_class()
{
    if(my_font != NULL) my_font->Release();
    if(screen != NULL)  screen->Release();
    if(dx != NULL)      dx->Release();
    DBG_MSG("painter resources released");
};


The message handler is very dull, and hasn't changed.
//--------------------------------------------------------------------------------------------------
// Message handler
//--------------------------------------------------------------------------------------------------
LRESULT CALLBACK message_handler( HWND current_window, UINT message_id,
    WPARAM wParam, LPARAM lParam)
{
    switch (message_id)
    {
        case WM_DESTROY:
            PostQuitMessage(0); // send WM_QUIT to message queue with wParam=0
            break;

        case WM_KEYUP:
          switch (wParam)
          {
            case VK_ESCAPE:
              PostQuitMessage(0); // Escape key pressed -> exit
              break;
          }
          break;

        default:
            return DefWindowProc(current_window, message_id, wParam, lParam);
    }
    return 0;
}



--"I'm not at home right now, but" = lights on, but no ones home
Advertisement
In which way do you close the app that causes it to hang? Are you just hitting escape, or doing something else?
From fullscreen mode, I'm hitting escape, as there are no menus or buttons available yet. It fails to close quite often at that time.

From windowed mode, hitting either escape or clicking the close box on the menu shuts it down every time.
--"I'm not at home right now, but" = lights on, but no ones home
Hmmm...have you used the debugger to see if there's any particular function you're getting "stuck" inside of? You may want to trace through your app after you post that quit message, see what's taking it so long.
I ran into exactly the same problem at one time and can't remember the exact fix. However, try changing WM_DESTROY to WM_CLOSE and see if that resolves the problem.

Add a DestroyWindow(hwnd) for your app window in the app's destructor.


[Edited by - Buckeye on March 7, 2008 7:35:24 AM]

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

Hot Damn, that did it!

Thanks man, maybe it was something to do with the windows deallocation sequence.
--"I'm not at home right now, but" = lights on, but no ones home

This topic is closed to new replies.

Advertisement