Umíme to s Delphi, 30. díl – aby se uživatel neopařil

To, že při vývoji aplikace v Delphi existuje možnost vytvořit pro řadu akcí klávesovou zkratku (tzv. Hot Key), asi nikoho nezaskočí. Již jsme několik takových momentů společně zažili. Víte ale, že v Delphi existuje přímo komponenta určená k vytváření klávesových zkratek? Dnes si o ní povíme.

Klávesové zkratky bez speciálních komponent

Když jsme mluvili o vytváření uživatelských nabídek (komponenta MainMenu), řekli jsme si, že pro každou položku hlavního menu je možné vytvořit klávesovou zkratku. Používá se k tomu vlastnost položek menu ShortCut. Po klepnutí na šipku v pravé části obdélníčku vedle vlastnosti ShortCut v Object Inspectoru (možná raději viz obrázek:-)) se rozbalí seznam předdefinovaných klávesových zkratek.

Představte si ale situaci, ve které chcete dát uživateli možnost za běhu aplikace změnit klávesovou zkratku některé volby v menu, případně nějakého příkazu a podobně. Největší problém zřejmě nebude v tom, jak novou klávesovou zkratku „zakomponovat“ do aplikace – prostě změníme např. hodnotu vlastnosti ShortCut položky v menu, ale jak ji od uživatele komfortně získat.

Nabízela by se třeba možnost vytvořit speciální formulář, na něj umístit seznam s klávesami Alt, Shift a Ctrl, dát uživateli možnost vybrat některou z těchto kláves a k ní libovolnou alfanumerickou klávesu… nebo bychom mohli umístit na formulář editační pole a ošetřovat událost typu OnKeyDown pro zjištění stisknuté klávesy a jejího „modifikátoru“ Shift, Alt či Ctrl… nebo… nebo…

Jistě, možností je celá řada, ale asi všichni cítíme, že nejsou příliš elegantní a že na to, jakou „maličkost“ v naší aplikaci vylepší, je to poměrně významné plýtvání energií. Řešením je – komponenta HotKey.

Klávesové zkratky s pomocí komponenty HotKey

V Delphi existuje komponenta HotKey, která se nachází v paletě Win32. Na paletě vypadá jako editační pole, nicméně má v sobě viditelný nápis Alt. Po umístění na formulář se objeví klasické editační pole, ale obsahuje nápis Alt + A, viz obrázek:

Na rozdíl od „standardního“, nám již dobře známého editního pole (komponenta Edit) ovšem toto editační pole slouží pouze k načtení klávesové zkratky. Než si ukážeme konkrétní aplikaci používající HotKey, projdeme si společně vlastnosti a události této komponenty.

Vlastnosti komponenty HotKey

Komponenta HotKey má pouze 4 své vlastní vlastnosti, ostatní jsou zděděné a ty důležité jsme již uvedli v předcházejících kapitolách. (Ostatně, ani ty 4 vlastnosti nejsou přímo „její“, zdědila je od TCustomHotKey, ale to je tak neuvěřitelně lhostejné, že je to až neuvěřitelné).

Poznámka pro pokročilé uživatele:

Ona zmíněná lhostejnost samozřejmě ale platí jenom do té doby, dokud nebudete potřebovat specializovaný HotKey (stačí malinko pozměněný), protože pak budete muset oddědit novou třídu od TCustomHotKey a budete autorům Delphi blahořečit, že tyto vlastnosti třída THotKey pouze oddědila, a tudíž je nemusíte dodělávat ;-)

Poznámka: v následujícím textu budeme opakovaně používat pojmy „modifikátor“, „modifikátorová klávesa“ apod. Modifikátorem budeme rozumět klávesu typu Shift, Ctrl, Alt, která při současném stisku s jinou („nemodifikátorovou“) klávesou modifikuje význam této nemodifikátorové klávesy.

Příklad modifikátorových kláves: Shift, Ctrl, Alt

Příklad nemodifikátorových kláves: písmena, čísla, funkční klávesy (F1 – F12), šipky, apod.

Vlastnost AutoSize

Určuje, bude-li velikost komponenty automaticky přizpůsobena velikosti písma. Pokud nastavíte True, nebude možné editační pole HotKey zvětšit, aniž zvětšíme také velikost písma, v opačném případě ano.

Vlastnost HotKey

Obsahuje aktuální klávesovou zkratku. Tato vlastnost je typu TShortCut (a je tedy stejného typu jako zmíněná vlastnost ShortCut položek menu). Přednastavená hodnota je Alt + A. Chcete-li změnit hodnotu této vlastnosti, učiňte to buď přímo (ale není to příliš pohodlné), nebo prostřednictvím vlastnosti Modifiers – viz dále.

Vlastnost InvalidKeys

Umožňuje specifikovat jeden (nebo více) modifikátorů, které budou považovány za zakázané (budou tedy ignorovány). Klávesy, které zadáte do hodnoty této vlastnosti, nejsou povoleny a nebude tedy možné na jejich základě vytvořit klávesovou zkratku.

Možné hodnoty vlastnosti InvalidKeys:

Hodnota Význam
hcNone Klávesy bez modifikátoru jsou zakázány
hcShift Klávesu Shift nelze použít jako modifikátor
hcCtrl Klávesu Ctrl nelze použít jako modifikátor
hcAlt Klávesu Alt nelze použít jako modifikátor
hcShiftCtrl Jako modifikátor nelze použít kombinaci kláves Ctrl + Shift
hcShiftAlt Jako modifikátor nelze použít kombinaci kláves Shift + Alt
hcCtrlAlt Jako modifikátor nelze použít kombinaci kláves Ctrl + Alt
hcShiftCtrlAlt Jako modifikátor nelze použít kombinaci kláves Ctrl + Shift + Alt

Vlastnost Modifiers

Specifikuje klávesu (příp. více kláves), které jsou použity v kombinaci s „obyčejnými“ klávesami, tedy s klávesami, jež nejsou modifikátory. Je možné použít následující modifikátory:

Hodnota Modifikátor
hkShift Klávesa Shift je použita jako modifikátor
hkCtrl Klávesa Ctrl je použita jako modifikátor
hkAlt Klávesa Alt je použita jako modifikátor

Spolupráce vlastností

Pokud vám stále není úplně jasné praktické používání vlastností Modifiers a InvalidKeys, vězte, že nejvýkonnější (a nejčastěji využívané) jsou při vzájemné spolupráci. V následující tabulce naleznete příklad několika možných kombinací hodnot těchto vlastností a popis výsledku – tedy co příslušné nastavení bude v praxi znamenat:

Hodnota vlastnosti Modifikators Hodnota vlastnosti InvalidKeys Výsledek
[] [] Je možné vytvořit zcela libovolnou klávesovou zkratku s jakýmikoliv modifikátory a klávesami
[hkCtrl] [] V editačním okénku komponenty HotKey se objeví jako „default“ nápis „Ctrl +“, nicméně je možné stále vytvořit libovolnou klávesovou zkratku; při použití jiného (nebo žádného) modifikátoru nápis „Ctrl +“ zmizí a je možné vytvořit jakoukoliv zkratku, i bez klávesy Ctrl.
[] [hcShift] Je možné vytvořit jakoukoliv zkratku s výjimkou „Shift + jakákoliv_jiná_klávesa“. Je ale možné vytvořit např. „Shift + Ctrl + A“ – tedy nelze vytvořit pouze zkratky mající jako jediný modifikátor klávesu Shift.
[] [hcShift, hcShiftAlt] Je možné vytvořit všechny zkratky s výjimkou těch, kde se jako modifikátor vyskytuje samotný Shift nebo Shift + Alt. Zkratky typu Ctrl + Shift + Alt + A lze vytvářet.
[hkShift] [hcShift, hcShiftAlt] Hodnota Modifiers „přebije“ InvalidKeys, takže je možné vytvářet všechny zkratky s výjimkou těch, ve kterých je Shift + Alt.
[hkShift, hkCtrl] [hcNone, hcShift, hcShiftAlt] Jako „default“ je nabízen text „Ctrl + Shift +“. Kromě zkratek tohoto typu je možné vytvářet i zkratky typu „Ctrl + A“ či „Alt + A“, dále „Ctrl + Alt + A“ a „Ctrl + Shift + Alt + A“. Není možné vytvořit zkratky typu „Shift + A“, „Alt + Shift + A“ a také zkratky typu „A“ – tedy samostatné písmeno nebo číslo (nicméně např. klávesy z numerické klávesnice fungují bez problémů).

Události komponenty HotKey

Komponenta HotKey má šest událostí, podíváme se jen na dvě z nich, přestože jsme se s ni mi již v minulosti velmi stručně setkali:

Událost OnEnter

Objeví se v okamžiku, kdy komponenta obdrží vstupní zaměření, tedy např. když se do ní přemístí kurzor apod.

Událost OnExit

Objeví se v okamžiku, kdy naopak komponenta zaměření ztratí, tj. především když uživatel tuto komponentu opustí a přejde s kurzorem jinam.

Příklad použití komponenty HotKey

Nyní se pokusíme vytvořit aplikaci, na níž snad bude dostatečně patrné, jak s komponentou pracovat a především jak manipulovat s jejími (možná stále ještě poněkud záhadnými) vlastnostmi InvalidKeys, Modifiers, HotKey apod.

Vytvoříme aplikaci mající na hlavním formuláři (frmHlavni) následující komponenty:

  • HotKey (Name = HotKey);
  • komponenta ListView z palety Win32 (Name = ListView);
  • Hlavní menu (komponenta MainMenu, Name = MainMenu) s jedinou (hlavní) položkou Soubor (Name = mnItmSoubor), která bude mít následující podpoložky :
    • Nový (Name = mnItmNovy),
    • - (oddělovací čára, Name = N1),
    • Otevřít (Name = mnItmOtevri),
    • Uložit (Name = mnItmUloz),
    • Uložit jako (Name =mnItmUlozJako),
    • Zavřít (Name = mnItmZavri),
    • - (oddělovací čára Name = N2),
    • Konec (Name =mnItmKonec);
  • 2x tlačítko (btnNastavit a btnKonec).

Aplikace bude fungovat tak, že po jejím spuštění načte do komponenty ListView názvy všech podpoložek v menu Soubor a vedle nich zobrazí jejich klávesové zkratky (které samozřejmě žádné nejsou, pokud jste v návrhové fázi nevyplnili vlastnosti ShortCut jednotlivých položek). Po klepnutí do seznamu na kteroukoliv položku je možné zadat pomocí editačního pole HotKey novou klávesovou zkratku, která se po klepnutí na tlačítko Nastavit uloží k příslušné položce do menu a zobrazí se v seznamu. Přesvědčit se můžete tak, že se podíváte do hlavního menu (případné klávesové zkratky se totiž u všech položek zobrazují automaticky).

Poznámka: o komponentě ListView si podrobně povíme za týden, neboť slouží k prohlížení seznamu a má celou řadu možností nastavení, takže její použití je velmi flexibilní.

Zdrojový kód celého modulu:

unit Hlavni;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  ComCtrls, Menus, StdCtrls;

type
  TfrmHlavni = class(TForm)
    HotKey: THotKey;
    ListView: TListView;
    MainMenu: TMainMenu;
    mnItmSoubor: TMenuItem;
    mnItmNovy: TMenuItem;
    N1: TMenuItem;
    mnItmOtevri: TMenuItem;
    mnItmUloz: TMenuItem;
    mnItmUlozJako: TMenuItem;
    mnItmZavri: TMenuItem;
    N2: TMenuItem;
    mnItmKonec: TMenuItem;
    btnNastav: TButton;
    btnKonec: TButton;
    procedure FormCreate(Sender: TObject);
    procedure ListViewClick(Sender: TObject);
    procedure btnNastavitClick(Sender: TObject);
    procedure btnKonecClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  frmHlavni: TfrmHlavni;

implementation

{$R *.DFM}

procedure TfrmHlavni.FormCreate(Sender: TObject);
var
  NewColumn: TListColumn;
  NewItem: TListItem;
  I: Integer;

begin
  frmHlavni.Caption := `Ukázka práce s HotKey`;
  btnNastav.Caption := `Nastavit`;
  btnKonec.Caption := `Konec`;

  with ListView do begin
    Width := 200;
    HideSelection := False;
    ReadOnly := True;
    ViewStyle := vsReport;

    NewColumn := ListView.Columns.Add;
    NewColumn.Caption := `Položka menu`;
    NewColumn.Width := 90;

    NewColumn := ListView.Columns.Add;
    NewColumn.Caption := `Klávesová zkratka`;
    NewColumn.Width := 100;
  end;          // with ListView

  <**** Nacteni popisek polozek menu a
        klavesovych zkratek do ListView ****>
  for I := 0 to (mnItmSoubor.Count - 1) do begin
    NewItem := ListView.Items.Add;
    NewItem.Caption := mnItmSoubor.Items[I].Caption;
    NewItem.SubItems.Add(ShortCutToText(mnItmSoubor.Items[I].ShortCut));
  end;          // for

  <**** Prvni polozka je implicitne vybrana ****>
  ListView.Items[0].Selected := true;
end;

procedure TfrmHlavni.ListViewClick(Sender: TObject);
begin
  if Assigned(ListView.Selected) then begin
    HotKey.HotKey := TextToShortCut(ListView.Selected.SubItems[0]);
    HotKey.SetFocus;
  end;
end;

procedure TfrmHlavni.btnNastavitClick(Sender: TObject);
var
  I: Integer;

begin
  ListView.Selected.SubItems[0] := ShortCutToText(HotKey.HotKey);

  for I := 0 to (MnItmSoubor.Count - 1) do
    MnItmSoubor.Items[I].ShortCut :=
      TextToShortCut(ListView.Items[I].SubItems[0]);
end;

procedure TfrmHlavni.btnKonecClick(Sender: TObject);
begin
  Application.Terminate;
end;

end.

Poznámky ke zdrojovému kódu

  • V prohlížeči seznamu ListView (o kterém si podrobněji přečtete v příštím dílu) nejprve vytvoříme 2 sloupce (bylo by samozřejmě možné provést to v době návrhu, nicméně z názorných důvodů jsem tyto akce přesunul – jako obvykle – do ošetření události OnCreate hlavního formuláře).
  • Pak do tohoto prohlížeče načteme jména všech položek menu (pro jednoduchost včetně těch, které obsahují jen pomlčku) – to do položek seznamu, Items – a případné klávesové zkratky – to do tzv. podpoložek, SubItems.
  • K práci s klávesovými zkratkami používáme konverzní funkci ShortCutToText, která z vnitřní reprezentace klávesové zkratky vytvoří „normální“ text.
  • Po klepnutí na kteroukoliv položku v seznamu se její případná klávesová zkratka zkopíruje do editačního pole a toto pole také dostane zaměření (metoda SetFocus). Nyní již editační pole „zachytává“ klávesové zkratky, které stiskne uživatel.
  • Po klepnutí na tlačítko Nastavit se nastavená klávesová zkratka zkopíruje do seznamu v komponentě ListView, následně se aktualizují klávesové zkratky (vlastnosti ShortCut) všech položek přímo v hlavním menu.
  • Funkce Assigned vrací logickou hodnotu podle toho, zda proměnná (nebo ukazatel), který této funkci předáme jako parametr, obsahuje nějakou hodnotu. V našem případě jsme se chtěli pustit do nastavování klávesové zkratky pouze v případě, že ze seznamu byla nějaká položka vybrána.

Na závěr

Dnes jsme si ukázali, jak dát uživateli možnost vytvářet efektivně své vlastní klávesové zkratky. Zřejmě si dokážete představit typické použití komponenty HotKey – například do uživatelského menu vložíte položku typu „nadefinovat klávesové zkratky“ a po jejím zvolení bude otevřen nový dialog, na kterém bude umístěna nějaká variace na náš ListView (tedy vypsaný seznam aktuálních klávesových zkratek) a komponenta HotKey. Uživatel si vytvoří zkratky dle svého gusta a jakmile dialog uzavře, přiřadíte je položkám v uživatelském menu v hlavním dialogu. Je samozřejmé, že by asi nebylo od věci při ukončení aplikace aktuální stav klávesových zkratek nějakým způsobem zachovat (uložit do souboru nebo lépe do registrů – dříve či později se k tomu dostaneme, nebojte:-)), aby uživatel nemusel provádět tatáž nastavení opakovaně při každém spuštění aplikace.

V příštím díle seriálu se podíváme na komponentu ListView, o které jsme se dnes pouze zmínili a kterou jsme použili v demonstračním příkladu. Komponenta ListView je nesmírně zajímavá a jistě si zaslouží vlastní díl seriálu.

Určitě si přečtěte

Články odjinud