Exiting Fullscreen D3D8 App Bug

Started by
8 comments, last by SHilbert 22 years, 8 months ago
Well, I don''t know how long it''s been since I posted an actual question on these forums, but here goes... Okay, I''m creating a D3D8 device fullscreen. Everything succeeds, etc. like normal; in fact, my code is about as generic as you could get. However, the problem is that when you exit, Microsoft Visual Studio 6 (which was maximized before running) is now non-maximized, approximately the size of the resolution I had switched to for fullscreen. Other than that, everything works perfectly. Here''s some code that exemplifies the problem... aside from the C-ish use of a global structure and such, it''s pretty vanilla and should expose about everything one would need to track down this bug
  
//-----------------------------------------------------------------------------

// File: Main.cpp

//

// Desc: Main core functions

//

// Copyright (C) 2001 Scott Hilbert (SHilbert@gdnmail.net)

//-----------------------------------------------------------------------------

#include "Globals.h"
#include "IniFile.h"

//-----------------------------------------------------------------------------

// Globals

//-----------------------------------------------------------------------------

CLIENT_GLOBALS * g_pCG = NULL;
char g_szError[256] = "Unspecified Error Occurred!";

//-----------------------------------------------------------------------------

// Name: MsgProc()

// Desc: The window''s message handler

//-----------------------------------------------------------------------------

LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
    switch( msg )
    {
	case WM_SETCURSOR:
		if(LOWORD(lParam) == HTCLIENT)
			SetCursor(NULL);
		else
			SetCursor(LoadCursor(NULL, IDC_ARROW));
		return 0;

    case WM_DESTROY:
        PostQuitMessage( 0 );
        return 0;
    }

    return DefWindowProc( hWnd, msg, wParam, lParam );
}

//-----------------------------------------------------------------------------

// Name: Init()

// Desc: Inits everything

//-----------------------------------------------------------------------------

HRESULT Init()
{
	//-----------------------------------------------------------------------------

	// REGISTRY LOADING

	//-----------------------------------------------------------------------------


	// Load reg settings

	int nWidth, nHeight, nBPP;
	BOOL bWindowed;
	char szWindowCaption[256] = "";
	char szWindowCls[256] = "";

	{
		CIniFile Settings;
		if(FAILED(Settings.Load("Client.ini")))
		{
			strcpy(g_szError, "Couldn''t load registry settings!");
			return E_FAIL;
		}
		nWidth		= Settings.GetInt ("Display", "Width");
		nHeight		= Settings.GetInt ("Display", "Height");
		nBPP		= Settings.GetInt ("Display", "BPP");
		bWindowed	= Settings.GetBool("Display", "Windowed");

		Settings.GetString("Window", "Caption", szWindowCaption, 256);
		Settings.GetString("Window", "Class", szWindowCls, 256);
	}
	
	//-----------------------------------------------------------------------------

	// GLOBAL SETUP

	//-----------------------------------------------------------------------------


	// Allocate globals

	g_pCG = new CLIENT_GLOBALS;
	if(!g_pCG)
	{
		strcpy(g_szError, "Couldn''t create client global struct!");
		return E_FAIL;
	}
	ZeroMemory(g_pCG, sizeof(CLIENT_GLOBALS));

	//-----------------------------------------------------------------------------

	// WINDOW CREATION

	//-----------------------------------------------------------------------------


    // Register the window class

	WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L,
                      GetModuleHandle(NULL), NULL, NULL, NULL, NULL,
                      szWindowCls, NULL };
	memcpy(&g_pCG->wc, &wc, sizeof(wc));
    if(!RegisterClassEx(&g_pCG->wc))
	{
		strcpy(g_szError, "Couldn''t register window class!");
		return E_FAIL;
	}

	DWORD dwStyle;	// Window style


	// If windowed

	if(bWindowed)
		// Adjust settings for a windowed renderer

		dwStyle = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX;
	else
		// Adjust settings for a fullscreen renderer

		dwStyle = WS_POPUP | WS_SYSMENU;

    // Create the application''s window

    g_pCG->hWnd = CreateWindow(szWindowCls, szWindowCaption,
                              dwStyle, 0, 0, nWidth, nHeight,
                              GetDesktopWindow(), NULL, wc.hInstance, NULL );


	if(!g_pCG->hWnd)
	{
		strcpy(g_szError, "Couldn''t create main window!");
		return E_FAIL;
	}

	// Resize the window to make sure the client area is really the size we requested.

	// Also position the window in the middle of the screen.

	if(bWindowed)
	{
		RECT rcClient, rcWindow;
		GetClientRect(g_pCG->hWnd, &rcClient);
		GetWindowRect(g_pCG->hWnd, &rcWindow);
		int W = nWidth + ((rcWindow.right-rcWindow.left)-rcClient.right);
		int H = nHeight + ((rcWindow.bottom-rcWindow.top)-rcClient.bottom);
		int ScrW = GetSystemMetrics(SM_CXSCREEN);
		int ScrH = GetSystemMetrics(SM_CYSCREEN);
		SetWindowPos(g_pCG->hWnd, NULL, ScrW/2 - W/2, ScrH/2 - H/2, W, H, SWP_NOZORDER);
	}

	// Now, show this window

    ShowWindow(g_pCG->hWnd, SW_SHOWDEFAULT );
    UpdateWindow(g_pCG->hWnd);
	SetFocus(g_pCG->hWnd);

	//-----------------------------------------------------------------------------

	// D3D INITIALIZATION

	//-----------------------------------------------------------------------------


	// Try to create D3D

	if(NULL == (g_pCG->pD3D = Direct3DCreate8(D3D_SDK_VERSION)))
	{
		strcpy(g_szError, "Couldn''t create D3D8 interface!");
		return E_FAIL;
	}

	// Get the current display mode

	D3DDISPLAYMODE d3ddm;
	if(FAILED(g_pCG->pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm)))
	{
		strcpy(g_szError, "Couldn''t retrieve current display mode via D3D8!");
		return E_FAIL;
	}

	// Set up the D3DPRESENT_PARAMETERS struct for use.

	// It tells D3D what device settings we want.

	D3DPRESENT_PARAMETERS d3dpp; 
	ZeroMemory( &d3dpp, sizeof(d3dpp) );
	d3dpp.Windowed   = bWindowed;
	d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
	d3dpp.hDeviceWindow = g_pCG->hWnd;

	// If windowed

	if(bWindowed)
	{
		d3dpp.BackBufferFormat = d3ddm.Format;
	}
	else
	{
		if(nBPP == 16)
			d3dpp.BackBufferFormat	= D3DFMT_R5G6B5;
		else if(nBPP == 24)
			d3dpp.BackBufferFormat	= D3DFMT_R8G8B8;
		else if(nBPP == 32)
			d3dpp.BackBufferFormat	= D3DFMT_X8R8G8B8;
		else
		{
			strcpy(g_szError, "Unrecognized bit depth!");
			return E_FAIL;	// stupid parameter

		}

		d3dpp.BackBufferWidth	= nWidth;
		d3dpp.BackBufferHeight	= nHeight;
	}

    // Create the D3DDevice

    if(FAILED(g_pCG->pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, g_pCG->hWnd,
                                      D3DCREATE_SOFTWARE_VERTEXPROCESSING,
                                      &d3dpp, &g_pCG->pd3dDevice)))
    {
		strcpy(g_szError, "Couldn''t create D3D8 Device!");
        return E_FAIL;
    }

    return S_OK;
}

//-----------------------------------------------------------------------------

// Name: Cleanup()

// Desc: Releases all previously initialized objects

//-----------------------------------------------------------------------------

VOID Cleanup()
{
	if(g_pCG)
	{
		// Destroy D3D

		SafeRelease(g_pCG->pd3dDevice);
		SafeRelease(g_pCG->pD3D);

		// Unregister the window class

		UnregisterClass(g_pCG->wc.lpszClassName, GetModuleHandle(NULL));
	}

	SafeDelete(g_pCG);
}

//-----------------------------------------------------------------------------

// Name: WinMain()

// Desc: The application''s entry point

//-----------------------------------------------------------------------------

INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT )
{
    // Initialize Direct3D

    if(SUCCEEDED(Init()))
    {
        // Enter the message loop

        MSG msg;
        ZeroMemory( &msg, sizeof(msg) );
        while( msg.message!=WM_QUIT )
        {
            if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) )
            {
                TranslateMessage( &msg );
                DispatchMessage( &msg );
            }
            else
			{
				g_pCG->pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,255), 1, 0);
				g_pCG->pd3dDevice->Present(NULL, NULL, NULL, NULL);
			}
        }
    }
	else
		MessageBox(NULL, g_szError, "Error", MB_OK | MB_ICONEXCLAMATION);

    // Clean up everything and exit the app

    Cleanup();
    return 0;
}
  
Gaah!
Advertisement
Gaah, copy and paste doesn''t seem to like me. It''s actually laid out much better than that

Gaah!
I get that problem all the time. Everytime I execute from MSVC++ to test my direct draw 6 application. I think that DirectX doesn''t return to Windows the new resolution size and so MSVC++ is still told that the old resolution is the correct one to be maximized in. Just a thought.

~Andrew Clark
i''m not sure of this, but i think the problem is in your message handler;

    //-----------------------------------------------------------------------------// Name: MsgProc()// Desc: The window''s message handler//-----------------------------------------------------------------------------LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam ){    switch( msg )    {	case WM_SETCURSOR:		if(LOWORD(lParam) == HTCLIENT)			SetCursor(NULL);		else			SetCursor(LoadCursor(NULL, IDC_ARROW));		return 0;    case WM_DESTROY:        PostQuitMessage( 0 );        return 0;    }    return DefWindowProc( hWnd, msg, wParam, lParam );}  


should be (i think):

  LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam){    switch(msg)    {                case WM_SETCURSOR:	if(LOWORD(lParam) == HTCLIENT)		SetCursor(NULL);	else		SetCursor(LoadCursor(NULL, IDC_ARROW));	return 0;        case WM_CLOSE:            DestroyWindow(hwnd);        break;        case WM_DESTROY:            PostQuitMessage(0);        break;        default:            return DefWindowProc(hwnd, msg, wParam, lParam);    }    return 0;}Greetz,Sephiroth The Third  
Sephiroth
Nah, that''s not it, because WM_DESTROY just breaks and drops out to the return 0; like before, and the default action for WM_CLOSE is to call DestroyWindow(...). I''m uninitializing everything right, I''ve been working with various versions of D3D for over 2 years It''s just that there''s something funny about this bug. The DX8 samples don''t cause this, though, but I haven''t been able to isolate why yet.

Gaah!
I''m not sure, but shouldn''t the cleanup function be call from inside the WM_DESTROY handler? IIRC dx has to unsubclass the window.

Bjørn.
We are boki. The rest is known.
I have also the same problem and dont know what causes it. I solved it not to maximize VC dev studio, but resize it to fit entire screen. Lol, it doesn''t solve the problem if it''s in my code, but at least devstudio doesn''t get small every time.
Boki: Darn, cleaning up in WM_DESTROY (or in WM_CLOSE or anything like that) doesn't seem to work either. But I'll look into it more. It seems so far that all of MS's samples clean up D3D in the WM_CLOSE handler, which may have something to do with it. I can't find many really big inconsitencies with how I init D3D, so hopefully that's it, although I haven't gotten it to give the results I want yet It seems, though, that when you ALT+TAB, MSVC is already resized, so perhaps it is something wrong with the initialization. Who knows

stefu: Well, luckily my code can run windowed so I don't have to worry about MSVC resizing, but I can't help but think there's something wrong with my code if it does that...

Gaah!

Edited by - SHilbert on August 2, 2001 7:45:34 PM
Hm, should have read your post more carefully. Anyway, I had this known problem, too, and IIRC it has been fixed with a vc sp or via a manual restore of the desktop res in the WM_CLOSE handler.

Bjørn.
We are boki. The rest is known.
Alright, I''m gonna install the latest VC++ service pack I can find and hope it fixes it

Gaah!

This topic is closed to new replies.

Advertisement