# 12.4 wxHtmlWindow
wxWidgets在其內建幫助系統中使用了wxHtmlWindow控件,如果你希望你的程序可以顯示格式化文件,圖片等(比如在生成報表的時候),你可以使用這個控件.這個控件可以支持標準HTML標記的一個子集,包括表格(但是不支持框架),GIF動畫,高亮鏈接顯示,字體顯示,背景色,列表,居中或者右對齊,水平條以及字符編碼等.雖然它不支持CSS,你還是可以通過已經的或者自定義的標記來達到同樣的效果.其中的HTML文本也支持拷貝到剪貼板以及從剪貼板以普通文本的方式拷貝回應用程序.
下圖演示了自帶的samples/html/test例子編譯運行以后的樣子:

和一個完整的瀏覽器不同,wxHtmlWindow是小而快的,因此你可以在你的程序中大方的使用它,下圖演示了在一個關于對話框中使用wxHtmlWindow的例子:

下面的代碼用來創建上面的例子,在這個例子中,HTML控件首先使自己的大小滿足其內部的HTML文本的需要,然后對話框的布局控件在調整自己的大小已滿足HTML控件的需要.
```
#include "wx/html/htmlwin.h"
void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
{
wxBoxSizer *topsizer;
wxHtmlWindow *html;
wxDialog dlg(this, wxID_ANY, wxString(_("About")));
topsizer = new wxBoxSizer(wxVERTICAL);
html = new wxHtmlWindow(&dlg, wxID_ANY, wxDefaultPosition,
wxSize(380, 160), wxHW_SCROLLBAR_NEVER);
html->SetBorders(0);
html->LoadPage(wxT("data/about.htm"));
// 讓HTML控件的大小滿足其內部HTML文本需要的大小
html->SetSize(html->GetInternalRepresentation()->GetWidth(),
html->GetInternalRepresentation()->GetHeight());
topsizer->Add(html, 1, wxALL, 10);
topsizer->Add(new wxStaticLine(&dlg, wxID_ANY), 0, wxEXPAND | wxLEFT | wxRIGHT, 10);
wxButton *but = new wxButton(&dlg, wxID_OK, _("OK"));
but->SetDefault();
topsizer->Add(but, 0, wxALL | wxALIGN_RIGHT, 15);
dlg.SetSizer(topsizer);
topsizer->Fit(&dlg);
dlg.ShowModal();
}
```
下面列出的是例子中的HTML文本:
```
<html>
<body bgcolor="#FFFFFF">
<table cellspacing=3 cellpadding=4 width="100%">
<tr>
<td bgcolor="#101010">
<center>
<font size=+2 color="#FFFFFF"><b><br>wxHTML Library Sample 0.2.0<br></b>
</font>
</center>
</td>
</tr>
<tr>
<td bgcolor="#73A183">
<b><font size=+1>Copyright (C) 1999 Vaclav Slavik</font></b><p>
<font size=-1>
<table cellpadding=0 cellspacing=0 width="100%">
<tr>
<td width="65%">
Vaclav Slavik<p>
</td>
<td valign=top>
<img src="logo.png">
</td>
</tr>
</table>
<font size=1>
Licenced under wxWindows Library Licence, Version 3.
</font>
</font>
</td>
</tr>
</table>
</body>
</html>
```
請參考第4章,"基礎窗口類"中,"wxListBox和wxCheckListBox"小節中關于wxHtmlListBox的內容.
wxHtmlWindow窗口類型
| wxHW_SCROLLBAR_NEVER | 不要顯示滾動條. |
|:--- |:--- |
| wxHW_SCROLLBAR_AUTO | 只在需要的時候顯示滾動條. |
| wxHW_NO_SELECTION | 用戶不可以選擇其中的文本(默認可以). |
wxHtmlWindow成員函數
GetInternalRepresentation函數返回最頂層的wxHtmlContainerCell控件,使用它的GetWidth和GetHeight函數可以得到整個HTML區域的大致大小.
LoadFile加載一個HTML文件然后顯示它. LoadPage則可以傳遞一個URL. 有效的URL包括:
http://www.wxwindows.org/front.htm # 一個URL
file:myapp.zip#zip:html/index.htm # 一個zip文件中特定的文件
SetPage則直接傳遞要顯示的HTML字符串.
OnCellClicked函數在有鼠標單擊某個HTML元素的時候被調用.它的參數包括wxHtmlCell指針, X和Y座標, 一個wxMouseEvent引用.其默認行為為:如果這個元素是一個超鏈接,則調用OnLinkClicked函數.
OnLinkClicked函數的參數為wxHtmlLinkInfo類型,它的默認行為是調用LoadPage函數加載當前鏈接.你可以重載這種行為,比如,在你的關于對話框中,你可以在用戶單擊某個鏈接的時候使用默認的瀏覽器打開你的主頁.
其它可以重載的函數包括OnOpeningURL,它在某個URL正被打開的時候調用, OnCellMouseHover函數,當鼠標移過某個HTML元素的時候被調用.
ReadCustomization和WriteCustomization函數則用來保存字體和邊界信息,它們的參數包括一個wxConfig*指針以及一個可選的位于配置中的路徑.
你可以使用SelectAll,SelectLine和SelectWord函數來進行文本選擇,SelectionToText將當前選擇區域以純文本的方式返回,ToText函數則將整頁以純文本的方式返回.
SetBorders函數用來設置HTML周圍的邊框,SetFonts函數則用來設置字體名稱,你還可以給七個預定義的字體大小指定整數類型點單位的具體大小.
AppendToPage函數在當前的HTML文本中添加內容并且刷新窗口.
你可以編寫一個自定義的wxHtmlFilter以用來讀取特定的文件,你可以使用AddFilter函數將其在wxHtmlWindow類中登記.比如,你可以寫一個自定義的過濾器用來解密并顯示加密的HTML電子雜志.
GetOpenedAnchor, GetOpenedPage和GetOpenedPageTitle函數用來返回當前網頁的一些相關信息.
wxHtmlWindow有自己的訪問歷史機制,你可以通過HistoryBack, HistoryForward, HistoryCanBack, HistoryCanForward和HistoryClear函數來使用它.
在網頁中集成窗口控件
你可以在網頁中集成你自己的窗口控件,甚至包括那些你自定義的控件,如下圖所示.這是通過制作一個定制的標簽處理函數來實現的,這個定制的標簽處理函數用來處理某些特定的標簽并相應的在網頁窗口中插入自己的窗口.

上圖演示了某個HTML窗口的一部分,是由下面的網頁產生的:
```
<mybind name="(small one)" x=150 y=30>
<hr>
<mybind name="a widget with floating width" float=y x="50" y=50>
<hr>
Here you can find multiple widgets at the same line:<br>
here
<mybind name="widget_1" x="100" y=30>
...and here:
<mybind name="widget_2" x="150" y=30>
```
用于實現特定的HTML標記mybind的代碼如下所示:
```
#include "wx/html/m_templ.h"
TAG_HANDLER_BEGIN(MYBIND, "MYBIND")
TAG_HANDLER_PROC(tag)
{
wxWindow *wnd;
int ax, ay;
int fl = 0;
tag.ScanParam(wxT("X"), wxT("%i"), &ax);
tag.ScanParam(wxT("Y"), wxT("%i"), &ay);
if (tag.HasParam(wxT("FLOAT"))) fl = ax;
wnd = new wxTextCtrl(m_WParser->GetWindow(), wxID_ANY, tag.GetParam(wxT("NAME")),
wxPoint(0,0), wxSize(ax, ay), wxTE_MULTILINE);
wnd->Show(true);
m_WParser->GetContainer()->InsertCell(new wxHtmlWidgetCell(wnd, fl));
return false;
}
TAG_HANDLER_END(MYBIND)
TAGS_MODULE_BEGIN(MyBind)
TAGS_MODULE_ADD(MYBIND)
TAGS_MODULE_END(MyBind)
```
這種技術在你想使用wxHtmlWindow來創建整個應用程序界面的時候是比較有用的,你可以用一些教本來產生HTML文件以響應用戶輸入,就象一個網頁表單一樣.另外一個例子是當你需要搜集用戶的注冊信息的時候,你可以提供這樣一個界面,其中包含文本框,用戶可以輸入相關的信息然后點擊"注冊"按鈕以便將他輸入的信息發送到你的組織.或者你也可以使用這種技術來給用戶產生一個報告,報告中包含一些復選框,以便可以可以針對他感興趣的內容進行詳細查看.
關于制作自定義HTML標記的更詳細的內容,請參考samples/html/widget目錄中的例子,或者wxWidgets參考手冊.
HTML打印
通常如果你的應用程序中使用了wxHtmlWindow,那么你也希望能夠打印這些HTML文件.wxWidgets提供了一個 wxHtmlEasyPrinting類來用一種簡單的方法打印HTML文件.你需要作的是創建一個這個類的實例,然后使用本地HTML文件調用 PreviewFile和PrintFile函數.你還可以調用PageSetup函數來顯示打印設置對話框,使用GetPrintData函數和 GetPageSetupData獲取用戶的打印設置和頁面設置.可以通過SetHeader和SetFooter函數定制頁眉和頁腳,其中可以包含預定義的宏@PAGENUM@(當前頁碼)和@PAGESCNT@(總頁數).
下面的代碼取自samples/html/printing,演示了上述控件的基本使用方法以及怎樣更改默認的字體:
```
#include "wx/html/htmlwin.h"
#include "wx/html/htmprint.h"
MyFrame::MyFrame(const wxString& title,
const wxPoint& pos, const wxSize& size)
: wxFrame((wxFrame *)NULL, wxID_ANY, title, pos, size)
{
...
m_Name = wxT("testfile.htm");
m_Prn = new wxHtmlEasyPrinting(_("Easy Printing Demo"), this);
m_Prn->SetHeader(m_Name + wxT("(@PAGENUM@/@PAGESCNT@)<hr>"),
wxPAGE_ALL);
}
MyFrame::~MyFrame()
{
delete m_Prn;
}
void MyFrame::OnPageSetup(wxCommandEvent& event)
{
m_Prn->PageSetup();
}
void MyFrame::OnPrint(wxCommandEvent& event)
{
m_Prn->PrintFile(m_Name);
}
void MyFrame::OnPreview(wxCommandEvent& event)
{
m_Prn->PreviewFile(m_Name);
}
void MyFrame::OnPrintSmall(wxCommandEvent& event)
{
int fontsizes[] = { 4, 6, 8, 10, 12, 20, 24 };
m_Prn->SetFonts(wxEmptyString, wxEmptyString, fontsizes);
}
void MyFrame::OnPrintNormal(wxCommandEvent& event)
{
m_Prn->SetFonts(wxEmptyString, wxEmptyString, 0);
}
void MyFrame::OnPrintHuge(wxCommandEvent& event)
{
int fontsizes[] = { 20, 26, 28, 30, 32, 40, 44 };
m_Prn->SetFonts(wxEmptyString, wxEmptyString, fontsizes);
}
wxWidgets自帶的samples/html例子演示了上述所有的知識,請參考.
```
- 第一章 介紹
- 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 全書小結