How to run an application fullscreen? (Taken from UDDF)
From: "Mike Lischke" <Lischke@imib.med.tu-dresden.de>
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.
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.
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:
--------------------------------------------------------------------------------
function SetFullscreenMode(ModeIndex: Integer) : Boolean;
// changes to the video mode given by 'ModeIndex'
var DeviceMode : TDevMode;
begin
with DeviceMode do
begin
dmSize:=SizeOf(DeviceMode);
dmBitsPerPel:=VideoModes[ModeIndex].ColorDepth;
dmPelsWidth:=VideoModes[ModeIndex].Width;
dmPelsHeight:=VideoModes[ModeIndex].Height;
dmFields:=DM_BITSPERPEL or DM_PELSWIDTH or DM_PELSHEIGHT;
// if mode set failed, we'll just run in windowed mode
Result:=ChangeDisplaySettings(DeviceMode,CDS_FULLS CREEN) = DISP_CHANGE_SUCCESSFUL;
if Result then ScreenModeChanged:=True;
if ModeIndex = 0 then ScreenModeChanged:=False;
end;
end;
--------------------------------------------------------------------------------
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:
--------------------------------------------------------------------------------
const MaxVideoModes = 200; // this isn't very much actually
type TVideoMode = record
Width,
Height,
ColorDepth : Word;
Description : String[20];
end;
var VideoModes : array[0..MaxVideoModes] of TVideoMode;
NumberVideomodes : Integer = 1; // 1 because we have a default mode
--------------------------------------------------------------------------------
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:
--------------------------------------------------------------------------------
procedure ReadVideoModes;
var I, ModeNumber : Integer;
done : Boolean;
DeviceMode : TDevMode;
DeskDC : HDC;
begin
// prepare 'default' entry
with VideoModes[0] do
try
DeskDC:=GetDC(0);
ColorDepth:=GetDeviceCaps(DeskDC,BITSPIXEL);
Width:=Screen.Width;
Height:=Screen.Height;
Description:='default';
finally
ReleaseDC(0,DeskDC);
end;
// enumerate all available video modes
ModeNumber:=0;
done:=False;
repeat
done:=not EnumDisplaySettings(nil,ModeNumber,DeviceMode);
TryToAddToList(DeviceMode);
Inc(ModeNumber);
until (done or (NumberVideomodes >= MaxVideoModes));
// low-res modes don't always enumerate, ask about them explicitly
with DeviceMode do
begin
dmBitsPerPel:=8;
dmPelsWidth:=42;
dmPelsHeight:=37;
dmFields:=DM_BITSPERPEL or DM_PELSWIDTH or DM_PELSHEIGHT;
// make sure the driver doesn't just answer yes to all tests
if ChangeDisplaySettings(DeviceMode,CDS_TEST or CDS_FULLSCREEN) <> DISP_CHANGE_SUCCESSFUL then
begin
I:=0;
while (I < NumberLowResModes-1) and (NumberVideoModes < MaxVideoModes) do
begin
dmSize:=Sizeof(DeviceMode);
dmBitsPerPel:=LowResModes[I].ColorDepth;
dmPelsWidth:=LowResModes[I].Width;
dmPelsHeight:=LowResModes[I].Height;
dmFields:=DM_BITSPERPEL or DM_PELSWIDTH or DM_PELSHEIGHT;
TryToAddToList(DeviceMode);
Inc(I);
end;
end;
end;
end;
--------------------------------------------------------------------------------
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:
--------------------------------------------------------------------------------
type TLowResMode = record
Width,
Height,
ColorDepth : Word;
end;
const NumberLowResModes = 60;
LowResModes : array[0..NumberLowResModes-1] of TLowResMode =
((Width:320;Height:200;ColorDepth:8),(Width:320;He ight:200;ColorDepth:15),
(Width:320;Height:200;ColorDepth:16),(Width:320;He ight:200;ColorDepth:24),
(Width:320;Height:200;ColorDepth:32),(Width:320;He ight:240;ColorDepth: 8),
(Width:320;Height:240;ColorDepth:15),(Width:320;He ight:240;ColorDepth:16),
(Width:320;Height:240;ColorDepth:24),(Width:320;He ight:240;ColorDepth:32),
(Width:320;Height:350;ColorDepth: 8),(Width:320;Height:350;ColorDepth:15),
(Width:320;Height:350;ColorDepth:16),(Width:320;He ight:350;ColorDepth:24),
(Width:320;Height:350;ColorDepth:32),(Width:320;He ight:400;ColorDepth: 8),
(Width:320;Height:400;ColorDepth:15),(Width:320;He ight:400;ColorDepth:16),
(Width:320;Height:400;ColorDepth:24),(Width:320;He ight:400;ColorDepth:32),
(Width:320;Height:480;ColorDepth: 8),(Width:320;Height:480;ColorDepth:15),
(Width:320;Height:480;ColorDepth:16),(Width:320;He ight:480;ColorDepth:24),
(Width:320;Height:480;ColorDepth:32),(Width:360;He ight:200;ColorDepth: 8),
(Width:360;Height:200;ColorDepth:15),(Width:360;He ight:200;ColorDepth:16),
(Width:360;Height:200;ColorDepth:24),(Width:360;He ight:200;ColorDepth:32),
(Width:360;Height:240;ColorDepth: 8),(Width:360;Height:240;ColorDepth:15),
(Width:360;Height:240;ColorDepth:16),(Width:360;He ight:240;ColorDepth:24),
(Width:360;Height:240;ColorDepth:32),(Width:360;He ight:350;ColorDepth: 8),
(Width:360;Height:350;ColorDepth:15),(Width:360;He ight:350;ColorDepth:16),
(Width:360;Height:350;ColorDepth:24),(Width:360;He ight:350;ColorDepth:32),
(Width:360;Height:400;ColorDepth: 8),(Width:360;Height:400;ColorDepth:15),
(Width:360;Height:400;ColorDepth:16),(Width:360;He ight:400;ColorDepth:24),
(Width:360;Height:400;ColorDepth:32),(Width:360;He ight:480;ColorDepth: 8),
(Width:360;Height:480;ColorDepth:15),(Width:360;He ight:480;ColorDepth:16),
(Width:360;Height:480;ColorDepth:24),(Width:360;He ight:480;ColorDepth:32),
(Width:400;Height:300;ColorDepth: 8),(Width:400;Height:300;ColorDepth:15),
(Width:400;Height:300;ColorDepth:16),(Width:400;He ight:300;ColorDepth:24),
(Width:400;Height:300;ColorDepth:32),(Width:512;He ight:384;ColorDepth: 8),
(Width:512;Height:384;ColorDepth:15),(Width:512;He ight:384;ColorDepth:16),
(Width:512;Height:384;ColorDepth:24),(Width:512;He ight:384;ColorDepth:32));
--------------------------------------------------------------------------------
What remains is the function TryToAddToList:
--------------------------------------------------------------------------------
procedure TryToAddToList(DeviceMode: TDevMode);
// Adds a video mode to the list if it's not a duplicate and can actually be set.
var I : Integer;
begin
// See if this is a duplicate mode (can happen because of refresh
// rates, or because we explicitly try all the low-res modes)
for I:=1 to NumberVideomodes-1 do
with DeviceMode do
if ((dmBitsPerPel = VideoModes[I].ColorDepth) and
(dmPelsWidth = VideoModes[I].Width) and
(dmPelsHeight = VideoModes[I].Height)) then Exit; // it's a duplicate mode
// do a mode set test (doesn't actually do the mode set, but reports whether it would have succeeded).
if ChangeDisplaySettings(DeviceMode,CDS_TEST or CDS_FULLSCREEN) <> DISP_CHANGE_SUCCESSFUL then Exit;
// it's a new, valid mode, so add this to the list
with DeviceMode do
begin
VideoModes[NumberVideomodes].ColorDepth:=dmBitsPerPel;
VideoModes[NumberVideomodes].Width:=dmPelsWidth;
VideoModes[NumberVideomodes].Height:=dmPelsHeight;
VideoModes[NumberVideomodes].Description:=Format('%d x %d, %d bpp',[dmPelsWidth,dmPelsHeight,dmBitsPerPel]);
end;
Inc(NumberVideomodes);
end;
--------------------------------------------------------------------------------
To make your implementation complete, you'd need a function to restore the default video mode, after your program exits:
--------------------------------------------------------------------------------
procedure RestoreDefaultMode;
// restores default desktop video mode
var T : TDevMode absolute 0; // a little trick to create a nil pointer
begin
// Since the first parameter must be a var, we cannot use nil directly. Instead
// we use a variable with an absolute address of 0.
ChangeDisplaySettings(T,CDS_FULLSCREEN);
end;
Bookmarks