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
C plus noob    100
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
C plus noob    100
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
hi cplus noob!

thanx for ur quick answer and tips. in most of my code is error checking handled, but not in that function...
i will have a look to your posted link and will report, if it works for me.

Thx and til soon
BrainlessDesigns

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