Delphi - объектно-ориентированный язык программирования, разработанный компанией Borland в 1995 году. Он основан на языке программирования Pascal, но имеет более расширенные возможности и добавлены новые функции.
Delphi является интегрированной средой разработки (IDE), которая позволяет разрабатывать программное обеспечение для различных платформ, включая Windows, macOS, Android и iOS. Delphi достигает многоплатформенности с помощью...
При разработке приложений, которые затем будут использоваться на большом числе различных ПК очень полезно иметь возможность не только получения информации о текущем видеорежиме, но и возможность получить все доступные видеорежимы для данного ПК. Еще одна область, где используется переключение видеорежимов при написании игр без использования DirectX.
Получение списка видеорежимов
Получить видеорежимы можно серией вызовов EnumDisplaySettings. Функция EnumDisplaySettings возвращает информацию о видеорежиме, указанном в параметре IModeNode. Функции необходимо передать структуру типа TDevMode, в которую будет записана информация о видеорежиме. Данная структура имеет поля, характеризующие видеорежим: разрешение (dmPelsWidth, dmPelsHeight), количество битов цветности (dmBitsPerPel), частота обновления экрана (dmDisplayFrequency) и др.
function EnumDisplaySettings(lpszDeviceName: PWideChar; iModeNum: DWORD; var lpDevMode: TdeviceMode): BOOL; stdcall;
Параметры
Поле Описание
Если lpDevMode равно nil, из реестра берется информация о видеорежиме установленном по умолчанию. Передавая в lpDevMode nil и в dwFlags 0 можно получить настройки текущего видеорежима.
Ниже приведена процедура, получающая и отображающая в ListBox все возможные видеорежимы.
procedure TForm1.FormCreate(Sender: TObject); var i: Integer; DevMode : TDeviceMode; begin i:=0; while EnumDisplaySettings(nil,i,DevMode) do begin with Devmode do ListBox1.Items.Add(Format('%dx%d %d Colors', [dmPelsWidth,dmPelsHeight,Int64(1) shl dmBitsperPel])); Inc(i); end; end;
Получение параметров текущего видеорежима
Помимо вызова EnumDisplaySettings инфомацию о текущем видеорежиме можно получать и другими способами.Получить количество битов цвета текущего видеорежима можно и другим способом:
GetDeviceCaps(Form1.Canvas.Handle, BITSPIXEL) * GetDeviceCaps(Form1.Canvas.Handle, PLANES)
Получаемые значения при этом:
Непосредственно количество цветов можно так же легко подсчитать:
NumberOfColors := (1 shl (GetDeviceCaps(Form1.Canvas.Handle, BITSPIXEL) * GetDeviceCaps(Form1.Canvas.Handle, PLANES));
Текущее разрешение экрана можно узнать с помощью вызова GetSystemMetrics() в качестве параметров передается:
Ниже приведен пример получения высоты и ширины рабочей области экрана (для всей экранной области надо просто поменять параметры вызова GetSystemMetrics):
var x, y: Integer; Mode: string; begin x:=GetSystemMetrics(Sm_Cxscreen); y:=GetSystemMetrics(Sm_CYscreen); Mode:=Format('%d x %d',[x,y]); if y=480 then Mode:=Mode+('Standard VGA') else Mode:=Mode+('Super VGA'); StaticText1.Caption:=Mode; end;
Установка видеорежима
Как мы убедились получения списка и параметров видеорежимов не проблема. Теперь разберемся с программной сменой видеорежимов. Функция ChangeDisplaySettings предназначена для изменения текущего видеорежима экрана и при необходимости обновления этой информации в реестре Windows.
function ChangeDisplaySettings(var lpDevMode: TDeviceMode; dwFlags: DWORD): Longint; stdcall;
Параметры:
При немедленном изменении видеорежима всем запущенным приложениям рассылается сообщение WM_DISPLAYCHANGE.
А вот и пример смены видеорежима:
{...} type TForm1 = class(TForm) Button1: TButton; ListView1: TListView; procedure Button1Click(Sender: TObject); procedure FormCreate(Sender: TObject); procedure ListView1DblClick(Sender: TObject); private { Private declarations } {Массив для хранения информации о видеорежимах} DevMode : array[0..20] of TDeviceMode; public { Public declarations } end; {...} procedure TForm1.FormCreate(Sender: TObject); begin {Настройка ListView} ListView1.ViewStyle := vsReport; ListView1.RowSelect := TRUE; ListView1.Columns.Add; ListView1.Columns.Add; ListView1.Columns[0].Caption := 'Width x Height'; ListView1.Columns[0].Width := 100; ListView1.Columns[1].Caption := 'Colors'; ListView1.Columns[1].Width := 100; end; {Процедура получения списка режимов} procedure TForm1.Button1Click(Sender: TObject); var tmpStr1, tmpStr2 : string; tmpDC : HDC; x, Selection, cxScreen, cyScreen, Resolution : Integer; begin { Запоминаем текущие настройки} tmpDC := getDC(Handle); try cxScreen := GetSystemMetrics(SM_CXSCREEN); cyScreen := GetSystemMetrics(SM_CYSCREEN); Resolution := GetDeviceCaps(tmpDC, BITSPIXEL); finally ReleaseDC(Handle, tmpDC); end; ListView1.Items.Clear; x := 0; { Получаем список видеорежимов} while EnumDisplaySettings(nil,x,DevMode[x]) do begin { Разрешение экрана } tmpStr1 := IntToStr(DevMode[x].dmPelsWidth) + 'x' + IntToStr(DevMode[x].dmPelsHeight); { Цвета } case DevMode[x].dmBitsPerPel of 4 : tmpStr2 := '16 Colors'; 8 : tmpStr2 := '256 Colors'; 16 : tmpStr2 := 'High Color (16 Bit)'; 32 : tmpStr2 := 'True Color (32 Bit)'; end; { А теперь полученную информацию надо отобразить } with ListView1.Items.Add do begin Caption := tmpStr1; SubItems.Add(tmpStr2); end; { В ListView надо встать не строку с описанием текущего режима, для этого сохраним индекс элемента с описанием этого режима } if ( cxScreen = DevMode[x].dmPelsWidth ) and ( cyScreen = DevMode[x].dmPelsHeight ) and ( Resolution = DevMode[x].dmBitsPerPel ) then Selection := x; inc(x); if x = 20 then Break; end; { В ListView перемещаемся на строчку с описанием текущего режима } ActiveControl := ListView1; ListView1.Selected := ListView1.Items.Item[Selection]; end; {Установка выбранного пользователем видеорежима} procedure TForm1.ListView1DblClick(Sender: TObject); var tmpDevMode : TDevMode; begin { Получаем сохраненную ранее информацию по выбранному режиму} tmpDevMode := DevMode[ListView1.Items.IndexOf(ListView1.Selected)]; { Скажем Windows, какие параметры надо сменить } tmpDevMode.dmFields := DM_BITSPERPEL or DM_PELSWIDTH or DM_PELSHEIGHT or DM_DISPLAYFLAGS or DM_DISPLAYFREQUENCY; { Очень неплохо будет протестировать видеорежим и записать изменения в реестр} if ChangeDisplaySettings(tmpDevMode, CDS_TEST) = DISP_CHANGE_SUCCESSFUL then ChangeDisplaySettings(tmpDevMode, CDS_UPDATEREGISTRY); end;
Замечание 1:
Не рекомендуется устанавливать видеорежимы, отличные от полученных вызовами EnumDisplaySettings. Возможна ситуация, когда пользователь вместо рабочего стола увидит лишь черный экран.
Замечание 2:
Многие драйвера, особенно старые не поддерживают изменения видеорежима без перезагрузки компьютера.
Обнаружение изменений видеорежима
При изменениях видеорежима генерируется сообщение WM_DISPLAYCHANGE. Необходимо создать обработчик данного сообщения в вашем приложении.
... type TForm1 = class(TForm) ListBox1: TListBox; ... private procedure WMDisplayChange(var message:TMessage); message WM_DISPLAYCHANGE; ... procedure TForm1.WMDisplayChange(var message: TMessage); begin ShowMessage('Changes in display detected!'); inherited; end;