2. Podpora ”inteligentních” formulářů

Pro co nejsnadnější manipulaci s daty se vždy snažíme vytvořit co nejlepší formuláře. V této kapitole je popsáno několik typických postupů, které usnadňují uživateli práci s daty.

2.1 Automatická změna velikosti objektu

V některých aplikacích je požadováno zobrazení tolika položek (objektů) ve formuláři, že je stěží umístíme na obrazovku. Často musíme omezit velikost objektu na minimum, což zejména u různých poznámek znamená, že není možné vidět celý jejich obsah. To je nepříjemné zejména při editaci jejich obsahu. Řešením je např. zajištění automatického zvětšení velikosti objektu při vstupu do něj a opětovné zmenšení po jeho opuštění, jak ukazuje následující obr. 6.

Obr. 6. Automatické zvětšení objektu formuláře

Změnu velikosti realizuje následující funkce.

Function VelikostObjektu (Jmeno As String, RLeft As Variant, RTop As Variant, RWidth As Variant, RHeight As Variant, REnabled As Integer, RLocked As Integer, Vstup As Integer)
' *********************************************************************
' Funkce v aktuálním formuláři nastaví velikost určeného objektu
' a nastaví jeho vlastnosti Enabled a Locked. Parametr Vstup
' určuje, zda systém vstoupí do objektu
' *********************************************************************
Dim F As Form, C As Control, I As Long
Set F = Screen.ActiveForm
For I = 0 To F.Count - 1
    If F(I).Name = Jmeno And Len(F(I).Name) = Len(Jmeno) Then
        ' Objekt nalezen
        Set C = F(I)
        C.Left = RLeft * 567
        C.Top = RTop * 567
        C.Width = RWidth * 567
        C.Height = RHeight * 567
        C.Locked = RLocked
        If Vstup Then
            ' Požadován vstup do objektu
            C.Enabled = True
            DoCmd GoToControl Jmeno
        Else
            C.Enabled = REnabled
        End If
        Exit Function
    End If
Next I
End Function

Dostává v parametrech nejen název objektu (míní se automaticky objekt aktuálně otevřeného formuláře) a požadovanou velikost, ale také požadavky na nastavení vlastností Enabled a Locked. Nesmíme totiž zapomínat na možnost součinnosti této funkce se systémem hromadného zamykání objektů ve formuláři. Na obr. 7 pak vidíme konkrétní připojení funkce do objektu ”Poznamka” s uvažováním možného uzamčení změn (vlastnost Locked). Je zřejmé, že při tomto způsobu připojení musí být vlastnost Enabled nutně při vstupu do objektu nastavena na hodnotu True, jinak by do objektu vůbec nemohl vstoupit kurzor a tudíž by událost On Enter vůbec nenastala.

Obr. 7. Připojení funkce pro automatickou změnu velikosti objektu

V popsaném přístupu nebyl využit parametr Vstup popsané funkce. Slouží pro případ, že zvětšování objektu je vyvoláno např. obslužným tlačítkem. opětovné zmenšení objektu můžeme přitom řešit obsluhou události On Exit. Vnucením vstupu kurzoru do objektu zajistíme, že po opuštění objektu se jeho velikost opět zmenší.

Z praktických zkušeností s používáním této funkce vyplývá vhodnost prodlužovat objekt směrem dolů a doprava. Kurzor a začátek obsahu objektu se totiž po změně rozměrů objektu nepřesouvají. Pokud by se objekt zvětšil směrem nahoru nebo doleva, došlo by k přesunu textu, což je uživatelem vnímáno jako rušivý moment. Rovněž je vhodné zvětšovat všechny objekty ve formuláři stejným směrem. ”Skákání” objektů pokaždé jinam je rovněž velmi rušivé.

2.2 Doplnění nabídky o možnost ”Vše”

Velmi častým požadavkem, je možnost vybírat pro zobrazení ve formuláři jen záznamy zvoleného typu (ten je dán hodnotou některé položky). Přitom je však žádoucí také možnost zobrazit jednoduše také všechny záznamy bez ohledu na typ. Možné řešení vidíme na obr. 8.

Obr. 8. Nabídka doplněná o možnost ”Vše”

Tento problém je ukázkově řešen v databázi SOLUTIONS.MDB, následující postup řešení z této ukázky vychází. Především vytvoříme objekt typu Combo Box pro volbu požadovaného typu. Jeho základní vlastnosti vidíme na obr. 9. Jeho zdrojem by za normálních okolností byl dotaz vracející dvě položky, první obsahuje popis typu, druhá číslo typu (v rozsahu 1 - n). Ukládá se přitom hodnota druhá. Budeme usilovat o to, aby seznam hodnot byl doplněn možností ”Vše”, vracející hodnotu nula. Ta je proto také nastavena jako implicitní hodnota, neboť po otevření formuláře budou zobrazeny všechny záznamy, je proto vhodné, aby výběrový objekt obsahoval také text ”Vše”.

Jako zdroj objektu vidíme text ”SeznamTypu”. Takovou možnost ovšem systém MS-Access pro tuto vlastnost vůbec nenabízí, nutně musela být vložena autorem. I když to ze zápisu není zřejmé, jedná se o volání funkce uvedeného jména (byť chybí zadání parametrů).

Z výpisu funkce je zřejmá také její činnost na jednotlivé požadavky.

Obr. 9. Vlastnosti objektu pro volbu typu zobrazených záznamů
Function SeznamTypu (MyComboBox As Control, ID As Long, Row As Long, Col As Long, Code As Integer) As Variant
' *************************************************
' Funkce pro generování seznamu typů majetku
' včetně nabídky "Vše"
' *************************************************
Static MyDB As Database, MyRecordset As Recordset
Dim X As Long

Select Case Code
    '  Initializace, naplnění datového zdroje
    Case LB_INITIALIZE
        Set MyDB = DBEngine.Workspaces(0).Databases(0)
        Set MyRecordset = MyDB.OpenRecordset("Select [Popis],[Typ] From [TMajetekTypy];")
        SeznamTypu = True
    '  Otevření objektu
    Case LB_OPEN
        SeznamTypu = Timer
    '  počet řádků (ve skutečnosti má být poslední záznam z TmajetekTypy ignorován, jinak by v nabídce chyběl nebo bylo nutné přičíst 1)
    Case LB_GETROWCOUNT
        MyRecordset.MoveLast
        SeznamTypu = MyRecordset.RecordCount
    '  Nastavení počtu sloupců
    Case LB_GETCOLUMNCOUNT
        SeznamTypu = 2
    '  Nastavení šířky sloupce
    Case LB_GETCOLUMNWIDTH
        SeznamTypu = -1
    '  Vrácení konkrétních dat
    Case LB_GETVALUE
        '  První řádek je "Vše"
        If Row = 0 Then
            If Col = 0 Then
                SeznamTypu = "Vše"
            Else
                SeznamTypu = 0
            End If
        Else
            '  Ostatní řádky jsou naplněny z datového zdroje
            MyRecordset.MoveFirst
            For X = 1 To Row - 1
                MyRecordset.MoveNext
            Next X
            If Col = 0 Then
                SeznamTypu = MyRecordset.[Popis]
            Else
                SeznamTypu = MyRecordset.[Typ]
            End If
        End If
    '  Uzavření datového zdroje
    Case LB_END
        MyRecordset.Close
End Select
End Function

Realizace výběru požadovaného typu záznamů je připojena jako procedura pro obsluhu události After Update:

Sub PTyp_AfterUpdate ()
'  Po nastavení hodnot
If Me![PTyp].Column(1) = 0 Then
    DoCmd ShowAllRecords
Else
    DoCmd ApplyFilter , "[Typ] = Forms![FMajetek]![PTyp]"
End If
End Sub

2.3. Zobrazení úvodního obrázku

V některých aplikacích požadujeme po otevření zobrazení úvodního obrázku. Pomíjíme přitom možnost zobrazit úvodní obrázek při spuštění úlohy jeho uvedením v inicializačním souboru. Tento požadavek realizujeme vytvořením speciálního formuláře. Nazvěme ho např. StartupScreen.

Ze zkušeností víme, že uživatelé jsou často znechuceni opakovaným zobrazováním úvodního obrázku při každém spuštění úlohy. Proto je vhodné umožnit zákaz zobrazování úvodního obrázku. Příklad jeho realizace je uveden na obr. 10.

Obr. 10. Úvodní obrázek úlohy

Na obr. 12 vidíme základní vlastnosti formuláře pro úvodní obrázek. jeho zdrojem je tabulka Options, viz obr. 11, s jedinou položkou ShowStartupScreen typu Yes/No, která je připojena do CheckBoxu v dolní části obrazovky.

Obr. 11. Definice tabulky Options

Otevření formuláře realizujeme v makru Autoexec pomocí funkce OpenStartupScreen(). Uzavření obrázku je realizováno obsluhou události On Timer (čas otevření je nastaven na 7000 milisekund). Při uzavření formuláře je spuštěna funkce CloseStartupScreen(), která otevře hlavní obslužný formulář úlohy.

Všimněte si zejména nastavení názvu hlavního obslužného formuláře úlohy v modulu MODStartupScreen, jehož výpis následuje.

Obr. 12. Vlastnosti formuláře úvodního obrázku
Option Compare Database   'Use database order for string comparisons
Option Explicit


' *********************************************************
' Systém pro obsluhu úvodní obrazovky otevírané v systému
' Copyright (C) 1996 Ing. Radim Farana, CSc.
' *********************************************************

'Systém vyžaduje existenci objektů:
'Tabulka "Options" s položkou "ShowStartupScreen" typu Yes/No
'Formulář "StartupScreen" se zdrojem "Options" a objektem
'připojujícím položku ShowStartupScreen

' Globální konstanta s názvem hlavního obslužného formuláře

Const FirstForm = "FHlavni"

'Seznam procedur:
'Function CloseStartupScreen ()
' ********************************************
' Obsluha otevření úvodní obrazovky
' ********************************************
'Function OpenStartupScreen ()
' ********************************************
' Obsluha otevření úvodní obrazovky
' ********************************************

Function CloseStartupScreen ()
' ********************************************
' Obsluha otevření úvodní obrazovky
' ********************************************
DoCmd OpenForm FirstForm
End Function

Function OpenStartupScreen ()
' ********************************************
' Obsluha otevření úvodní obrazovky
' ********************************************
Dim D As Database, R As Recordset, V As Integer

Set D = DBENGINE(0)(0)
Set R = D.TableDefs("Options").OpenRecordset()

On Error GoTo Err_OpenStartupScreen
If R.Fields("ShowStartupScreen").Value = False Then
    DoCmd OpenForm FirstForm
Else
    DoCmd OpenForm "StartupScreen"
End If

Exit Function
Err_OpenStartupScreen:
    ' Chyba - neexistuje požadovaná vlastnost
    R.AddNew
    R("ShowStartupScreen") = True
    R.Update
    R.MoveFirst
    Resume Next
End Function

2.4. Posloupnost otevírání formulářů

Obvyklý požadavek při práci se systémem je jednoznačná hierarchie otevírání formulářů s nemožností dostat se zpět do dříve otevřeného formuláře bez toho, aby byl později otevřený formulář uzavřen.

K řešení tohoto požadavku slouží vlastnost Modal s hodnotou True, která zajistí, že formulář nedovolí přechod do dříve otevřených formulářů. Pro vedlejší formulář máme k dispozici několik možných postupů.

  1. na obr. 13 je ukázka stavu, kdy hlavní formulář je otevřen přes celé okno systému, má připojeno uživatelské menu a pomocný formulář byl při otevření otevřen jako Dialog. To znamená, že:

Obr. 13. Formulář s pomocným formulářem (Dialog)
  1. Právě nepřítomnost uživatelského menu a viditelnost části hlavního formuláře způsobuje, že často pomocný formulář otevíráme bez nastavení Window Mode. Pak musí mít pomocný formulář nastavenu vlastnost Modal = True. Pokud požadujeme nepřítomnost tlačítek pro minimalizaci a maximalizaci, dosáhneme toho nastavením vlasností Min Button = False, Max Button = False a případně i Control Button = False. Pak by se vzhled pomocného formuláře měl od předchozího případu lišit jen přítomností svého vlastního menu a otevřením přes celé okno systému. Bohužel tomu tak není a tlačítko pro Restore (tedy nastavení okna do obvyklé velikosti) je stejně přítomno, a je možno ovlivnit velikost všech formulářů v systému.

Zmenšení pomocného formuláře pomocí Restore nám obvykle nevadí, potíž je s tím, že tím současně proběhne zmenšení hlavního formuláře. Pro zajištění zobrazení hlavního formuláře vždy přes celé okno systému můžeme na obsluhu události On Activate hlavního formuláře připojit makropříkaz Maximize. Po návratu z pomocného formuláře tato událost nastane a okno bude opět zvětšeno. Bohužel však dojde k porušení modality hlavního okna (je možno se z něj dostat do dříve otevřených oken).

Zvětšení hlavního okna musíme zajistit při obsluze uzavření pomocného okna, jak je naznačeno na obr. 14 (pomocný formulář na ukázce má nastavenu vlastnost Border Style = Dialog a při jeho otevření byl proveden makropříkaz Restore). Stejně tak počáteční zvětšení hlavního formuláře nesmí být připojena k obsluze události On Open tohoto formuláře, ale k obsluze události, která vyvolala otevření hlavního formuláře.

Obr. 14. Formulář s pomocným formulářem