Změna rozlišení obrazovky - Builder.cz - Informacni server o programovani

Odběr fotomagazínu

Fotografický magazín "iZIN IDIF" každý týden ve Vašem e-mailu.
Co nového ve světě fotografie!

 

Zadejte Vaši e-mailovou adresu:

Kamarád fotí rád?

Přihlas ho k odběru fotomagazínu!

 

Zadejte e-mailovou adresu kamaráda:



Delphi

Změna rozlišení obrazovky

14. května 2001, 00.00 | Článek ukazuje, jak lze v Delphi zjistit seznam rozlišení obrazovky, dostupných na daném počítači, a přepínat mezi nimi. Vše je vysvětleno na ukázkové aplikaci.

Možná jste někdy řešili problém, jak ve Windows změnit rozlišení obrazovky. Pokud například programujete nějakou hru, a chcete, aby běhala ve fullscreenu a rozlišení 640x480, 16 bitů, a z nějakého důvodu nechcete (popř. nemůžete) použít DirectX, přijde tato možnost vhod.

Ukázková aplikaceCelý problém si vysvětlíme na jednoduché aplikaci. Jak vypadá, vidíte na obrázku vpravo. Princip je jednoduchý - program zjistí a vypíše do seznamu všechny dostupné režimy obrazovky a uživatel si může kliknutím na položku seznamu a následným stiskem tlačítka Změnit potřebné rozlišení vybrat. Vím, že něco podobného ve Windows už je, ale pomůže nám to lépe pochopit celý mechanismus přepínání rozlišení obrazovky ve Windows. Ještě bych měl dodat, že dále nebudu hovořit o rozlišení, ale o režimu obrazovky. Režim proto, že rozlišení je jen nastavení rozměrů v pixelech, kdežto my budeme měnit i barevnou hloubku. Možná jsem trochu pedantský, ale přijde mi to o něco výstižnější a přesnější.

Krok první - zjištění dostupných režimů obrazovky

Prvním naším úkolem je zjistit, jaké všechny režimy můžeme na displeji nastavit. Nemusím snad připomínat, že získaný seznam se bude (někdy i dost podstatně) lišit podle videokarty a připojeného monitoru.

Na zjištění parametrů jednotlivých rozlišení je tu Windows API funkce EnumDisplaySettings, která je v unitě Windows.pas deklarována takto:

function EnumDisplaySettings(lpszDeviceName: PChar; iModeNum: DWORD;
  var lpDevMode: TDeviceMode): BOOL; stdcall;

Parametr první, lpszDeviceName, je název zařízení, pro které chceme parametry zjišťovat. Pokud místo něj předáme hodnotu nil, bude se jako zkoumané zařízení chápat hlavní displej počítače. iModeNum je index režimu, jehož parametry zjišťujeme. Indexy jsou počítány od nuly a pokud zadáme špatný index, funkce vrátí False. Toho za moment využijeme.

Poslední parametr je lpDevMode, což je struktura (čili záznam, abych byl věrný Pascalské terminologii), kde jsou uchovány všechny možné parametry daného zařízení. Tato struktura je celkem rozsáhlá, protože Windows jí používají poměrně univerzálně (třeba i pro tiskárny a v podstatě jakákoliv zobrazovací zařízení). Nás z ní budou zajímat členy dmPelsWidth, dmPelsHeight a dmBitsPerPel. Všechno jsou to celá čísla a co znamenají je doufám jasné z jejich názvu (pro jistotu: šířka, výška a počet bittů na pixel v daném režimu).

Seznam režimů budeme udržovat dvakrát - jednou v listBoxu (jako textový popis) a jednou ve speciálním seznamu DevModes, který bude obsahovat ukazatele na jednotlivé struktury TDeviceMode (budeme si pamatovat jednu pro každý režim). Seznam získáme opakovaným voláním funkce EnumDisplaySettings, přičemž nejdřív nastavíme index režimu na nulu a pak ho budeme postupně zvyšovat, dokud funkce nevrátí False. To je znamení, že další režimy už není možné nastavit a námi vytvořený seznam režimů je kompletní. Ale dost už bylo teorie, jdeme na kód:

procedure TForm1.FormCreate(Sender: TObject);
var
  DevMode: TDeviceMode;
  P: Pointer;
  I: Integer;
begin
  // inicializujeme seznam, kam uložíme načtené údaje
  DevModes := TList.Create;

  I := 0;
  // opakujeme, dokud fce nevrátí False
  while EnumDisplaySettings(nil, I, DevMode) do
  begin
    GetMem(P, SizeOf(TDeviceMode));         // alokujeme paměť
                                            //pro novou položku seznamu...
    Move(DevMode, P^, SizeOf(TDeviceMode)); // ..zkopírujeme do ní údaje z DevMode
    DevModes.Add(P);                        // ...a přidáme do seznamu

    // přidáme i položku do ListBoxu
    with DevMode do
      ListBox1.Items.Add(Format('%dx%d, %dbit',
      [dmPelsWidth, dmPelsHeight, dmBitsPerPel, dmDisplayFrequency]));

    Inc(I);
  end;
end;

procedure TForm1.FormDestroy(Sender: TObject);
var
  I: Integer;
begin
  // nejdřív uvolníme jednotlivé položky seznamu, pak celý objekt
  for I := 0 to DevModes.Count - 1 do
    FreeMem(DevModes[I]);
  DevModes.Free;
end;

do deklarace formuláře samozřejmě nesmíme zapomenout umístit proměnnou DevModes:

...
public
  { Public declarations }
  DevModes: TList;
end;
...
Krok druhý - vlastní změna rozlišení

Samotná změna rozlišení se provádí pomocí funkce ChangeDisplaySettings, která má dva parametry. První je známá struktura TDeviceMode, popisující rozlišení, jež chceme nastavit. Snad bych jen dodal, že v jejím členu dmFlags musí být patřičně nastaveno, které položky chceme měnit (rozlišení, barevnou hloubku) a ve členu dmSize by měla být uvedena velikost celé struktury v bytech.

Druhý parametru určuje přesněji chování funkce. Předáme-li jako jeho hodnotu 0, funkce prostě změní rozlišení. Pokud předáme konstantu CDS_UPDATEREGISTRY, rozlišení bude v registrech nastaveno jako výchozí - změní se tedy napevno. Hodnota CDS_TEST zase způsobí, že funkce "otestuje", zda je změna režimu možná, vrátí adekvátní návratovou hodnotu, ale režim obrazovky ponechá beze změny. V naší ukázce se spokojíme s případem prvním - hodnotou 0.

Návratová hodnota je DISP_CHANGE_SUCCESSFUL v případě úspěšné změny režimu nebo DISP_CHANGE_RESTART pokud je nutno před změnou restartovat počítač. Pak existuje několik dalších hodnot, které funkce vrací v případě chyby - pro přesný popis vás odkážu na nápovědu k Win32 API.

Procedura "pověšená" na tlačítko Změnit bude tedy vypadat takto:

procedure TForm1.Button1Click(Sender: TObject);
var
  DevMode: TDeviceMode;
begin
  // pokud je vybrána nějaká poožka...
  if ListBox1.ItemIndex <> - 1 then
  begin
    // ...naplníme DevMode příslušnými daty
    with PDeviceMode(DevModes[ListBox1.ItemIndex])^ do
    begin
      DevMode.dmSize := SizeOf(TDeviceMode);
      DevMode.dmPelsWidth := dmPelsWidth;
      DevMode.dmPelsHeight := dmPelsHeight;
      DevMode.dmBitsPerPel := dmBitsPerPel;
      DevMode.dmFields := DM_PELSWIDTH + DM_PELSHEIGHT + DM_BITSPERPEL;
    end;
    // vlastní změna rozlišení
    // + jednoduchá chybová detekce podle návratové hodnoty fce
    case ChangeDisplaySettings(DevMode, 0) of
      DISP_CHANGE_SUCCESSFUL: ;
      DISP_CHANGE_RESTART:
        Application.MessageBox(
          'Aby nastavení obrazovky vstoupilo v platnost, 
          je nutné restartovat počítač.',
          'Restart', MB_ICONEXCLAMATION);
    else
      Application.MessageBox(
        'Při změně nastavení obrazovky nastala chyba.',
        'Restart', MB_ICONSTOP);
    end;
  end;
end;

Funkce ChangeDisplaySettings má jednu zajímavou vlastnost - pokud jako první parametr předáme nil místo odkazu na strukturu TDeviceMode, funkce obnoví rozlišení nastavené původně jako výchozí (pokud jsme ovšem předtím nepoužili CDS_UPDATEREGISTRY). Toho s výhodou využijeme u procedury přiřazené ke druhému tlačítku:

procedure TForm1.Button2Click(Sender: TObject);
begin
  ChangeDisplaySettings(PDevMode(nil)^, 0); //vrácení rozlišení na původní hodnotu
end;

Tak, to je ke změnám režimů obrazovky ode mne vše. Ukázkovou aplikaci i se zdrojáky pro Delphi 3 a vyšší si můžete stáhnout tady.

Tématické zařazení:

 » Rubriky  » Delphi  

 » Rubriky  » Windows  

 

 

 

Nejčtenější články
Nejlépe hodnocené články

 

Přihlášení k mému účtu

Uživatelské jméno:

Heslo: