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

Computerworld 12(2001) číslo 21, strana 19-20.

N

ápověda je dnes nedílnou součástí kultury interaktivního software. Rozsáhlou dokumen­taci, kterou často uživatel programů nemá čas nebo není ochoten číst, nahradí pohotový systém nápovědy, který uživatele vede při zadávání dat a spouštění úloh a často plně nahradí různé příručky a jiné pomůcky. Uvedeme několik rad pro tvorbu nápovědy v operačním systému MS Windows a jazyce Visual C++.

 

Jiří Šoler

 

Řídicí objekty a objekty windows

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 komu­nikuje přímým voláním systému. Přitom každému objektu je 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 záviset na 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ý řídící 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.

Interaktivní programy jsou řízeny zprávami, které operační systém zasílá uživatel­skému programu např. po každé akci uživatele ve vstupním okně nebo dialogu. Klasický in­teraktivní (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, realizo­vané 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. SDIMDI 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ápo­vě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 radiová tlačítka, posuv­níky apod.), drobných vstupních a výstupních prvků (statický a editovaný text, kombo box, …), seznamy (prostý, řízený a stromový seznam CListBox, CListCtrlCTreeCtrl) 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 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í sys­tému. Soubor může odkazovat na další objekty, např. bitové mapy s grafikou. Zdrojový sou­bor (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ů; in­formace pro nápovědu je v samostatném souboru, proto umožňuje přímou kontrolu jeho veli­kosti a v kritickém případě instalaci bez nápovědy. Zdrojové soubory jsou zpracovány v kla­sickém textovém procesoru, ale mají poněkud nezvyklou formu; potřebné systémové kompo­nenty 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ápo­vědy individuálně pro různé jazyky.

Nápověda technikou HTMLHelp využívá pro grafickou úpravu objektů dnes běžný for­má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.

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 in­teraktivní 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. Pro snadnou lokalizaci programu nebo vytváření vícejazyčných verzí je možno texty nápovědy umístit místo do textu programu 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ápo­vědy, typicky stisknutím tlačítka s otazníkem v pravém horním rohu okna. Kurzor se změní, po stisknutí myši nad kteroukoliv kontrolou 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 SDIMDI aplikací.

Pokud ovšem dialog umožňuje minimalizaci a maximalizaci okna (to má smysl, pokud aplikace mění polohu nebo velikost některých kontrol 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, které je informace o ná­povědě předána strukturou HELPINFO. Její prvek iContextTypeudává, zda se nápověda týká okna (prvku dialogu) nebo položky menu, prvek iCtrlId udává identi­fiká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 0x10000, identifikáto­rům IDR_ a _IDD_ identifikátor HIDR_ a HIDD_ zvětšený o 0x20000 apod. Takto vzniklý soubor s identifikátorů 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 musí ve zdrojovém souboru být na samostatné stránce. Přímým voláním systému ::WinHelp lze dosáhnout další efekty.

Vlastně tak byl dialog doplněn o stejnou funkci, kterou u SDIMDI aplikací zajišťo­val 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ší a autor 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í kur­zor 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ů. Je nutno:

1)     Do řídicího objektu dialogu (jeho třída je odvozena od CDialog) umístit objekt třídy CTool­TipCtrl, v příkladech ho nazveme m_toolTip.

2)     Ve funkci OnInitDialog řídicího objektu dialogu zavolat funkci m_toolTip.Create(this), parametrem je ukazatel na rodičovské okno.

3)     Pro 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ě.

4)     Objektu m_toolTip je nutno předávat relevantní zprávy z rodičovského okna pomocí proce­dury 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.

5)     Pokud úloha obsahuje více dialogů, je nutno zopakovat postup pro každý z nich.

 

Několik doporučení

1.     Soubor nápovědy vznikne překladem souboru typu *.hpj odkazujícího na vlastní zdro­jový 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, Word 2000) při exportu do formátu rtf generuje během konverze do 8-bitové reprezentace řadu kódových tabulek bez viditelné logiky; při překladu tohoto textu vzni­kají 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 jed­noduchý program.

2.     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).

3.     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 li­bovolnou kontrolu. Přístup lze též umožnit ze systémového menu, kam lze doplňovat po­ložky stejně, jako to dělá průvodce při vytváření aplikace s dialogem "About …" . Podrob­něji viz funkce OnInitDialog hlavního okna aplikace a identifikátor IDM_ABOUTBOX. Pří­stup umožní opět funkce WinHelp aplikace.

4.     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:

5.     Podrobnější popis zdrojového souboru nápovědy a jiné detaily lze najít v původní dokumen­taci k prostředí MSDE.

 

Přechod na domovskou stránku