How to run an application fullscreen?<br><br>From: "Mike Lischke" <Lischke@imib.med.tu-dresden.de><br><br>Running an application full screen means that the application window covers the entire desktop area. This is often necessary because of some video cards which can only accelerate full screen apps., but you may also often want that nothing else than your program is visible to the user. BTW: Running fullscreen isn't only related to OpenGL, DirectX or 3D in general. Strictly taken would fullscreen only require that you set your window state to wsMaximize, that's all.<br><br>But there's another question implied by asking for fullscreen applications. It's the point that you either may want to let the user choose a specific color and pixel resolution or you want to run your program in a fixed resolution. The latter is in particular very important since not all video cards support all resolutions and often a game or other 3D application has to run in a different (mostly lower) resolution than the user uses for everday work.<br><br>So the complete question should read as: How to run an application fullscreen in a specific color and pixel resolution (whithout reboot)? The key point is the function ChangeDisplaySettings. Depending on the video driver you can set many video modes dynamically, without rebooting the computer:<br><br><br>--------------------------------------------------------------------------------<br><br>function SetFullscreenMode(ModeIndex: Integer) : Boolean;<br>// changes to the video mode given by 'ModeIndex'<br>var DeviceMode : TDevMode;<br>begin<br> with DeviceMode do<br> begin<br> dmSize:=SizeOf(DeviceMode);<br> dmBitsPerPel:=VideoModes[ModeIndex].ColorDepth;<br> dmPelsWidth:=VideoModes[ModeIndex].Width;<br> dmPelsHeight:=VideoModes[ModeIndex].Height;<br> dmFields:=DM_BITSPERPEL or DM_PELSWIDTH or DM_PELSHEIGHT;<br> // if mode set failed, we'll just run in windowed mode<br> Result:=ChangeDisplaySettings(DeviceMode,CDS_FULLSCREEN) = DISP_CHANGE_SUCCESSFUL;<br> if Result then ScreenModeChanged:=True;<br> if ModeIndex = 0 then ScreenModeChanged:=False;<br> end;<br>end;<br><br><br>--------------------------------------------------------------------------------<br><br>As you may have noticed there's a global variable VideoModes in this example. The reason is that you should enumerate all available video modes which can be set dynamically and store them into a structur like VideoModes, to ensure only these are tried to be set:<br><br><br>--------------------------------------------------------------------------------<br><br>const MaxVideoModes = 200; // this isn't very much actually<br>type TVideoMode = record<br> Width,<br> Height,<br> ColorDepth : Word;<br> Description : String[20];<br> end;<br><br>var VideoModes : array[0..MaxVideoModes] of TVideoMode;<br> NumberVideomodes : Integer = 1; // 1 because we have a default mode<br><br><br>--------------------------------------------------------------------------------<br><br>This makes our example much larger as you will see, but you'll get a very useful functionality by implementing it. If you still want you can replace VideoModes in the above function by fixed values (say 640, 480, 16). Enumerating all video modes is done by EnumDisplaySettings:<br><br><br>--------------------------------------------------------------------------------<br><br>procedure ReadVideoModes;<br>var I, ModeNumber : Integer;<br> done : Boolean;<br> DeviceMode : TDevMode;<br> DeskDC : HDC;<br><br>begin<br> // prepare 'default' entry<br> with VideoModes[0] do<br> try<br> DeskDC:=GetDC(0);<br> ColorDepth:=GetDeviceCaps(DeskDC,BITSPIXEL);<br> Width:=Screen.Width;<br> Height:=Screen.Height;<br> Description:='default';<br> finally<br> ReleaseDC(0,DeskDC);<br> end;<br><br> // enumerate all available video modes<br> ModeNumber:=0;<br> done:=False;<br> repeat<br> done:=not EnumDisplaySettings(nil,ModeNumber,DeviceMode);<br> TryToAddToList(DeviceMode);<br> Inc(ModeNumber);<br> until (done or (NumberVideomodes >= MaxVideoModes));<br><br> // low-res modes don't always enumerate, ask about them explicitly<br> with DeviceMode do<br> begin<br> dmBitsPerPel:=8;<br> dmPelsWidth:=42;<br> dmPelsHeight:=37;<br> dmFields:=DM_BITSPERPEL or DM_PELSWIDTH or DM_PELSHEIGHT;<br> // make sure the driver doesn't just answer yes to all tests<br> if ChangeDisplaySettings(DeviceMode,CDS_TEST or CDS_FULLSCREEN) <> DISP_CHANGE_SUCCESSFUL then<br> begin<br> I:=0;<br> while (I < NumberLowResModes-1) and (NumberVideoModes < MaxVideoModes) do<br> begin<br> dmSize:=Sizeof(DeviceMode);<br> dmBitsPerPel:=LowResModes.ColorDepth;<br> dmPelsWidth:=LowResModes.Width;<br> dmPelsHeight:=LowResModes.Height;<br> dmFields:=DM_BITSPERPEL or DM_PELSWIDTH or DM_PELSHEIGHT;<br> TryToAddToList(DeviceMode);<br> Inc(I);<br> end;<br> end;<br> end;<br>end;<br><br><br>--------------------------------------------------------------------------------<br><br>I think this function isn't hard to understand. There are two parts to consider. The first is the standard way to enumerate the video modes. The second ensures that also all low-res modes are tested . This requires, though, a list of low-res modes:<br><br><br>--------------------------------------------------------------------------------<br><br>type TLowResMode = record<br> Width,<br> Height,<br> ColorDepth : Word;<br> end;<br><br>const NumberLowResModes = 60;<br> LowResModes : array[0..NumberLowResModes-1] of TLowResMode =<br> ((Width:320;Height:200;ColorDepth:8),(Width:320;Height:200;ColorDepth:15),<br> (Width:320;Height:200;ColorDepth:16),(Width:320;Height:200;ColorDepth:24),<br> (Width:320;Height:200;ColorDepth:32),(Width:320;Height:240;ColorDepth: 8),<br> (Width:320;Height:240;ColorDepth:15),(Width:320;Height:240;ColorDepth:16),<br> (Width:320;Height:240;ColorDepth:24),(Width:320;Height:240;ColorDepth:32),<br> (Width:320;Height:350;ColorDepth: 8),(Width:320;Height:350;ColorDepth:15),<br> (Width:320;Height:350;ColorDepth:16),(Width:320;Height:350;ColorDepth:24),<br> (Width:320;Height:350;ColorDepth:32),(Width:320;Height:400;ColorDepth: 8),<br> (Width:320;Height:400;ColorDepth:15),(Width:320;Height:400;ColorDepth:16),<br> (Width:320;Height:400;ColorDepth:24),(Width:320;Height:400;ColorDepth:32),<br> (Width:320;Height:480;ColorDepth: 8),(Width:320;Height:480;ColorDepth:15),<br> (Width:320;Height:480;ColorDepth:16),(Width:320;Height:480;ColorDepth:24),<br> (Width:320;Height:480;ColorDepth:32),(Width:360;Height:200;ColorDepth: 8),<br> (Width:360;Height:200;ColorDepth:15),(Width:360;Height:200;ColorDepth:16),<br> (Width:360;Height:200;ColorDepth:24),(Width:360;Height:200;ColorDepth:32),<br> (Width:360;Height:240;ColorDepth: 8),(Width:360;Height:240;ColorDepth:15),<br> (Width:360;Height:240;ColorDepth:16),(Width:360;Height:240;ColorDepth:24),<br> (Width:360;Height:240;ColorDepth:32),(Width:360;Height:350;ColorDepth: 8),<br> (Width:360;Height:350;ColorDepth:15),(Width:360;Height:350;ColorDepth:16),<br> (Width:360;Height:350;ColorDepth:24),(Width:360;Height:350;ColorDepth:32),<br> (Width:360;Height:400;ColorDepth: 8),(Width:360;Height:400;ColorDepth:15),<br> (Width:360;Height:400;ColorDepth:16),(Width:360;Height:400;ColorDepth:24),<br> (Width:360;Height:400;ColorDepth:32),(Width:360;Height:480;ColorDepth: 8),<br> (Width:360;Height:480;ColorDepth:15),(Width:360;Height:480;ColorDepth:16),<br> (Width:360;Height:480;ColorDepth:24),(Width:360;Height:480;ColorDepth:32),<br> (Width:400;Height:300;ColorDepth: 8),(Width:400;Height:300;ColorDepth:15),<br> (Width:400;Height:300;ColorDepth:16),(Width:400;Height:300;ColorDepth:24),<br> (Width:400;Height:300;ColorDepth:32),(Width:512;Height:384;ColorDepth: 8),<br> (Width:512;Height:384;ColorDepth:15),(Width:512;Height:384;ColorDepth:16),<br> (Width:512;Height:384;ColorDepth:24),(Width:512;Height:384;ColorDepth:32));<br><br><br>--------------------------------------------------------------------------------<br><br>What remains is the function TryToAddToList:<br><br><br>--------------------------------------------------------------------------------<br><br>procedure TryToAddToList(DeviceMode: TDevMode);<br>// Adds a video mode to the list if it's not a duplicate and can actually be set.<br>var I : Integer;<br>begin<br> // See if this is a duplicate mode (can happen because of refresh<br> // rates, or because we explicitly try all the low-res modes)<br> for I:=1 to NumberVideomodes-1 do<br> with DeviceMode do<br> if ((dmBitsPerPel = VideoModes.ColorDepth) and<br> (dmPelsWidth = VideoModes.Width) and<br> (dmPelsHeight = VideoModes.Height)) then Exit; // it's a duplicate mode<br><br> // do a mode set test (doesn't actually do the mode set, but reports whether it would have succeeded).<br> if ChangeDisplaySettings(DeviceMode,CDS_TEST or CDS_FULLSCREEN) <> DISP_CHANGE_SUCCESSFUL then Exit;<br><br> // it's a new, valid mode, so add this to the list<br> with DeviceMode do<br> begin<br> VideoModes[NumberVideomodes].ColorDepth:=dmBitsPerPel;<br> VideoModes[NumberVideomodes].Width:=dmPelsWidth;<br> VideoModes[NumberVideomodes].Height:=dmPelsHeight;<br> VideoModes[NumberVideomodes].Description:=Format('%d x %d, %d bpp',[dmPelsWidth,dmPelsHeight,dmBitsPerPel]);<br> end;<br> Inc(NumberVideomodes);<br>end;<br><br><br>--------------------------------------------------------------------------------<br><br>To make your implementation complete, you'd need a function to restore the default video mode, after your program exits:<br><br><br>--------------------------------------------------------------------------------<br><br>procedure RestoreDefaultMode;<br>// restores default desktop video mode<br>var T : TDevMode absolute 0; // a little trick to create a nil pointer<br>begin<br> // Since the first parameter must be a var, we cannot use nil directly. Instead<br> // we use a variable with an absolute address of 0.<br> ChangeDisplaySettings(T,CDS_FULLSCREEN);<br>end;<br><br>