# 20.4 實現聯機幫助
雖然你應該盡可能的將你的應用程序界面設計的非常直觀,以便用戶根本不需要使用聯機幫助,但是除了那些最最簡單的應用程序外,對于大多數應用程序來說,提供聯機幫助都是一個非常重要的事情.你可以提供PDF版的幫助文件或者是HTML格式的幫助文件以便用戶可以使用他最習慣的方式瀏覽,不過如果你能夠借助于某種幫助制作手段,使得你的聯機幫助中的主題直接和對話框或者你的主窗口中的控件聯系起來,這會讓你的用戶感覺更好.
wxWidgets提供了幫助控制器,你的應用程序可以使用它來加載和顯示幫助文件中的主題,它主要包括下面幾個類:
* wxWinHelpController,這個類用來提供對windows平臺的基于RTF格式的幫助文件(擴展名為.hlp)的支持. 這中格式現在已經不推薦使用了,新的用來代替它的類是wxCHMHelpController.
* wxCHMHelpController, 用來提供對windows平臺的MS HTML幫助文件(擴展名是.chm)的支持.
* wxWinceHelpController,用來提供對WindowsCE上的幫助文件(擴展名是.htm)的支持.
* wxHtmlHelpController, 用來提供對wxWidgets自定義的HTML幫助文件(擴展名是.htb)的支持.
wxHtmlHelpController類和別的幫助控制類是不同的,別的類都只是封裝了那個平臺上相應的本地實現,而這個類是和 wxWidgets的幫助實現機制集成在一起的,和主程序屬于同一個進程.如果你想以不同進程的方式使用wxWidgets提供的幫助文件,你可以編譯 wxWidgets自帶的utils/src/helpview目錄下的HelpView程序.其中文件remhelp.h和remhelp.cpp實現了一個遠程幫助文件控制器(wxRemoteHtmlHelpController),你可以將它和你的應用程序鏈接在一起,以便你的應用程序可以遠程控制位于別的進程的幫助文件控制器實例.
注意到目前為止,還沒有實現對Mac OSX平臺上的幫助文件的支持,在這個平臺上,你可以使用通用的wxWidgets HTML格式的幫助文件.
下面的兩副圖演示了Windows平臺上同時顯示MS HTML格式的幫助文件和wxWidgets的HTML幫助文件的樣子.它們兩個的外觀很相似,都是右邊顯示HTML幫助的內容,左邊則顯示主題的繼承關系以及一個用來搜索主題的文本框.稍微有一點不同的是:wxWidgets格式的幫助控制器可以同時加載多個幫助文件.


使用幫助控制器
一般說來,你需要創建一個幫助文件控制器并且在整個應用程序的生命周期維護它,通常是在應用程序類中保存一個指針,在OnInit函數中初始化,在OnExit函數中釋放.之所以使用指針是因為你可以自己控制什么時候釋放這個指針,某些幫助控制器是依賴于某種動態鏈接庫類的,這個類在應用程序對象被釋放以后就不存在了.在創建這個幫助控制器指針以后,使用其Initialize指定一個幫助文件.你可以不用提供文件的擴展名, wxWidgets將會提供針對當前平臺的擴展名,比如:
```
#include "wx/help.h"
#include "wx/fs_zip.h"
bool MyApp::OnInit()
{
...
// wxWidgets HTML需要這個
wxFileSystem::AddHandler(new wxZipFSHandler);
m_helpController = new wxHelpController;
m_helpController->Initialize(helpFilePath);
...
return true;
}
int MyApp::OnExit()
{
delete m_helpController;
...
return 0;
}
```
注意這里我們讓wxWidgets自己決定使用哪個幫助控制器類: wxHelpController在Windows平臺上定義為wxCHMHelpController,而在別的平臺上則定義為 wxHtmlHelpController.你可以在windows平臺上也使用wxHtmlHelpController類,不過最好是盡可能使用本地平臺提供的幫助控制器.
一旦幫助控制器初始化成功,你就可以使用下面的函數顯示相應的幫助了:
```
// 顯示幫助內容
m_helpController->DisplayContents();
// 顯示標題為"Introduction"的主題
m_helpController->DisplaySection(wxT("Introduction"));
// 顯示包含在指定文件中的幫助主題.
m_helpController->DisplaySection(wxT("wx.html"));
// 顯示指定ID的主題(僅適用于WinHelp和MS HTML Help)
m_helpController->DisplaySection(500);
// 查找關鍵字
m_helpController->KeywordSearch(wxT("Getting started"));
```
通常情況下,你將在幫助菜單的事件處理函數中調用DisplayContents,也許在幫助菜單中你還會列舉出其它的重要的主題,你可以在其對應的事件處理函數中使用DisplaySection函數,如果你希望通過標題使用DisplaySection函數,那么所有的標題必須是不重復的.
可能你還打算在所有的自定義對話框上增加一個幫助按鈕,以便用來顯示針對這個對話框的幫助主題.然而,這里有一個需要注意的事情:不是所有的平臺都支持從一個模式對話框的事件處理函數中顯示幫助.當幫助文件是通過一個外部程序顯示的時候(比如Windows平臺的 wxCHMHelpController),你可以放心的在模式對話框中調用幫助控件,但是如果幫助控制器只是在本進程中通過一個非模式對話框顯示幫助文件時(比如wxHtmlHelpController),你必須小心,因為通常我們不可以在一個模式對話框中創建一個非模式的frame窗口.模式對話框不允許你切換到另外一個非模式的對話框中.在wxGTK平臺上,這種行為僅對于wxHtmlHelpController來說是可以的,但是在Mac OS X平臺上,這種行為是不允許的,這時你可以使用前面介紹的使用自己編譯的HelpView程序等外部程序來顯示幫助文件,或者使用模式對話框來顯示幫助文件,后一種方法我們稍后會進一步描述.
擴展wxWidgets HTML幫助
wxWidgets的HTML幫助系統確實是很不錯的,不過它有兩個問題:首先,它只能在自己的frame窗口中顯示幫助,因此你不可以在你的主窗口的某個TAB控件中顯示幫助文件,另外一個缺陷是前面提到過的在模式對話框中使用的問題.
為了解決這兩個問題而對wxWidgets HTML幫助系統進行的一個擴展將wxWidgets的幫助顯示在一個自定義的窗口中,這個窗口可以是任何類型窗口的子窗口.你可以從光盤的 examples/chap20/htmlctrlex目錄中或者ftp: //biolpc22.york.ac.uk/pub/contrib/helpctrlex獲取它的源代碼.
如果你將它集成進你的應用程序,你可以將wxHtmlHelpWindowEx窗口集成進你的主窗口,然后使用wxHtmlHelpControllerEx類來對它進行和別的控制器一樣的控制來顯示幫助內容,下面是一個例子:
```
#include "helpwinex.h"
#include "helpctrlex.h"
bool MyApp::OnInit()
{
...
m_embeddedHelpController = new wxHtmlHelpControllerEx;
m_embeddedHelpWindow = new wxHtmlHelpWindowEx;
m_embeddedHelpWindow->SetController(m_embeddedHelpController);
m_embeddedHelpController->SetHelpWindow(m_embeddedHelpWindow);
m_embeddedHelpController->UseConfig(config, wxT("EmbeddedHelp"));
m_embeddedHelpWindow->Create(parentWindow,
wxID_ANY, wxDefaultPosition, wxSize(200, 100),
wxTAB_TRAVERSAL|wxNO_BORDER, wxHF_DEFAULT_STYLE);
m_embeddedHelpController->AddBook(wxT("book1.htb"));
m_embeddedHelpController->AddBook(wxT("book2.htb"));
return true;
}
int MyApp::OnExit(void)
{
if (m_embeddedHelpController)
{
m_embeddedHelpController->SetHelpWindow(NULL);
delete m_embeddedHelpController;
}
...
return 0;
}
```
而為了解決模式對話框的問題,你可以使用wxModalHelp類來在模式對話框中顯示某個幫助主題.當用戶看完幫助以后,需要使用關閉按鈕關閉這個幫助對話框,然后焦點才會重新返回上一個模式對話框中去.下面的代碼就是你所需要作的全部:
```
wxModalHelp help(parentWindow, helpFile, topic);
```
在同一個程序使用兩種不同的方法來顯示幫助有時候是很不方便的,這時候你可以使用下面的函數來節約一些代碼:
```
// 如果modalParent不為空,則使用模式幫助顯示方法,否則就使用普通的方法.
void MyApp::ShowHelp(const wxString& topic, wxWindow* modalParent)
{
#if USE_MODAL_HELP
if (modalParent)
{
wxString helpFile(wxGetApp().GetFullAppPath(wxT("myapp")));
wxModalHelp help(modalParent, helpFile, topic);
}
else
#endif
{
if (topic.IsEmpty())
m_helpController->DisplayContents();
else
m_helpController->DisplaySection(topic);
}
}
```
宏USE_MODAL_HELP應該在那些使用wxHtmlHelpController控件的平臺上被定義.當你在模式對話框中顯示幫助的時候,將這個對話框的指針作為ShowHelp函數的第二個參數,這樣,如果需要,幫助就會顯示在一個模式的對話框中,而當你不是在模式對話框中顯示幫助的時候,只需要傳遞NULL作為ShowHelp的第二個參數.
幫助文件中的聲明
大多數現代的幫助文件系統都是基于HTML格式的.為了讓跨平臺的幫助文件制作更容易一些,wxWidgets的HTML幫助文件使用了和MS的HTML幫助文件同樣的工程,內容以及關鍵字文件輸入格式.這可以讓你在制作多平臺的幫助文件時,只需要考慮一套文件就可以了.下面列舉出為了創建幫助文件所需要的所有的文件:
* 一套HTML文件,每個主題是一個文件.
* 一個內容文件(擴展名是hhc)以XML的格式描述了主題的繼承關系.
* 一個可選的關鍵字文件(擴展名是hhk)用來將關鍵字映射到幫助主題.
* 一個工程文件(擴展名是hhp)用來描述工程中所有的其它文件以及整個工程的各個選項.
然后,你就可以將它們編譯為MS HTML幫助文件格式(擴展名為chm)或者wxWidgets的HTML幫助文件格式(擴展名是htb).對于前者,你需要使用微軟的HTML幫助制作軟件(Microsoft's HTML Help Workshop),它既可以從命令行調用也可以從GUI界面中被調用,而對于后者來說,你只需要使用任何你喜歡的zip壓縮工具將所有的這些文件打包成一個文件,將擴展名修改為.htb就可以了.
當然你可以手動制作你的幫助文件,但是使用一個工具可以節省你的時間.有很多MS HTML幫助文件的制作工具,但是它們有時候會輸出不兼容于wxWidgets(不能被wxWidgets解析)的HTML標記.Anthemion Software公司的HelpBlocks軟件是目前唯一的可以同時支持MS HTML格式和wxWidgets HTML格式的軟件,可以用來幫助你制作幫助文件和分析關鍵字.
要了解好的幫助文件的結構,最好是看看別人是怎么作的.你可以考慮增加下面的這些主題:內容,歡迎,聯系信息,安裝信息,注冊信息,發布信息,教程,菜單使用幫助,工具條使用幫助,對話框使用幫助(將所有針對對話框的主題作為子標題),快捷鍵,命令行參數以及故障解決等內容.
記住,應用程序中各個幫助主題的風格最好設計成各自獨立的.比如教程主題,最好采用一種比較現代的風格.
其它提供幫助的手段
你也可以考慮使用別的方法給你的用戶提供幫助,比如使用wxWidgets的HTML類等.Anthemion Software公司的Writer's Caf?軟件使用一個模式對話框來實現一些初始選項,它是用wxHtmlWindow實現的,這些選項包括顯示一個快速教程來通過一系列的HTML文件演示這個程序的用途(如下圖所示).這樣作的好處是不言而喻的,對于您軟件的使用新手來說,這樣做可以給你的用戶提供一個更狹長的學習路徑以便你的用戶不至于一開始就被浩如煙海的幫助給淹沒,從而把自己至于迷失的狀態.

另外一個常用的方法是提供每日一學之類的啟動提示對話框,這種方法把應用程序的功能分成一個一個的小片,然后每天學習一點點,這很符合某些人的口味.我們在第8章,"使用標準對話框"中已經介紹了怎樣使用wxShowTip函數來顯示這種幫助,它的參數包括一個父窗口,一個 wxTipProvider指針以便告訴wxWidgets到哪里去尋找那些幫助信息,以及一個boolean變量以便指定除此顯示這個對話框的時候,用于給用戶選擇是否顯示這種幫助的復選框的初始選項.如下所示:
```
#include "wx/tipdlg.h"
...
m_tipProvider = wxCreateFileTipProvider(tipFilename, currentTip);
wxShowTip(parent, m_tipProvider, showAtStart);
```
上下文敏感幫助和工具提示
應用程序應該盡可能的提供上下文敏感幫助和工具提示.所謂工具提示是指一個很小的提示窗口,這個窗口是當鼠標在某個控件上提留一小段時間的時候探出來的.上下文敏感幫助也和它類似,不過它是由用戶先點擊某個幫助按鈕或者是工具條上的系統按鈕,然后再點擊他感興趣的控件來加以顯示的.第9 章,"創建定制的對話框"中,對這些內容有比較詳細的介紹,在那里我們用來介紹怎樣給對話框提供幫助信息,然而這些方法不僅僅只能應用于對話框,它可以應用于任何一種窗口類型.比如用戶可以在工具條或者幫助菜單中提供一個"這是什么?"的選項,以便在用戶選擇這個菜單或者點擊這個工具按鈕以后,對用戶隨后點擊的窗口控件提供工具提示.你也不必拘泥于系統默認提供的幫助顯示方法,你可以自己重載wxHelpProvider類來實現你自己的ShowHelp 函數.
一些控件支持使用更本地化的方法來提供上下文敏感幫助,如果你正在使用wxCHMHelpController控件,你可以使用它來提供上下文敏感的幫助,比如:
```
#include "wx/cshelp.h"
m_helpController = new wxCHMHelpController;
wxHelpProvider::Set(
new wxHelpControllerHelpProvider(m_helpController));
```
wxHelpControllerHelpProvider類的實例將使用其m_helpController成員的DisplayTextPopup函數來提供上下文敏感幫助.
注意,提供上下文敏感幫助和Mac OSX的風格是格格不入的,因此在這個平臺你應該忽略這種幫助.
菜單項提示
當你在菜單中加入菜單項的時候,你可以提供一個幫助信息字符串.如果這個菜單是菜單條的一部分,而這個菜單條所在的frame窗口擁有一個狀態條,那么當用戶鼠標在這個菜單項上劃過的時候,這個幫助信息將顯示在狀態欄上.你可以通過wxFrame::SetStatusBarPane函數來指定顯示這個幫助信息的狀態條方格(如果設置為-1則將禁止顯示幫助信息).這個行為是在wxFrame的默認菜單項事件 EVT_MENU_HIGHLIGHT_ALL的處理函數中實現的,因此你可以攔截這個事件來提供你自己的顯示方式,比如將這個幫助信息顯示在另外的一個窗口上.
- 第一章 介紹
- 1.1 為什么要使用wxWidgets?
- 1.2 wxWidgets的歷史
- 1.3 wxWidgets社區
- 1.4 wxWidgets和面向對象編程
- 1.5 wxWidgets的體系結構
- 1.6 許可協議
- 第一章小結
- 第二章 開始使用
- 2.1 一個小例子
- 2.2 應用程序類
- 2.3 Frame窗口類
- 2.4 事件處理函數
- 2.5 Frame窗口的構造函數
- 2.6 完整的例子
- 2.7 wxWidgets程序一般執行過程
- 2.8 編譯和運行程序
- 第二章小結
- 第三章 事件處理
- 3.1 事件驅動編程
- 3.2 事件表和事件處理過程
- 3.3 過濾某個事件
- 3.4 掛載事件表
- 3.5 動態事件處理方法
- 3.6 窗口標識符
- 3.7 自定義事件
- 第三章小結
- 第四章 窗口的基礎知識
- 4.1 窗口解析
- 4.2 窗口類概覽
- 4.3 基礎窗口類
- 4.4 頂層窗口
- 4.5 容器窗口
- 4.6 非靜態控件
- 4.7 靜態控件
- 4.8 菜單
- 4.9 控制條
- 第四章小結
- 第五章繪畫和打印
- 5.1 理解設備上下文
- 5.2 繪畫工具
- 5.3 設備上下文中的繪畫函數
- 5.4 使用打印框架
- 5.5 使用wxGLCanvas繪制三維圖形
- 第五章小節
- 第六章處理用戶輸入
- 6.1 鼠標輸入
- 6.2 處理鍵盤事件
- 6.3 處理游戲手柄事件
- 第六章小結
- 第七章使用布局控件進行窗口布局
- 7.1 窗口布局基礎
- 7.2 窗口布局控件
- 7.3 使用布局控件進行編程
- 7.4 更多關于布局的話題
- 第七章小結
- 第八章使用標準對話框
- 8.1信息對話框
- 8.2 文件和目錄對話框
- 8.3 選擇和選項對話框
- 8.4 輸入對話框
- 8.5 打印對話框
- 第八章小結
- 第九章創建定制的對話框
- 9.1 創建定制對話框的步驟
- 9.2 一個例子:PersonalRecordDialog
- 9.3 在小型設備上調整你的對話框
- 9.4 一些更深入的話題
- 9.5 使用wxWidgets資源文件
- 第九章小結
- 第十章使用圖像編程
- 10.1 wxWidgets中圖片相關的類
- 10.2 使用wxBitmap編程
- 10.3 使用wxIcon編程
- 10.4 使用wxCursor編程
- 10.5 使用wxImage編程
- 10.6 圖片列表和圖標集
- 10.7 自定義wxWidgets提供的小圖片
- 第十章小結
- 第十一章剪貼板和拖放操作
- 11.1 數據對象
- 11.2 使用剪貼板
- 11.3 實現拖放操作
- 第十一章小結
- 第十二章高級窗口控件
- 12.1 wxTreeCtrl
- 12.2 wxListCtrl
- 12.3 wxWizard
- 12.4 wxHtmlWindow
- 12.5 wxGrid
- 12.6 wxTaskBarIcon
- 12.7 編寫自定義的控件
- 第十二章小結
- 第十三章數據結構類
- 13.1 為什么沒有使用STL?
- 13.2 字符串類型
- 13.3 wxArray
- 13.4 wxList和wxNode
- 13.5 wxHashMap
- 13.6 存儲和使用日期和時間
- 13.7 其它常用的數據類型
- 第十三章小結
- 第十四章文件和流操作
- 14.1 文件類和函數
- 14.2 流操作相關類
- 第十四章小結
- 第十五章內存管理,調試和錯誤處理
- 15.1 內存管理基礎
- 15.2 檢測內存泄漏和其它錯誤
- 15.3 構建自防御的程序
- 15.4 錯誤報告
- 15.5 提供運行期類型信息
- 15.6 使用wxModule
- 15.7 加載動態鏈接庫
- 15.8 異常處理
- 15.9 調試提示
- 第十五章小結
- 第十六章編寫國際化程序
- 16.1 國際化介紹
- 16.2 從翻譯說起
- 16.3 字符編碼和Unicode
- 16.4 數字和日期
- 16.5 其它媒介
- 16.6 一個小例子
- 第十六章小結
- 第十七章編寫多線程程序
- 17.1 什么時候使用多線程,什么時候不要使用
- 17.2 使用wxThread
- 17.3 用于線程同步的對象
- 17.4 多線程的替代方案
- 第十七章小結
- 第十八章使用wxSocket編程
- 18.1 Socket類和功能概覽
- 18.2 Socket及其基本處理介紹
- 18.3 Socket標記
- 18.4 使用Socket流
- 18.5 替代wxSocket
- 第十八章小結
- 第十九章使用文檔/視圖框架
- 19.1 文檔/視圖基礎
- 19.2 文檔/視圖框架的其它能力
- 19.3 實現Undo/Redo的策略
- 第十九章小結
- 第二十章完善你的應用程序
- 20.1 單個實例和多個實例
- 20.2 更改事件處理機制
- 20.3 降低閃爍
- 20.4 實現聯機幫助
- 20.5 解析命令行參數
- 20.6 存儲應用程序資源
- 20.7 調用別的應用程序
- 20.8 管理應用程序設置
- 20.9 應用程序安裝
- 20.10 遵循用戶界面設計規范
- 20.11 全書小結