Sign in to follow this  
BrainlessDesigns

Toggling FullScreen - windowed mode

Recommended Posts

hi there, i've the problem, when i want to switch from fullscreen mode to windowed, my app hangs... when i switch, i release all directdraw stuff, primary surface, back buffer and so on. i use the same init method, but after that, nothing changes here's the code:
/*method:      init()
  parameters:  hWnd     -> main handle from window
               width    -> width of the primary surface
			   height   -> height of the primary surface
			   bpp      -> bits per pixel of the primary surface (color depth)
			   windowed -> flag for NO fullscreen mode
  returns:     0  -> BD_DirectDraw object successfully initialized
               >0 -> an error occured
  description: initializes the BD_DirectDraw object
*/
u8 BD_DirectDraw::init(const HWND hWnd,
					   const u16 width,
					   const u16 height,
					   const u32 bpp,
					   const u8 windowed)
{
	// copy parameters
	this->hWnd    = hWnd;
	displayWidth  = width;
	displayHeight = height;
	displayBPP    = bpp;
	isWindowed    = windowed;

	// initialize windows stuff
	hMenu           = GetMenu(hWnd);
	windowstyle     = GetWindowLong(hWnd,GWL_style);
	windowExstyle   = GetWindowLong(hWnd,GWL_EXstyle);
    GetWindowRect(hWnd,&windowBounds);
    GetClientRect(hWnd,&windowClient);
	MoveWindow(hWnd,
		       windowBounds.left,
		       windowBounds.top,
		       displayWidth +
			   windowBounds.right - windowBounds.left - windowClient.right,
			   displayHeight + 
			   windowBounds.bottom - windowBounds.top - windowClient.bottom,
			   TRUE);
    GetWindowRect(hWnd,&windowBounds);
    GetClientRect(hWnd,&windowClient);

	return ( restart() );
}

u8 BD_DirectDraw::restart()
{
	// build DirectDraw interface
	hr = DirectDrawCreateEx(NULL,
		                    (VOID**)&pDD,
							IID_IDirectDraw7,
							NULL);
	if(checkForErrors("DirectDrawCreateEx"))
		return 1;

	// set the cooperative level
	if(isWindowed)
	{
		// set DDSCL_NORMAL to use windowed mode
		hr = pDD->SetCooperativeLevel(hWnd,DDSCL_NORMAL);
		if(checkForErrors("SetCooperativeLevel windowed"))
			return 2;
	}
	else
	{
		// remove menu bar if exists
        SetWindowLong(hWnd,
			          GWL_style,
					  NULL);
        SetMenu(hWnd,NULL);

		MoveWindow(hWnd,
			       0,
			       0,
				   displayWidth,
			       displayHeight,
			       TRUE);
		
		// set the cooperative level for fullscreen mode
		hr = pDD->SetCooperativeLevel(hWnd,
			                          DDSCL_ALLOWMODEX |
									  DDSCL_FULLSCREEN | 
									  DDSCL_EXCLUSIVE  | 
									  DDSCL_ALLOWREBOOT);
		if(checkForErrors("SetCooperativeLevel"))
			return 2;

		// set the display mode
		hr = pDD->SetDisplayMode(displayWidth,
			                     displayHeight,
								 displayBPP,
								 0,
								 0);
		if(checkForErrors("SetDisplayMode"))
			return 3;
	}
	
	// clear DDSCAPS2 structure
	ZeroMemory(&ddscaps, sizeof(ddscaps));
	// clear DDSURFACEDESC2 structure
	ZeroMemory(&ddsd, sizeof(ddsd));
	ddsd.dwSize = sizeof(ddsd);

	if(isWindowed)
	{
		ddsd.dwFlags = DDSD_CAPS;
		ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
		ddsd.dwBackBufferCount = 0;
	}
	else
	{
		ddsd.dwFlags = DDSD_CAPS | 
			           DDSD_BACKBUFFERCOUNT;
		ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | 
			                  DDSCAPS_FLIP | 
							  DDSCAPS_COMPLEX;
		ddsd.dwBackBufferCount = 1;
	}
	//ddsd.ddpfPixelFormat.dwRGBBitCount = 8; 

	// create the primary surface
	hr = pDD->CreateSurface(&ddsd,
				            &pDDSPrimary,
							NULL);
	if(checkForErrors("Create primary surface"))
		return 4;

	// get the pixel format of the primary surface
	DDPIXELFORMAT ddpf;
	ZeroMemory(&ddpf,sizeof(ddpf));
	ddpf.dwSize = sizeof(ddpf);
	pDDSPrimary->GetPixelFormat(&ddpf);
	pixelFormat = ddpf.dwRGBBitCount;
	// only need a backbuffer for fullscreen modes
	if(isWindowed)
	{
		// must be windowed, so create a double buffer that will be blitted
		// rather than flipped as in full screen mode
		pDDSBack = createOffScreenSurface(displayWidth,displayHeight);
	}
	else
	{
		// query for the backbuffer i.e the secondary surface
		ddscaps.dwCaps = DDSCAPS_BACKBUFFER;

		hr = pDDSPrimary->GetAttachedSurface(&ddscaps,&pDDSBack);
		if(checkForErrors("init() Create back buffer"))
			return 5;
   }

	// create a palette only if 8bit mode
	if(displayBPP == 8)
	{
		// clear all palette entries
		ZeroMemory(palette,sizeof(palette));

		// made a pre-made "good" palette
		for(u16 i=0; i<256; i++)
		{
			palette[i].peRed   = (u8)i;
            palette[i].peGreen = (u8)i;
			palette[i].peBlue  = (u8)i;
			palette[i].peFlags = PC_NOCOLLAPSE;
			// use PC_NOCOLLAPSE | PC_RESERVED for animated palette	entries
		}

		// attach the palette, test for windowed mode
		if(isWindowed)
		{
			// Set the first and last 10 entries to match the system palette.
			for (u16 i=0; i < 10; i++)
			{
				palette[i].peFlags     = palette[i + 246].peFlags = PC_EXPLICIT;
				palette[i].peRed       = (u8)i;
				palette[i + 246].peRed = (u8)i +246;
			}

			// now create the palette object, but disable access to all 256 entries
			hr = pDD->CreatePalette(DDPCAPS_8BIT | DDPCAPS_INITIALIZE,
				                    (PALETTEENTRY *)palette,
									&pDDPal,
									NULL);
		}
		else
		{
			// in fullscreen mode, so simple create the palette with the default palette
			// and fill in all 256 entries
			hr = pDD->CreatePalette(DDPCAPS_8BIT | 
				                    DDPCAPS_INITIALIZE |
									DDPCAPS_ALLOW256,
                                    (PALETTEENTRY *)palette,
									&pDDPal,
									NULL);
		}
		
		if(checkForErrors("CreatePalette failed"))
			return 6;

		// now attach the palette to the primary surface
        hr = pDDSPrimary->SetPalette(pDDPal);
		if(checkForErrors("init() SetPalette failed"))
		{
			if(isWindowed)
				MessageBox(hWnd,
				           "Deskop Resolution not in 8-Bit Color Mode!",
						   NULL,
						   MB_OK);
			return 7;
		}
	}

	// clear out both primary and secondary surfaces
	if(isWindowed)
	{
		// only clear backbuffer
		clearSurface(BACK_BUFFER);
	}
	else
	{
		// fullscreen, simply clear everything
		clearSurface(PRIMARY_SURFACE);
		clearSurface(BACK_BUFFER);
	}

	// setup backbuffer clipper always
	if((pClipperBack = attachClipper(pDDSBack,1,&windowClient)) == NULL)
		return 8;

	// set up windowed mode clipper
	if(isWindowed)
	{
		// set windowed clipper
		hr = pDD->CreateClipper(0,&pClipperPrimary,NULL);
		if(checkForErrors("CreateClipper failed"))
			return 9;

		hr = pClipperPrimary->SetHWnd(0,hWnd);
		if(checkForErrors("SetHWnd failed"))
			return 10;

		hr = pDDSPrimary->SetClipper(pClipperPrimary);
		if(checkForErrors("SetClipper failed"))
			return 11;
	}

	return 0;
}

/*method:      toggleFullscreen()
  parameters:  none
  returns:     nothing
  description: this method switches between windowed and fullscreen mode
*/
u8 BD_DirectDraw::toggleFullscreen()
{
    // Toggle the windowed state
	isWindowed = !isWindowed;
	shutDown();
/* !!! IDirectDraw7::RestoreAllSurfaces !!! */

	return ( restart() );
}

/*method:      shutDown()
  parameters:  none
  returns:     nothing
  description: releases all DirectDraw stuff
*/
void BD_DirectDraw::shutDown()
{
	// release the clipper for the primary surface
	if(pClipperPrimary)
	{
		pClipperPrimary->Release();
		pClipperPrimary = NULL;
	}

	// release the clipper for the back buffer
	if(pClipperBack)
	{
		pClipperBack->Release();
		pClipperBack = NULL;
	}
	
	// release palette
	if(pDDPal)
	{
		pDDPal->Release();
		pDDPal = NULL;
	}

	// release back buffer
	if(pDDSBack)
	{
		pDDSBack->Release();
		pDDSBack = NULL;
	}

	// release primary surface
	if(pDDSPrimary)
	{
		pDDSPrimary->Release();
		pDDSPrimary = NULL;
	}

	// release DirectDraw7 interface
	if(pDD)
	{
		pDD->Release();
		pDD = NULL;
	}
}

anybody an idea, why toggling doesn't work?! thx 4 ur fast answers [Edited by - Coder on October 23, 2005 4:39:41 PM]

Share this post


Link to post
Share on other sites
try using the Definition of CDS_FULLSCREEN with a DEVMODE, i learnt this in OpenGL you can find it in the "Setting up a window in OGL" tutorial on NeHe just skip past all the OGL stuff and look towards the rest of it.

EDIT: use the source tags to enclose your code like:



\ = [ | = ] // because i cant display the tags

\source|
code goes here
\/source| just replace \ and | with the brackets []



Share this post


Link to post
Share on other sites
just a note

isWindowed = !isWindowed;
shutDown();
/* !!! IDirectDraw7::RestoreAllSurfaces !!! */

return ( restart() );
why not add error checking
make that function a BOOL

BOOL toggle()
{
isWindowed = !isWindowed;
if(!shutDown())
{ return FALSE; }

if(!restart())
{ return FALSE; }

return TRUE;
}

you should do this for all your code... make it a good habit of adding error checking as then the program might tell you whats wron with it.. like this

if(!shutDown)
{
MessageBox(NULL, "Shutdown didnt work!", "DX ERROR", MB_OK | MB_ICONERROR);
return FALSE;
}

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this