U databázových aplikací se často pracuje ještě s kontrolou při zápisu do databáze, a to jak na úrovni aplikace, tak i na úrovni databáze. Připomínám, že v řadě případů se snažíme volit takové ovládací prvky, které z principu neumožňují chybné zadání - volby, přepínače, výběr z připraveného menu apod.
Podíváme se zde na některé problémy kontroly zadávaných údajů, především ve vztahu k uživateli programu. Jako příklad použijeme ve všech případech kontrolu na zadání celého čísla.
Připravte si pro toto procvičení nový projekt - jako základ vezměte
již dříve použité téměř prázdné hlavní okno, z něhož se zobrazuje druhé,
modální okno. (Modálním oknům se často říká dialogová, i když to není zcela
přesné.) Do tohoto dialogu umístěte čtyři (stejná) editační pole - objekty
typu TEdit a dvě tlačítka pro ukončení dialogu OK
a
Cancel
(typu TButton nebo jednodušeji TBitBtn
z palety Additional
).
K těmto editačním polím postupně přidávejte jako události následující kontroly na to, zda uživatel skutečně zapisuje do editačního pole číselnou hodnotu.
if not (Key in ['0'..'9',#8]) then begin Key:=#0;MessageBeep(0); end;Stisknutá klávesa je uložena v parametru Key; obsluha události může tuto hodnotu změnit. Nezapomeňte do seznamu kláves zahrnout minimálně Backspace, příp. znaménko, mezeru apod. Tuto kontrolu lze "obelstít" přenesením údajů přes schránku.
{ Získej text z editačního pole } Val(Edit2.Text, I, Code); { Chyba? } if Code <> 0 then MessageDlg('Chyba na pozici: ' + IntToStr(Code), mtWarning, [mbOk], 0);Obecně tento způsob kontroly není příliš vhodný. Kromě toho lze pole i formulář opustit i s nesprávně zadanou hodnotou.
{ Získej text z editačního pole } Val(Edit3.Text, I, Code); { Chyba? } if Code <> 0 then begin MessageDlg('Chybná hodnota v editačním poli', mtWarning, [mbOk], 0); Edit3.SetFocus; end;Tento způsob kontroly je třeba považovat za základní. Při nalezení chyby je žádoucí vrátit kurzor do chybně vyplněného pole - voláním metody SetFocus tohoto editačního pole. Je však třeba dát pozor na to, aby uživatel měl možnost zjistit alespoň nějakou "přijatelnou" hodnotu, jinak není možné tento formulář opustit.
Návod: Jako obsluhu příslušných událostí použijte již existující obsluhy
událostí - místo zápisu nové obsluhy vyberte v Inspektoru objektů již
existující obsluhu z menu. Tyto existující obsluhy je třeba upravit tak,
aby odkaz na konkrétní editační pole (tj. Edit1 apod.) byl nahrazen
odkazem na "zasílatele" příslušné zprávy (např. o tom, že nastala změna
v editačním poli), který je obsažen v parametru Sender většiny
událostí. Používáme konstrukci (Sender as TEdit).Text
,
protože parametr Sender
je typu TObject a většina
použitých vlastností (např. Text
) je definována až u konkrétního
ovládacího prvku.
if Save then try a:=StrToInt(Edit1.Text)+StrToInt(Edit2.Text)+StrToInt(Edit3.Text)+StrToInt(Edit4.Text); if a<50 then begin ShowMessage('Součet zadaných hodnot musí být alespoň 50'); CanClose:=false; end; except on EConvertError do begin CanClose:=false; ShowMessage('Něco je špatně'); end; end;
Běžně chceme uživateli umožnit i opuštění formuláře bez uložení - když uživatel nemá data nebo si s formulářem neví rady. Zavedeme dvě tlačítka pro ukončení a rozlišíme je od sebe přiřazením hodnoty logické proměnné Save - tuto proměnnou definujeme většinou jako privátní položku příslušného okna. Přidejte ještě dotaz potvrzující opuštění formuláře bez uložení dat - využijte vlastnosti Modified editačního pole.
Poznámka: Standardní mechanismus pro rozlišení toho, kterým tlačítkem uživatel ukončil dialog, je přes vlastnost ModalResult prvku typu TButton - tato hodnota je vrácena jako výsledek funkce ShowModal, kterou zobrazujeme dialog. Tuto hodnotu se však dozvíme až po vyvolání funkce ShowModal a nemůžeme jí tedy přímo využít už při provádění události OnCloseQuery.
Kromě konstrukcí známých z dřívějška jsme na ukázku použili konstrukci try ... except on ... end, která využívá mechanismus tzv. výjimky, s nimiž se seznámíme příště. Mechanismus je zhruba takový, že při chybě v části try se předá řízení na část except on, kde je obsluha (předpokládaných) chyb. Zbývající část v příkazu try se již neprovádí.