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@)&lt;hr&gt;"),
                     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例子演示了上述所有的知识,请参考.