65.9K
CodeProject 正在变化。 阅读更多。
Home

HTMLLabel - .NET CF 的 HTML 标签

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.73/5 (9投票s)

2009 年 3 月 3 日

CDDL

11分钟阅读

viewsIcon

49388

downloadIcon

916

一个简单的 HTML 标签,支持一些基本的 HTML。

目录

引言

如果您至少是中级程序员,并且没有时间阅读整篇文章,或者只是不想读,那么 使用代码 部分是您开始阅读的地方。

HTMLLabel 是(您不会觉得是吧 :))一个简单的、支持 HTML 的 .NET CF 2.0 标签。最后一个词(CF)最重要,因为对于 Windows 程序员来说,有很多不同的支持 HTML 的标签,但据我所知,在此时此刻(2009 年初),.NET CF 或您可能说的 .NET 移动开发领域,并没有免费的 HTML 标签。我强调“免费”,甚至更好,“公开可用”,因为您可以购买一些商业化的 HTML 标签。

更多内容将在文章的其余部分介绍;让我们看看 HTMLLabel 的功能。

  1. 当然,它可以显示一些简单的 HTML 代码。我所说的简单 HTML 代码是指这些标签:<b><i><u><pre><br><font><p>。除此之外,它还使用 <label> 标签,但它具有特殊的含义,而非经典的 HTML 含义。
  2. 它可以取代许多不同的 Label 对象并将它们组合在一起。
  3. 它可以(事实上,它确实)加快 InitializeComponent() 函数的速度。这在移动开发中非常重要!
  4. 它有一个 Click 事件(.NET CF 的 Label 类中缺少)。
  5. 以及其他一些不错的功能……

背景

我是我们国家(一个美丽而相当小的国家 - 斯洛文尼亚)一家大型零售商的软件开发人员。我的工作是为我们公司的软件开发设定标准。我们有许多不同的开发平台,我个人负责管理 C++/Pervasive 环境、.NET Mobile 环境、Excel/Word VBA 环境、VBScript 和 Python 中的不同程序员团队。正如您所见,代码的可管理性是我的首要任务。

多年来,我们一直在我们的移动扫描器上使用 Oracle Form 3.0 终端应用程序,但去年,我们迁移到了 Oracle Forms 10,这对旧的 Symbol 扫描器来说负担太重了(好吧,让我们面对现实吧——F10 对全新的、调整过的扫描器来说都太重了!)。所以我们决定编写与服务器通过 Web 服务通信的 .NET 应用程序……是的,我接受了组建一个同事团队并建立一些标准的任务。对于一个完全是 C++ 的人来说,没有 C# 知识,这是一项非常艰巨的任务。

抱歉,介绍有点长,但:“嘿;这就是背景!”

正如我之前所说,我们是零售商,所以我们应用程序中的典型屏幕看起来像这样(当然,这有点简化,但足以说明问题)。

由于我们有不同的扫描器,它们的屏幕分辨率和屏幕尺寸不同,我们使用不同的字体大小,因此屏幕可以在运行时更改(根据应用程序运行的扫描器类型)。这样的屏幕由四个面板(均设置为 Dock=Top)、几个 Labels 和几个 TextBoxes(均设置为不同的属性,以便在字体大小更改时可以重新排列它们)组成。我的天哪,几个这样的应用程序(每个应用程序都有几个这样的屏幕)的管理起来真是噩梦!

如果我只能使用一个包含所有文本的对象,并根据文本重新排列文本框,那不是更好吗?而且所有这些都将在运行时完成,而无需设置多个对象的停靠。请记住,任何程序员都可以更改他的(或她的)代码并重新排列屏幕,但如果您必须这样做,而这最初并不是您的程序呢?重新排列所有这些停靠和计算字体更改可能会使代码变得非常复杂。

是的,**HTMLLabel 可以解决这个问题**。我知道,我知道,您期望找到一个可以显示不同字体、不同颜色、大小等内容的 Label 对象,是的——您找到了这样的 Label——但这很无聊;这只是您对任何支持 HTML 的 Label 的期望!

使用代码

非常重要信息

这个 HTMLLabel 对象是**为移动环境编写的**,**不适用于 Windows 编程。** 这是因为移动设备上的渲染方式与 Windows 环境不同。从技术上讲,在 .NET CF 中,您在 GUI 功能方面受到很大限制,只有一个函数可以计算文本大小:MeasureString()。而且,这个函数非常不准确,但对于移动设备来说是可以接受的。

演示项目也是如此。您可以在 PC 上运行演示项目,但可能会感到失望。最好**在真实的移动设备或模拟器上使用演示项目。**

快速介绍

使用代码很简单

  1. 下载源代码,并将 HTMLParser.csHTMLLabel.cs 文件添加到您的移动项目中。
  2. 编译代码,以便 Visual Studio 可以在工具栏上创建 HTMLLabel 对象。
  3. 将工具栏上的 HTMLLabel 对象放置在窗体上。
  4. 更改其 Text 属性为一些 HTML 文本,就完成了。

您可以使用 HTML 标签

  • <b> 用于粗体文本。
  • <i> 用于斜体文本。
  • <u> 用于下划线文本。
  • <p> 用于段落。
    • align 属性,值为(leftrightcenter)。
  • <font> 用于更改字体。
    • name 属性用于字体名称。
    • size 属性用于字体大小(字体大小以磅为单位,所以 size=10 表示 10 磅)。
    • color 属性。颜色可以是任何 HTML 命名颜色(www.w3schools.com),或者以 #RRGGBB 形式表示的十六进制颜色。
  • <pre> 表示不换行文本。
  • <br> 表示文本换行。

HTML 示例

HTMLLabel1.Text = @"<font size='8' name='Tahoma' color='red'>Tahoma, 8, red</font>";
HTMLLabel1.Text = @"<p align='left'>left</p><p align='center'>" + 
                  @"center</p><p align='right'>right</p>"

使用特殊的 <label> 标签

在屏幕上绘制 HTML 文本有三个基本步骤:

  1. 解析 HTML 文本
  2. 根据字体和对齐方式计算文本位置
  3. 在表面上绘制文本

第三步显然是强制性的,但前两步呢?事实证明,前两步是最耗时的(至少在我使用的普通移动设备上)。所以,如果我们能跳过前两步,那不是再完美不过了吗?如果我更改文本,那么第一步显然是强制性的,第二步和第三步也是。但是,如果我只更改文本的一部分呢?即使那样,也必须重复前两步,因为文本的更改可能会影响整个图像。

但是,有一个例外,在我这个行业,这个例外与其说是例外,不如说它本身就是规则。我们有一些屏幕,上面有很多固定文本,还有一些部分是可变文本,它们可以占用屏幕的一部分。我使用的解决方案是使用一个特殊的 <label> 标签,它是一个任意大小的标签,位于 HTML 文本的中间。这样的 HTML 文本只解析一次,所有的计算也只进行一次。之后,程序员只需更改标签值,然后将该标签的文本写入 HTML 文本中的正确位置。

这就是它的样子

// First the programmer set the initial HTML text
htmlLabel1.Text = "Desc: <label id='desc' width='100'>"

// ...
// Somewhere in the rest of the code he (she) set the value of the label:
htmlLabel1.ChangeLabelText("desc", "Description X");

Label 标签可以有四个属性(标签使用的字体当然由标签之前的 font 标签决定,如果没有 font 标签,则使用 HTMLLabel 本身的字体)。

  • id 是最重要的,因为它是程序员在代码中识别此标签的 ID。
  • value 是标签的初始值。
  • width 是标签在屏幕上的宽度。如果未指定,则从初始文本计算。如果初始文本也未指定,则宽度为一个空格的宽度。
  • height 是标签在屏幕上的高度。如果未指定,则从初始文本计算。如果初始文本也未指定,则高度为一个空格的高度。

一些标签的例子

htmlLabel1.Text = "Some HTML text <label id='lbl1' width='50'>";
htmlLabel1.Text = "Some HTML text <label id='lbl1' value='initial value'>";

将 HTML 文本中的标签与 .NET 代码连接起来

我们有三个函数和一个事件可用于将 HTML 文本中的标签与程序本身连接起来。

  • ChangeLabelText 用于更改标签的值。它接受两个参数:标签 ID 和新的标签值。如果标签文本已更改(找到标签),则返回 true,否则返回 false
  • GetLabelPos 返回标签占据的矩形区域。它接受两个参数:标签 ID 和 Rectangle 对象的引用。如果找到标签并设置了矩形,则返回 true,否则返回 false。**注意:** 矩形值是以 HTMLLabel 坐标表示的,而不是屏幕坐标!
  • RepositionControlOnLabel 将任意控件精确地定位在标签本身上。它接受两个参数:标签 ID 和控件的引用。如果找到标签,则返回 true,否则返回 false。**注意:** 您要定位在标签上方的控件必须与 HTMLLabel 在同一个容器中。您不能将 TextBox 放在 Panel 1 中,而将 HTMLLabel 放在 Panel 2 中,然后尝试将 TextBox 定位在 HTMLLabel 上方!
  • Recalculated 是一个事件,当 HTMLLabel 上的文本位置发生变化时触发,程序员必须重新排列组件。

以下是它们的签名:

  • public bool ChangeLabelText(string labelID, string value)
  • public bool GetLabelPos(string labelID, ref Rectangle rect)
  • public void RepositionControlOnLabel(string labelID, Control label)
  • public delegate void RecalculatedEvent(object sender, EventArgs e)

示例

private void myHtmlLabel_Recalculated(object sender, EventArgs e)
{
  myHtmlLabel.RepositionControlOnLabel("tb", myTextBox);
}

myHtmlLabel.ChangeLabelText("lbl1", "new value");

HTMLLabel 的附加属性

与 .NET CF 中的经典 Label 相比,HTMLLabel 具有三个额外的属性:

  • VerticalAlignment 控制 HTMLLabel 内部文本的垂直对齐方式,可以有三种状态:TopCenterBottom。文本的水平对齐方式由经典的 HTML 标签 <p> 及其 align 属性控制,可用的值为:leftrightcenter
  • SpaceSize 是文本之间的空格大小(以磅为单位)。它可以是负值或正值。当值为负数时,空格大小是通过将单词长度除以字符数来自动计算的。当值为正数时,表示空格大小以磅为单位。如果数字为零,则单词之间没有空格。您会发现,即使您将空格大小设置为 0,单词之间仍然存在一些空格。这是因为 MeasureString() 函数返回的文本大小“不准确”。“不准确”的意思是,它返回的大小会留有一些空间!
  • ShowBorders 更多是一个用于测试的属性,而不是一个您将在生产环境中使用到的属性。如果设置为 trueHTMLLabel 将在每个文本和标签下方绘制一个矩形,这个矩形显示了元素的计算大小。正如我所说的,您可以使用此属性来正确设置元素的大小。

技巧和窍门

如果您想在 HTML 文本中定位一个文本框,您可以使用组件大小和宽度来计算所需的精确空间!

htmlLabel1.Text = 
  string.Format("Price: <label id='price' width='{0}' height='{1}'>", 
                textBox1.Width, textBox1.Height);

如果您想为(比如说)8 个数字留出足够的空间,而不管字体如何,您可以设置标签的初始值。标签的大小将设置为能够容纳该初始值。

htmlLabel1.Text = "Price: <label id='price' value='999999.99'>";

使用 HTMLLabel 演示应用程序

演示应用程序易于使用,它将向您展示 HTMLLabel 可以做的各种事情。主窗口有三个部分:

  1. 一个选择项,您可以从中选择不同的测试用例。
  2. 一个文本框,其中包含 Text 属性的表示(显示原始 HTML)。
  3. 一个 HTMLLabel 显示结果。

完成预准备的测试用例后,您可以直接在顶部的文本框中更改原始 HTML,然后从菜单(4)中选择“显示更新的 HTML”选项,这将重绘 HTML。您还可以更改“设置”子窗体中的设置,所选设置将立即应用于主窗体上的 HTMLLabel

代码

HTMLLabel 有两个模块:一个是 HTML 解析器,另一个是 HTMLLabel 本身。

HTML 解析器非常小巧快速。其基础来自 Jeff Heaton 在他的文章 'Parsing HTML in Microsoft C#' 中编写的解析器。我重写了他的代码并对其进行了性能分析,使其在移动设备上的速度提高了约 70%。我还增加了对“HTML 处理指令”和“HTML 注释”的支持。

HTMLLabel 的基本思想是将 HTML 文本拆分为标签和纯文本。然后将文本再次拆分为单词。每个单词代表一个元素,HTMLLabel 计算每个此类元素的大小,然后将它们绘制在表面上。

通过检查代码可以学到什么?

  • 如何编写一个小型快速的文本解析器。
  • 如何使用双缓冲提高图形速度。
  • 如何在带有不同字体和颜色的表面上绘制文本。
  • 如何编写一个类层次结构,而不是一个带有类型字段的大类。
  • 如何将颜色名称和颜色代码转换为 Color 对象。
  • 如何编写具有自定义属性和事件的自定义 .NET CF 组件。
© . All rights reserved.