Но есть другой вопрос, подразумеваемый требованиями для полноэкранных приложений. Это наличие возможности выбора пользователем специфического разрешения экрана и глубины цвета или возможность запуска приложения в фиксированном разрешении. Последнее важно в каждом конкретном случае, поскольку не все видеокарты поддерживают все разрешения и часто игра или другое 3D-приложение хотят работать в другом разрешении (в основном на более низком), чем пользователь использует в каждодневной работе.
Так что полностью вопрос читается так: как запустить полноэкранное приложение в специфичном разрешении экрана и глубине цвета (без перезагрузки)? Ключевым пунктом является функция ChangeDisplaySettings. В зависимости от видеодрайвера, вы можете динамически установить один из множества режимов, не перегружая компьютер:
function SetFullscreenMode(ModeIndex: Integer) : Boolean; // изменение видеорежима, задаваемого 'ModeIndex' var DeviceMode : TDevMode; begin with DeviceMode dobegindmSize:=SizeOf(DeviceMode);dmBitsPerPel:=VideoModes[ModeIndex].ColorDepth;dmPelsWidth:=VideoModes[ModeIndex].Width;dmPelsHeight:=VideoModes[ModeIndex].Height;dmFields:=DM_BITSPERPEL or DM_PELSWIDTH or DM_PELSHEIGHT;// при неудачной смене режима переходим в режим текущего разрешенияResult:=ChangeDisplaySettings(DeviceMode,CDS_FULLSCREEN) = DISP_CHANGE_SUCCESSFUL;if Result then ScreenModeChanged:=True;if ModeIndex = 0 then ScreenModeChanged:=False;end;end; |
Если вы обратили внимание, в этом примере присутствует глобальная переменная VideoModes. Ее наличие обусловлено необходимостью перечисления всех доступных режимов, которые могут быть установлены динамически и загружены в структуру, подобную VideoModes для гарантии использования только описанных режимов:
const MaxVideoModes = 200; // это не очень актуально type TVideoMode = record Width,Height,ColorDepth : Word;Description : String[20];end; var VideoModes : array[0..MaxVideoModes] of TVideoMode; NumberVideomodes : Integer = 1; // 1, поскольку есть режим по умолчанию |
procedure ReadVideoModes; var I, ModeNumber : Integer; done : Boolean;DeviceMode : TDevMode;DeskDC : HDC; begin // создание режима "по умолчанию"with VideoModes[0] dotryDeskDC:=GetDC(0);ColorDepth:=GetDeviceCaps(DeskDC,BITSPIXEL);Width:=Screen.Width;Height:=Screen.Height;Description:='default';finallyReleaseDC(0,DeskDC);end; // перечисляем все доступные видеорежимыModeNumber:=0;done:=False;repeatdone:=not EnumDisplaySettings(nil,ModeNumber,DeviceMode);TryToAddToList(DeviceMode);Inc(ModeNumber);until (done or (NumberVideomodes >= MaxVideoModes)); // режимы низкого разрешения не всегда перечислимы, о них запрашивают явноwith DeviceMode dobegindmBitsPerPel:=8;dmPelsWidth:=42;dmPelsHeight:=37;dmFields:=DM_BITSPERPEL or DM_PELSWIDTH or DM_PELSHEIGHT;// тест видеодрайвера: убедимся, что он справится со всеми видеорежимамиif ChangeDisplaySettings(DeviceMode,CDS_TEST or CDS_FULLSCREEN) <> DISP_CHANGE_SUCCESSFUL thenbeginI:=0;while (I < NumberLowResModes-1) and (NumberVideoModes < MaxVideoModes) dobegindmSize:=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; |
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;Height:200;ColorDepth:15),(Width:320;Height:200;ColorDepth:16),(Width:320;Height:200;ColorDepth:24),(Width:320;Height:200;ColorDepth:32),(Width:320;Height:240;ColorDepth: 8),(Width:320;Height:240;ColorDepth:15),(Width:320;Height:240;ColorDepth:16),(Width:320;Height:240;ColorDepth:24),(Width:320;Height:240;ColorDepth:32),(Width:320;Height:350;ColorDepth: 8),(Width:320;Height:350;ColorDepth:15),(Width:320;Height:350;ColorDepth:16),(Width:320;Height:350;ColorDepth:24),(Width:320;Height:350;ColorDepth:32),(Width:320;Height:400;ColorDepth: 8),(Width:320;Height:400;ColorDepth:15),(Width:320;Height:400;ColorDepth:16),(Width:320;Height:400;ColorDepth:24),(Width:320;Height:400;ColorDepth:32),(Width:320;Height:480;ColorDepth: 8),(Width:320;Height:480;ColorDepth:15),(Width:320;Height:480;ColorDepth:16),(Width:320;Height:480;ColorDepth:24),(Width:320;Height:480;ColorDepth:32),(Width:360;Height:200;ColorDepth: 8),(Width:360;Height:200;ColorDepth:15),(Width:360;Height:200;ColorDepth:16),(Width:360;Height:200;ColorDepth:24),(Width:360;Height:200;ColorDepth:32),(Width:360;Height:240;ColorDepth: 8),(Width:360;Height:240;ColorDepth:15),(Width:360;Height:240;ColorDepth:16),(Width:360;Height:240;ColorDepth:24),(Width:360;Height:240;ColorDepth:32),(Width:360;Height:350;ColorDepth: 8),(Width:360;Height:350;ColorDepth:15),(Width:360;Height:350;ColorDepth:16),(Width:360;Height:350;ColorDepth:24),(Width:360;Height:350;ColorDepth:32),(Width:360;Height:400;ColorDepth: 8),(Width:360;Height:400;ColorDepth:15),(Width:360;Height:400;ColorDepth:16),(Width:360;Height:400;ColorDepth:24),(Width:360;Height:400;ColorDepth:32),(Width:360;Height:480;ColorDepth: 8),(Width:360;Height:480;ColorDepth:15),(Width:360;Height:480;ColorDepth:16),(Width:360;Height:480;ColorDepth:24),(Width:360;Height:480;ColorDepth:32),(Width:400;Height:300;ColorDepth: 8),(Width:400;Height:300;ColorDepth:15),(Width:400;Height:300;ColorDepth:16),(Width:400;Height:300;ColorDepth:24),(Width:400;Height:300;ColorDepth:32),(Width:512;Height:384;ColorDepth: 8),(Width:512;Height:384;ColorDepth:15),(Width:512;Height:384;ColorDepth:16),(Width:512;Height:384;ColorDepth:24),(Width:512;Height:384;ColorDepth:32)); |
procedure TryToAddToList(DeviceMode: TDevMode); // Добавление видеорежима к списку, это это не дубликат и режим действительно может быть установлен. var I : Integer; begin // Смотрим на предмет дублирования видеорежима (такое может быть из-за показателя// частоты смены кадров или из-за того, что мы явно пробуем все режимы низкого разрешения)for I:=1 to NumberVideomodes-1 dowith DeviceMode doif ((dmBitsPerPel = VideoModes[I].ColorDepth) and(dmPelsWidth = VideoModes[I].Width) and(dmPelsHeight = VideoModes[I].Height)) then Exit; // повтор видеорежима (дубликат) // устанавливаем тестируемый режим (на самом деле мы не устанавливаем данный режим, а хотим получить сообщение о его поддержке видеокартой).if ChangeDisplaySettings(DeviceMode,CDS_TEST or CDS_FULLSCREEN) <> DISP_CHANGE_SUCCESSFUL then Exit; // если это новый, поддерживаемый режим, то добавляем его к спискуwith DeviceMode dobeginVideoModes[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; |
procedure RestoreDefaultMode; // восстанавливаем видеорежим по умолчанию var T : TDevMode absolute 0; // маленькая хитрость: создаем указатель на ноль begin // Так как первый параметр является переменной, мы не можем использовать ноль// непосредственно. Взамен мы используем переменную с абсолютным адресом нуля.ChangeDisplaySettings(T,CDS_FULLSCREEN);end; |