Tvorba kontextové nápovědy v systému Windows

Nápověda je dnes nedílnou součástí každého softwaru. Ke čtení rozsáhlé dokumentace uživatelům často chybí čas...


Nápověda je dnes nedílnou součástí každého softwaru. Ke čtení rozsáhlé
dokumentace uživatelům často chybí čas nebo chuť a právě pohotový systém
nápovědy je pak vede při zadávání dat nebo spouštění různých úloh. Nápověda tak
často plně nahradí různé příručky a další pomůcky. V následujícím textu
přinášíme několik rad pro tvorbu nápovědy v operačním systému MS Windows a v
jazyce Visual C++.
Programy v operačním systému MS Windows pracují se dvěma druhy objektů. Prvé,
tzv. objekty windows, jsou realizovány uvnitř operačního systému a programátor
s nimi komunikuje přímým voláním systému. Přitom je každému objektu přiřazen
tzv. handle, celé číslo, které je programátorovi předáno při vytvoření objektu
a kterým se později na objekt odkazuje. Program nesmí záviset na struktuře
handlu, která může být poplatná verzi systému. Objekty windows tedy nejsou
objekty programovacího jazyka a pro danou verzi OS existuje určitý počet předem
definovaných typů. Pokud pracujeme s dialogem, je zpravidla každý řídicí prvek
dialogu samostatným objektem typu okno a má přiřazen číselný identifikátor.
Pokud programátor pracuje v objektově orientovaném jazyce (např. C++), potom
může používat objekty podle definice příslušného jazyka. Při práci s objekty
windows jsou v knihovnách zpravidla používány paralelní řídicí objekty; každému
objektu windows odpovídá řídicí objekt obsahující jeho handle, programátor volá
jeho funkce a knihovna převádí tato volání na přímá volání operačního systému.
Zprávy a okna
Interaktivní programy jsou řízeny zprávami, které operační systém zasílá
uživatelskému programu např. po každé akci uživatele ve vstupním okně nebo
dialogu. Klasický interaktivní (GUI) program ve Windows obsahuje čekací smyčku
zpracovávající takové zprávy; při použití MFC je tato smyčka ukryta v
knihovních modulech a provádí volání jednotlivých funkcí řídicích objektů
paralelních k odpovídajícím windows objektům. Přitom interaktivní vývojové
prostředí (MSDE) umožňuje jednoduché přiřazení mezi zprávami, objekty a jejich
funkcemi, realizované pomocí vygenerované mapy. Umožňuje vytvářet i programy, u
kterých je vhodné usnadnění práce pomocí nápovědy (help).
Klasické interaktivní aplikace (např. součásti systému MS Office) pracují v
okně, které ovládá speciální řídicí objekt typu rámec (frame) zobrazující jedno
nebo několik podřízených oken a zajišťujících interakci s jedním nebo několika
zpracovávanými agendami (tzv. SDI a MDI aplikace Single nebo Multiple Document
Interface). Řídicí objekt je složitý a zajišťuje programátorovi řadu
vestavěných funkcí, včetně těch pro vytváření systému nápovědy. Snadno lze
potom zajistit kontextovou nápovědu pro různé položky menu, lišty nástrojů
apod., její zpracování je popsáno v systémové dokumentaci k vývojovému
prostředí MSDE.
Mnoho uživatelských aplikací nevyžaduje bohatství služeb poskytovaných rámci,
jejich hlavním oknem je dialog řízený jednodušším objektem odvozeným od třídy
CDialog. Pro takové okno je typická řada řídicích prvků (obyčejná, zaškrtávací
a rádiová tlačítka, posuvníky apod.), drobných vstupních a výstupních prvků
(statický a editovaný text, kombo box...), seznamy (prostý, řízený a stromový
seznam CListBox, CListCtrl a CTreeCtrl) a další speciální prvky. Kontextovou
nápovědou budeme rozumět nápovědu spojenou s těmito prvky. Pokud aplikace
používá několik dialogových oken (samostatně nebo prostřednictvím záložek
CTabCtrl), je někdy nutno použít dále popsanou techniku pro každý dialog
samostatně. Různé metody nápovědy
Nápovědu lze obecně realizovat několika prostředky: pomocí klasického souboru
nápovědy WinHelp typu *.hlp, pomocí HTML nápovědy (*.chm) nebo pomocí tipových
oken (tooltip).
Použití systémové funkce WinHelp je tradiční způsob nápovědy systému Windows.
Vyžaduje připravit několikastránkový (často rozsáhlý) zdrojový dokument, přitom
určitá místa označená speciální poznámkou pod čarou umožňují přímý přístup
podle kontextu, podle klíčových slov, sekvenční prohlížení (browse) nebo
textové hledání; potřebné metody jsou součástí systému. Soubor může odkazovat
na další objekty, např. bitové mapy s grafikou.
Zdrojový soubor (může jich být i několik) je převeden do formátu RTF, obvykle
exportem z vhodného textového procesoru; překladač interpretuje pouze známé
příkazy RTF, zbytek ignoruje, proto nevadí rozsáhlý balast ve vygenerovaném
souboru. Hlavní zdrojový soubor HPJ (jeho kostra je vytvořena průvodcem při
tvorbě projektu) má textový formát a na RTF soubory odkazuje; překladem vznikne
binární soubor HLP, který je zobrazován systémovým programem WinHelp.exe.
Informace je zhuštěná, proto jeho rozsah není příliš velký ani při použití
grafiky. Obsah nápovědy je obsažen v samostatném textovém souboru typu *.cnt,
který odkazuje na jednotlivé položky souboru *.hlp, lze ho vytvářet libovolným
textovým editorem, např. textovým editorem prostředí MSDE.
Vytvoření nápovědy touto technikou vyžaduje níže popsanou úpravu programů;
informace pro nápovědu je v samostatném souboru, proto umožňuje přímou kontrolu
jeho velikosti a v kritickém případě instalaci bez nápovědy. Zdrojové soubory
jsou zpracovány v klasickém textovém procesoru, ale mají poněkud nezvyklou
formu; potřebné systémové komponenty jsou společné pro všechny programy
operačního systému a technika má plnou podporu ve vývojovém prostředí a
knihovně MFC. Při využití malých okének se jeho využití přibližuje technice
tipových oken. Pro vytváření vícejazyčných verzí je možno vytvářet soubory
nápovědy individuálně pro různé jazyky.
HTML
Nápověda technikou HTMLHelp využívá pro grafickou úpravu objektů dnes běžný
formát HTML používaný v Internetu, který se stává běžnější než forma
předchozího typu. Tento způsob nápovědy využívají zejména rozsáhlé aplikace,
např. operační systém Windows, MS Office apod. Potřebné komponenty jsou
obsaženy ve vývojovém prostředí Visual C++, ale systém má menší podporu
knihovny MFC a vyžaduje přímé volání operačního systému. Umožňuje pružné
rozšíření i na rozsáhlé systémy.
Tipová okénka
Níže popsaná technika tipových okének přímo navazuje na techniku zahrnutou do
rámců, kde je nápovědu možno vytvořit jednoduše vyplněním odpovídajících
položek při interaktivní tvorbě menu či nástrojové lišty. Nemůže plně nahradit
programovou dokumentaci, pouze usnadňuje použití programu pro uživatele.
Techniku lze libovolně kombinovat s dalšími popsanými metodami. Cenou za
přátelskost programu je o málo větší velikost; text nápovědy je součástí
programu a není požadován žádný další soubor. Kvůli snadné lokalizaci programu
nebo kvůli vytváření vícejazyčných verzí je možno texty nápovědy umístit nikoli
do textu programu, ale jako textové prostředky (resources).
Klasická kontextová nápověda
Při použití klasické kontextové nápovědy je systém nejprve uveden do stavu
nápovědy, typicky stisknutím tlačítka s otazníkem v pravém horním rohu okna.
Kurzor se změní, po kliknutí myší na kterýkoli řídicí prvek je vyvolána
příslušná nápověda. Pro řádnou funkci nápovědy je nutno vybrat odpovídající
volbu během vytváření projektu pomocí průvodce (wizard), případně doplnit
odpovídající funkce dodatečně. Pokud to bude možné, použijeme pro kontextovou
nápovědu stejných mechanismů, jakých používají rámce u SDI a MDI aplikací.
Pokud ovšem dialog umožňuje minimalizaci a maximalizaci okna (to má smysl,
pokud aplikace mění polohu nebo velikost některých řídicích prvků při změně
velikosti okna), není příslušné tlačítko v horní liště k dispozici. Lze si
pomoci tak, že do dialogu umístíme speciální tlačítko (se znakem otazník),
které má stejnou funkci jako chybějící tlačítko na horní liště. Při jeho
stisknutí je spuštěna funkce, která zašle oknu stejnou zprávu jako tlačítko na
systémové liště:
void CMainDialog::OnMyhelp() { SendMessage(WM_SYSCOMMAND,SC_CONTEXTHELP,NULL);
} .
K zajištění kontextové nápovědy pro více současně viditelných dialogů stačí
jedno takové tlačítko.
Po vyvolání kontextové nápovědy je odpovídajícímu oknu odeslána zpráva
WM_HELPINFO; k jejímu zpracování slouží funkce OnHelpInfo, jíž je informace o
nápovědě předána strukturou HELPINFO. Její prvek iContextType udává, zda se
nápověda týká okna (prvku dialogu) nebo položky menu, prvek iCtrlId udává
identifikátor okna nebo položky.
Pro realizaci nápovědy je použit stejný mechanismus, jaký používají pro volání
nápovědy rámce. Souboru identifikátorů položek zdrojů resource.h je v MSDE
průvodcem přiřazen krok (custom build) pro sestavení aplikace, který každému
identifikátoru začínajícím IDM_ přiřadí odpovídající identifikátor začínající
HIDM_ zvětšený o hodnotu 0x10000, identifikátorům IDR_ a _IDD_ identifikátor
HIDR_ a HIDD_ zvětšený o 0x20000 apod. Takto vzniklý soubor identifikátorů s
koncovkou .hm je použit při následném překladu zdrojového souboru nápovědy.
Pokud příslušným prvkům dialogu přiřadíme identifikátory IDD_..., je nutno do
zdrojového souboru nápovědy umístit odpovídající text označený poznámkou
#HIDD_...; při volání nápovědy potom stačí zvětšit identifikátor prvku o
0x20000 a předat funkci WinHelp aplikace, která vyvolá odpovídající položku
nápovědy. Příslušná funkce může vypadat takto:
BOOL CMainDialog::OnHelpInfo(HELPINFO* pHelpInfo) { if(pHelpInfo->iContextType
== HELPINFO_WINDOW) { AfxGetApp()->WinHelp(pHelpInfo->iCtrlId +
0x20000L,HELP_CONTEXT); return true; } // ........
return CDialog::OnHelpInfo(pHelpInfo);
}
Pokud ve funkci WinHelp použijeme jako druhý argument hodnotu
HELP_CONTEXTPOPUP, je nápověda zobrazena místo hlavního okna v malém okně v
místě kurzoru; text nápovědy pak musí být ve zdrojovém souboru na samostatné
stránce. Přímým voláním systému ::WinHelp lze dosáhnout dalších efektů.
Dialog tak vlastně byl doplněn o stejnou funkci, kterou u SDI a MDI aplikací
zajišťoval rámec. Při práci s několika vnořenými dialogy (např. při použití
záložek) stačí doplnit funkci pro hlavní dialog (hlavní okno), který obslouží
všechny dialogy programu.
Stejný mechanismus je možno použít pro kontextovou HTML nápovědu systémovým
voláním ::HTMLHelp; ale podpora tohoto přístupu z MFC je menší. Osobně jsem to
v praxi nevyzkoušel. Použití tipových oken
Jinou technikou nápovědy jsou tipová okna. Pokud jsou aktivní a uživatel umístí
kurzor na určitý kontrolní prvek, objeví se po chvíli malé okénko s jeho
stručným popisem. K vytváření takové nápovědy slouží objekty třídy
CToolTipCtrl, které je nutno umístit do každého z dialogů. Proto je nezbytné:
lDo řídicího objektu dialogu (jeho třída je odvozena od CDialog) umístit objekt
třídy CToolTipCtrl, v příkladech ho nazveme m_toolTip.
lVe funkci OnInitDialog řídicího objektu dialogu zavolat funkci
m_toolTip.Create(this), parametrem je ukazatel na rodičovské okno.
lPro každý kontrolní prvek, pro který požadujeme nápovědu, vytvořit nástroji
MSDE v řídicím objektu dialogu jeho řídící objekt a v jeho funkci OnInitDialog
zavolat m_toolTip.AddTool(CWnd* p1,LPCTSTR p2). Prvým parametrem p1 je ukazatel
na řídicí objekt prvku, druhým parametrem p2 text zobrazovaný v tipovém okně.
lObjektu m_toolTip je nutno předávat relevantní zprávy z rodičovského okna
pomocí procedury dialogu:
BOOL CMainDialog::PreTranslateMessage(MSG* pMsg) { If (pMsg->message ==
WM_LBUTTONDOWN || pMsg->message == WM_LBUTTONUP || pMsg->message ==
WM_MOUSEMOVE ) m_toolTip.RelayEvent(pMsg);
return CDialog::PreTranslateMessage(pMsg);
}
Nevadí, pokud předáme objektu i irelevantní zprávy, ty jsou odfiltrovány, ale
nesmíme vynechat žádnou významnou zprávu.
Pokud úloha obsahuje více dialogů, je nutno zopakovat postup pro každý z nich.
Několik doporučení
Soubor nápovědy vznikne překladem souboru typu *.hpj odkazujícího na vlastní
zdrojový soubor typu *.rtf. Ten lze nejsnáze vytvářet či upravovat exportem z
textového procesoru MS Word. Poslední verze procesoru pracující interně s kódem
UNICODE (Word 97/2000) při exportu do formátu rtf generuje během konverze do
8bitové reprezentace řadu kódových tabulek bez viditelné logiky; při překladu
tohoto textu vznikají ve vygenerovaném hlp souboru různé artefakty. Pokud tedy
dokument fakticky používá pouze znakovou sadu Latin2, doporučuji nahradit ve
výsledném rtf kódu pro všechny příkazy "fcharset" kód znakové sady číslem 238
odpovídající sadě Latin2. Při jednorázové akci to lze provést ručně, při
častějších úpravách doporučuji napsat na to jednoduchý program.
Pokud chceme opravovat přímo soubor ve formátu rtf, nelze použít ani MS Word
ani WordPad, které soubor automaticky konvertují do grafické podoby. Lze použít
NotepPad (pro malé soubory) nebo editor prostředí MSDE, když při otevření
specifikujeme formát text (položka Open as).
K obsahu nápovědy, vyhledávání podle klíčových slov (pokud jsme je do zdrojové
formy zařadili) nebo textovému vyhledávání má uživatel přístup po spouštění
nápovědy pro libovolnou kontrolu. Přístup lze též umožnit ze systémového menu,
kam lze doplňovat položky stejně, jako to dělá průvodce při vytváření aplikace
s dialogem "About..." . Podrobněji viz funkce OnInitDialog hlavního okna
aplikace a identifikátor IDM_ABOUTBOX. Přístup umožní opět funkce WinHelp
aplikace.
Pokud chceme doplnit nápovědu k již hotovému projektu, je možno průvodcem
vygenerovat prázdný projekt se shodnými parametry a systémem nápovědy a
příslušné komponenty přenést do výsledného projektu. Přitom je nutno
respektovat následující pravidla:
lKromě zdrojového textu v jazyce C/C++ je nutno přenést i komentáře používané
průvodcem tříd označených komentářem "//{{ ... //}}", jinak nebude možno
používat řadu funkcí MSDE. Pokud jsou měněna jména tříd, je nutno je změnit i v
těchto komentářích. Takové chyby nevadí při překladu, ale blokují použití
průvodce tříd (class wizard).
lPokud není po úpravách v pořádku interní popis tříd, je nutno zrušit
odpovídající soubor typu *.clw, spustit průvodce tříd a nechat soubor vytvořit
znovu.
lJe nutno přenést sestavovací kroky pro některé soubory (resource.h, *.hpj) do
schématu sestavení úlohy (nastavení settings) v seznamu souborů. Dávkový popis
zpracování souborů v dialogu "Nastavení..." ("Settings...") je možno přenášet
přes schránku. Podrobnější popis zdrojového souboru nápovědy a jiné detaily lze
samozřejmě najít v původní dokumentaci k prostředí MSDE.
1 0861 / pen









Komentáře
K tomuto článku není připojena žádná diskuze, nebo byla zakázána.