.NET 2.0 C# 版本的所见即所得 HTML 编辑器






2.53/5 (13投票s)
2007年7月18日
4分钟阅读

106158

1889
关于如何使用 .NET 2.0 组件构建所见即所得 HTML 编辑器的基本示例

引言
欢迎来到精彩的 .Net 2.0 世界
几周来,我一直在为我的雇主构建一个所见即所得的 HTML 编辑器。不幸的是,他们有一个糟糕的习惯,那就是 a) 不提供任何软件开发工具 b) 不提供任何互联网访问 c) 想要在周三完成所有工作。
首先,我尝试使用 RichTextBox,并花费了大部分时间开发 HTML->RTF 和 RTF->HTML 转换器。随着项目的进行,很快发现需要更复杂的布局控件,因此开始了研究。(顺便说一下,所有这些代码都放在一台工作机器上,被锁起来了,没有文件进出 - 这里的代码是我在空闲时间用一些时间和一些我在这里家里的记忆拼凑起来的)。我一度非常生气,我考虑用 C 或 C++ 开发它,但是因为仅仅在系统上安装 .NET Framework 和 SDK 就花费了将近一年的时间,所以我不会尝试冒险在上面安装 C 编译器。
我开始尝试弄清楚 AxWebBrowser 控件。首先,我必须使用 Aximp 导入 SHDocVw.dll,然后我必须使用 TblImp 命令导入 MSHTML.tbl,然后……我快抓狂了。到目前为止,我看到的所有其他代码都调用此控件。
工作了一段时间后,我完成了代码的编写并添加了许多功能。我开始在分布式环境中测试可执行文件。最后,在我认为一切正常并稳定之后,我在非开发计算机上收到了这些难看的 COM 错误
“无法将 System._ComObject 转换为 MSHTML.HTMLDocumentClass 类型,因为互操作程序集未被识别……但是如果存在接口,您可以将其转换为接口” 我差点气炸了。
因此,我进行了更多挖掘,发现 Microsoft 已经在他们的 SDK (%INSTALLLOCATION%\SDK\PRIMARY INTEROP ASSEMBLIES) 中提供了一个不错的 Microsoft.mshtml.dll 引用程序集。这解决了 MSHTML 导入问题,现在如果我能够获得浏览器的互操作程序集就好了。
等等,System.Windows.Forms 已经有了一个不错的 WebBrowser 控件(我可以对其进行各种不错的事件设置)。让我们看看我是否可以使用它。
事实证明你可以。所以我继续用标准的 Windows.Forms 控件替换了 AxWebBrowser 控件 - 通过这样做,我节省了大量内存和开销,因为不需要加载其他 DLL 到内存中。
1) 添加对 Microsoft.mshtml.dll 的引用(手动浏览并选择 DLL)或者 Microsoft.mshtml 程序集可能已经加载到您的 GAC 中。
2) 向您的窗体添加一个 webbrowser 对象,确保将其默认 url 设置为 about:blank(例如 webBrowser1.Navigate("about:blank");
3) 获取对文档的引用并创建一个对非托管文档的接口引用(允许您执行诸如编辑文档内容之类的操作)。
4) 尽情享受。所有这些都使用标准的 .NET 2.0 程序集,无需处理 AxSHDocVw、SHDocVw 或 MSHTML.tbl。
代码示例
namespace WYSIWYGnet2._
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.Load += new EventHandler(Form1_Load);
}
/// <summary>
/// Private property to hold the document you will be editing
/// </summary>
private mshtml.IHTMLDocument2 doc;
/// <summary>
/// Initialization function which sets the editable document to the display in the webbrowser
/// as well as turn the control into an editable area.
///
/// Please note, that you must have some sort of data loaded into the webbrowser before you can work
/// with the document element - hence in the designer code, the web broser initial URL is set to about:blank
/// </summary>
void Form1_Load(object sender, EventArgs e)
{
/*If you haven't already initalized the webBrowser with a blank document
* do so here before you try to capture a null reference
* this.webBrowser1.Navigate("about:blank");
*/
doc = (mshtml.IHTMLDocument2)this.webBrowser1.Document.DomDocument;
doc.designMode = "On";
doc.write("Hello World!");
}
/// <summary>
/// Example function for executing commands to the document.
///
/// Other popular commands are:
///
/// Cut, Paste, Copy, Underline, Italics
/// CreateLink, CreateOrderedList, CreateUnorderedList
///
/// lots more - see the CommandIdentifiers section at MSDN
/// </summary>
private void BoldBut_Click(object sender, EventArgs e)
{
doc.execCommand("Bold", false, null);
}
/// <summary>
/// Example function working with text ranges and the selected text.
/// </summary>
private void SelBut_Click(object sender, EventArgs e)
{
mshtml.IHTMLTxtRange txt = (mshtml.IHTMLTxtRange) doc.selection.createRange();
MessageBox.Show("Text Selected: " + txt.text);
MessageBox.Show("HTML Selected: " + txt.htmlText);
MessageBox.Show("Inserting Peter Pan into selection point");
string insert_text = "##INSERTPOINT##";
/* Note, if you wish to preserve the original text
* you would need to create an additional variable to hold the temporary text
*/
txt.text = insert_text;
doc.execCommand("SelectAll", false, null);
txt = (mshtml.IHTMLTxtRange) doc.selection.createRange();
txt.findText(insert_text,0,0);
txt.select();
txt.text = "Peter Pan";
}
/// <summary>
/// Shows how to insert HTML code directly into the document.
/// </summary>
private void InsHTMLBut_Click(object sender, EventArgs e)
{
if (this.HTMLTB.Text.Length == 0)
{
MessageBox.Show("Nothing to insert");
return;
}
mshtml.IHTMLTxtRange txt = (mshtml.IHTMLTxtRange) doc.selection.createRange();
txt.pasteHTML(this.HTMLTB.Text);
this.HTMLTB.Clear();
}
/// <summary>
/// Shows how to extract the source of the body of the document.
/// </summary>
private void VwSrcBut_Click(object sender, EventArgs e)
{
MessageBox.Show(doc.body.innerHTML);
}
}
}
结论
所有这些代码只是为了让您对如何使用 .NET 组件来完成以前需要花费大量时间来导入和设置程序集以及所有那些有趣的事情有一个基本的入门了解。此外,此代码只是一个片段 - 实际组件需要创建和初始化(请参阅包含的源代码)。
关于分发的快速说明。Microsoft.mshtml.dll 不是标准框架包的一部分 – 但它是 SDK 的一部分(自从他们从 beta 2.0 发布以来),为了避免混淆,请务必设置属性(将“复制到输出目录”设置为 true)或在您的程序集分发中包含 DLL 的副本。如果您担心再分发权限,Microsoft 已将其包含在其主互操作程序集安装程序中,并且包含您可以与您的应用程序一起分发的可再分发包。