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

基于 Windows 窗体的 HTML 输出文本编辑器

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.91/5 (165投票s)

2006年9月12日

CPOL

5分钟阅读

viewsIcon

2849417

downloadIcon

72937

一款基于 Windows Forms 的文本编辑器,可输出 HTML,通过在编辑模式下使用浏览器控件实现。

 

通知:截至 2017 年 10 月 28 日,已有新版本可用。 

包含以下功能

  • 需要 .NET 4.5.1。
  • 修复了导致浏览器对话框弹出的“另存为”和“加载”错误。
  • 通过 URL 或文件系统插入内嵌图像。文件系统图像将嵌入到生成的 HTML 中。
  • 完全支持对 HTML、Body HTML、Body Text 的编程访问
  • 设置 body 的背景颜色。
  • 插入图像。
  • 调整图像大小。
  • 从文本添加和编辑超链接。
  • 从图像添加和编辑超链接。
  • 支持从 Windows XP SP2 到 Windows 8。
  • 支持所有版本的 IE。 

 

 

Sample Image - editor.png

 

引言

不久前,我正在开发一个聊天应用程序,其中一个聊天客户端是基于 Web 的,用 ASP.NET 2.0 编写。另一个聊天客户端是使用 C# 编写的基于 Windows Forms 的 .NET 应用程序。我的 WinForms 客户端需要一个可以输出 HTML 的富文本编辑器,以便 ASP.NET 客户端可以显示 WinForms 客户端的格式。在使用 RTF 文本框时,这一点被排除了。

我找到的解决方案是,在我的 WinForms 客户端中使用处于编辑模式的 `WebBrowser` 控件。浏览器上方工具栏上的格式按钮会与 `WebBrowser` 控件中的当前选区同步。

本文解释了从 `WebBrowser` 控件构建编辑器控件过程中遇到的许多问题的解决方案。我不会深入介绍所有内容,因为源代码本身并不难浏览。但是,我确实涵盖了一些使其正常工作的必要技巧。

使用控件

该控件是一个可执行文件。

您可以直接运行其主窗体,也可以将其作为控件嵌入到您自己的应用程序中。

要将其嵌入到您自己的应用程序中,只需在 Visual Studio 中像引用 DLL 一样引用该 EXE 即可。

它应该会出现在 Visual Studio 的工具箱窗口中。  

请查看源代码,了解如何从您的代码中访问它的示例。

它是一个 .NET 2.0 控件,因此应该可以在旧项目中运行。 

设置设计模式 

在使用该组件时,会自动应用设计模式并为文档建立编辑模板。但为了参考,这里简要解释一下它的工作原理。

应用设计模式需要使用 COM 接口:添加对“Microsoft HTML Object Library”的引用,该引用解析为 MSHTML,并添加对“MSHTML”的“using”。

在应用更改到 DOM 文档之前,必须向控件添加一个 body。为此,您可以简单地将一些文本应用于 `WebBrowser` 控件的 `DocumentText` 属性。

webBrowser1.DocumentText = "<html><body></body></html>"

接下来,获取对新的 `DomDocument` COM 接口的引用,并将设计模式设置为“`On`”。

IHTMLDocument2 doc =
webBrowser1.Document.DomDocument as IHTMLDocument2;
doc.designMode = "On";

最后,我替换了浏览器控件的上下文菜单,以避免显示默认的 IE 浏览器上下文菜单。

webBrowser1.Document.ContextMenuShowing += 
new HtmlElementEventHandler(Document_ContextMenuShowing);

浏览器现在处于设计模式,并提供了一个自定义方法来显示上下文菜单。

应用格式

您可以使用 `browser.Document` 上的 **`ExecCommand`** 方法,向处于设计模式下的浏览器控件应用格式和编辑器功能。

这里有一些例子

public void Cut()
{
    webBrowser1.Document.ExecCommand("Cut", false, null);
}
public void Paste()
{
    webBrowser1.Document.ExecCommand("Paste", false, null);
}
public void Copy()
{
    webBrowser1.Document.ExecCommand("Copy", false, null);
}

一些命令将切换当前选区的格式状态。

public void Bold()
{
    webBrowser1.Document.ExecCommand("Bold", false, null);
}

public void Italic()
{
    webBrowser1.Document.ExecCommand("Italic", false, null);
}

同步格式按钮与选中文本

这比向浏览器控件应用格式命令要棘手一些。我每 200 毫秒实际查询一次浏览器编辑器选区状态,并基于此设置工具栏格式按钮。

private void timer_Tick(object sender, EventArgs e)
{
    SetupKeyListener();
    boldButton.Checked = IsBold();
    italicButton.Checked = IsItalic();
    underlineButton.Checked = IsUnderline();
    orderedListButton.Checked = IsOrderedList();
    unorderedListButton.Checked = IsUnorderedList();
    linkButton.Enabled = SelectionType == SelectionType.Text;

    UpdateFontComboBox();
    UpdateFontSizeComboBox();
    if (Tick != null) Tick();
}

您会注意到有一个 `Tick` 事件,该事件在计时器 `tick` 事件结束时触发。外部组件可以订阅此事件来更新其 GUI 的状态。例如,它们可以根据编辑器控件的状态更新剪切/复制/粘贴/撤销/重做按钮的 `Enabled` 状态。

我通过使用从 `WebBrowser` 控件检索到的 COM 文档接口来实现此目的

IHTMLDocument2 doc = webBrowser1.Document.DomDocument as IHTMLDocument2;

然后我使用 **`queryCommandState`** 来确定当前选区的状态

public bool IsBold()
{
    return doc.queryCommandState("Bold");
}

public bool IsItalic()
{
    return doc.queryCommandState("Italic");
}

public bool IsUnderline()
{
    return doc.queryCommandState("Underline");
}

链接按钮和字体控件以类似的方式管理,但我将把这个留给您在代码中查看。

焦点

控件的焦点也不是那么简单。`WebBrowser` 控件本身不会接受焦点。`WebBrowser` 控件的文档也不会。**但是**,如果控件中存在 `body` 元素,则 `body` 会获得焦点。

private void SuperFocus()
{
    if (webBrowser1.Document != null && 
        webBrowser1.Document.Body != null)
      webBrowser1.Document.Body.Focus();
}

当然,您永远不需要直接调用此方法。调用控件上的 **`Focus`** 方法会将焦点放在包含 `WebBrowser` 控件的编辑器控件上。当编辑器控件收到 **`GotFocus`** 事件时,它会自动将焦点转移到 `WebBrowser` 的文档 body。

检索文本或 HTML

**`BodyHtml`** 和 **`BodyText`** 方法分别检索 body 的 HTML 和文本。

链接到组件程序集

在 Visual Studio 2005 中,您可以链接到一个程序集(添加引用),即使该程序集是可执行文件。该编辑器是作为一个嵌入在窗体中的组件编写的,因此您可以将其添加到控件面板,并将其拖放到您的应用程序中。该控件的名称是 `Editor`,位于 `Design` 命名空间下。

结论

基于 .NET 2.0 的 `WebBrowser` 控件可以有效地用作文本编辑器。当您需要一个可以用作 HTML 编辑器的编辑器控件时,这非常有用。在某些方面,实现并非完全直接。本文试图展示一些使其正常工作的必要技巧。

历史

  • 2006 年 10 月 4 日 - 各种错误修复和设计更新/设计器支持。
  • 2006 年 10 月 19 日 - 更多错误修复和更多设计器支持。
  • 2017 年 10 月 28 日 - 升级到 .net 4.5.1 和 VS 2015
© . All rights reserved.