替换 Windows Vista 及更高版本中的 DHTML 编辑控件

 

Van Kichline
Microsoft Corporation

2006 年 8 月

摘要:DHTML 编辑控件将不包括在 Windows Vista 中。 必须修改使用该控件的网页和 Windows 应用程序,以继续提供 WYSIWYG HTML 编辑器。 ) (25 个打印页

适用于:
   Windows Vista 上的 Internet Explorer 7
   适用于托管 DHTML 编辑控件的 Internet Explorer 的网页
   使用 DHTML 编辑 ActiveX 控件或 TriEdit ActiveX 文档的 Windows 应用程序

目录

简介
对 Windows 应用程序的影响
对 Web 应用程序的影响
总结

简介

DHTML 编辑控件是一个 ActiveX 控件,专为网页和 Windows 应用程序中的 WYSIWYG HTML 编辑而设计。 它最初由 Microsoft Visual InterDev 开发团队于 1998 年初发布到 ActiveX 控件库。 Internet Explorer 与 控件之间的紧密耦合使得在每次 Internet Explorer 更新中交付控件是可取的,自 1999 年初 Internet Explorer 5 发布以来,该控件已作为 Internet Explorer 的一部分交付。

将多个因素组合在一起,使对控件的持续支持随着时间的推移变得不那么可取。 Internet Explorer 不断发展,在 Internet Explorer 5.5 和 Internet Explorer 6 中整合了 WYSIWYG 自己的编辑功能。 同时,安全性已成为 Internet Explorer 的主要关注点。 为了提高安全性,浏览器会限制对潜在危险内容的访问,但编辑器侧重于确保其更改内容可以安全保存。 多个安全公告导致浏览器环境更加锁定,这降低了 DHTML 编辑控件的效用,并显著提高了其拥有成本。

因此,决定从 Windows Vista 中删除控件。 控件在 Windows Vista 的 Beta 1 版本中存在,但在后续 Beta 版本和 Windows Vista 的最终版本中不存在。

本文介绍此决策对使用该控件的现有应用程序的影响,如何确定哪些应用程序和网页使用该控件,以及如何缓解此更改对这些应用程序和网页的影响。

剖析课程

DHTML 编辑控件支持“WYSIWYG HTML 编辑”,这意味着用户可以在控件中键入文本,同时看到在网页上呈现的格式化 HTML。 各种命令允许用户调整字体、颜色和格式,并立即看到效果。 这类似于在客户端窗体中使用格式文本框控件,但控件保存的数据是 HTML 而不是 RTF。

DHTML 编辑控件比许多其他控件更复杂。 它由两个组件组成:Dhtmled.ocx 和 TriEdit.dll。 这些组件位于以下文件中,这些文件已针对 Windows Vista 删除:

  • [drive:]\Program Files\Common Files\Microsoft Shared\Triedit\dhtmled.ocx
  • [drive:]\Program Files\Common Files\Microsoft Shared\Triedit\TRIEDIT.DLL

这两个组件依次实现五个不同的对象:

Dhtmled.ocx

  • 安全脚本 DHTML 编辑控件 (DHTMLSafe)
  • 应用程序的 DHTML 编辑控件 (DHTMLEdit)
  • DEGetBlockFmtNamesParam 帮助程序对象
  • DEInsertTableParam 帮助程序对象

TriEdit.dll

  • TriEdit Document 对象

只有安全脚本 DHTML 编辑控件、 DEGetBlockFmtNamesParam 对象和 DEInsertTableParam 对象被标记为可安全编写脚本,并且可以在网页上创建。 DEGetBlockFmtNamesParamDEInsertTableParam 是简单对象,专用于向/从由 DHTML 编辑控件实现的某些命令传递数据。

应用程序的 DHTML 编辑控件是该控件的一个功能更强大的版本,可聚合安全脚本控件,旨在用于 ActiveX 托管应用程序,例如使用 Visual Basic 或 Delphi 创建的应用程序。 此控件也已从 Windows Vista 中排除。 但是,Microsoft 授权由第三方安装的类似工作版本的控件,使依赖于此控件的应用程序能够继续在 Microsoft Vista 上工作。 有关详细信息,请参阅本文档后面的 Windows 应用程序的缓解策略部分。

TriEdit Document 对象是一个 ActiveX 文档,它由两个版本的 DHTML 编辑控件使用 CoCreate 实例化,并且可由 ActiveX 文档托管应用程序单独实例化。 ActiveX 文档的承载比控件要复杂得多,但它们可以更直接地控制编辑图面的外观和集成。 与应用程序的 DHTML 编辑控件一样,使用第三方工作对象在 Windows Vista 中支持 TriEdit Document 对象。

除了提供 WYSIWYG HTML 编辑图面和一组面向典型编辑任务的属性、方法和事件外,DHTML 编辑控件和 TriEdit Document 对象都支持以下附加功能:

  • 多级撤消和重做。
  • 基础表编辑。
  • 选择功能,例如拖动移动、调整大小和 UI 激活。
  • 绝对定位和 Z 排序。
  • 源代码保留。
  • HTML 标记字形呈现。
  • 设计时控制 (DTC) 支持。 (这是 Microsoft Visual InterDev.) 中提供的一项功能
  • 键盘加速键。

其中一些功能已通过称为 MSHTML 编辑的功能(通过使用 DHTML designMode 属性实现)合并到 Internet Explorer 中。 但是,MSHTML 编辑并非支持所有 DHTML 编辑控件功能。 例如,DHTML 编辑控件中的源代码保留使它能够保留 HTML 源代码格式;源代码保留在 MSHTML 编辑中不可用。 绝对定位和 Z 排序现在由 Internet Explorer 处理。 不支持表编辑,也不支持 DTC。

由于源代码保留功能而专门使用 DHTML 编辑控件的网页将受到此更改的严重影响。 此功能没有方便的替代方法,实现替换是一个具有挑战性的技术问题。

对 Windows 应用程序的影响

包含适用于应用程序的 DHTML 编辑控件的 Windows 应用程序将不再按预期在 Windows Vista 上运行。 例如,Visual Basic 应用程序在打开或实例化包含控件的窗体时,可能会显示以下消息:

组件“dhtmled.ocx”或其依赖项之一未正确注册:文件缺失或无效。

Delphi 应用程序可能会引发未经处理的异常。

确定受影响的 Windows 应用程序

可以使用如下语法确定 Visual Basic 应用程序是否包含 Windows findstr 命令的 DHTML 编辑控件:

findstr /m DHTMLEDLibCtl.DHTMLEdit YourApplication.exe

Delphi 应用程序包含字符串“DHTMLEDLib_TLB”和“IDHTMLEdit”。 因此,可以使用以下命令查找使用 控件的 Visual Basic 和 Delphi 应用程序:

findstr /im dhtmledlib YourApplication.exe

C 和 C++ 应用程序可以直接使用 TriEdit ,而不是使用 DHTML 编辑控件。 低级别语言经常使用 CoCreateInstance 方法实例化 OLE 对象,而不是加载类型库。 在这种情况下,用于创建对象的 GUID 将编译到应用程序中。 控件和 TriEdit 文档的 GUID 如下所示:

  • TriEdit 文档:{438DA5E0-F171-11D0-984E-0000F80270F8}
  • DHTMLEdit: {2D360200-FFF5-11d1-8D03-00A0C959BC0A}
  • ITriEditDocument: {438DA5DF-F171-11D0-984E-0000F80270F8}
  • IDHTMLEdit: {CE04B591-2B1F-11D2-8D1E-00A0C959BC0A}

如果必须搜索编译的代码,则可以查看表示 GUID 的某些模式。 例如,以下 GUID:

{ABCDEFGH-IJKL-MNOP-QRST-UVWXYZ012345}

成为二进制中的以下十六进制序列:

GH EF CD AB KL IJ OP MN QR ST UV WX YZ 01 23 45

以下示例演示了一个简单的 C# 程序,用于搜索任一 GUID 的可执行二进制文件。

// Compile and execute:  "FindGUIDs YourApplication.exe"
using System;
using System.Text;
using System.IO;

namespace FindGUIDs {
class Program {
  static void Main(string[] args) {
    FileStream    fs = File.OpenRead(args[0]);
    StringBuilder sb = new StringBuilder();
    do {
      Int32 b = fs.ReadByte();
      if (-1 == b) {
        break;
      }
      sb.AppendFormat("{0:X2}", b);
    } while (true);
    fs.Close();
    String s = sb.ToString();
    if (s.Contains("E0A58D4371F1D011984E0000F80270F8"))
      Console.Out.WriteLine("GUID for TriEditDocument Class detected.");
    if (s.Contains("DFA58D4371F1D011984E0000F80270F8")) {
      Console.Out.WriteLine(
        "GUID for ITriEditDocument Interface detected.");
      }
      if (s.Contains("0002362DF5FFd1118D0300A0C959BC0A")) {
        Console.Out.WriteLine("GUID for DHTMLEdit Class detected.");
      }
      if (s.Contains("91B504CE1F2Bd2118D1E00A0C959BC0A")) {
        Console.Out.WriteLine("GUID for IDHTMLEdit Interface detected.");
      }
    }
  }
}

由于 C、C++ 和其他低级别语言可通过多种方式自由实例化 COM 对象,因此不能保证示例中所示的方法能够找到控件或文档对象的所有实例。 如果此测试为负数,请使用 Windows findstr 命令搜索 GUID 片段的文本表示形式,例如 438DA5E02D360200。 如果源代码可用,请仔细检查它。 搜索 GUID 片段或文本,例如“dhtmledit”或“triedit”。 搜索 GUID 片段非常重要,因为可通过多种方式将 GUID 表示为文本。 前八位数字是连续的,通常是唯一的,因此是一种很好的搜索模式。

Windows 应用程序的缓解策略

尽管将从 Windows Vista 中删除 DHTML 编辑控件和 TriEdit ,但 Microsoft 会将这两个二进制组件作为打包在签名的 Microsoft Windows 安装程序 (.msi 文件中的组件提供给 ISV) 。 此包中不包括 DHTML 编辑控件的安全脚本版本。 许可信息包含在此安装程序显示的最终用户许可协议中。 在安装或重新分发包之前,请仔细查看此内容。

若要获取 Windows 安装程序,请访问 Microsoft 下载中心网站。 此安装程序已签名,并且包含控件和 TriEdit 的已签名二进制文件,两者都进行了修改,以便在 Windows Vista 上使用。 此包将仅在 Windows Vista 上安装。 它不会在早期版本的 Windows(如 Windows XP)上运行。 如果尝试在早期版本的 Windows 上运行安装程序,对话框将显示错误:

此安装程序专为 Windows Vista 设计,安装将停止。

若要安装该文件,可以双击该文件,右键单击它并选择“ 安装”,也可以运行以下命令:

msiexec /i dhtmled.msi

这会安装 Dhtmled.ocx 并将其注册到以下目录中Triedit.dll:

%windir%\Program Files\Common Files\Microsoft Shared\dhtmled\

安装控件会将“DHTML 编辑组件”条目添加到 Windows 控制面板中的“添加或删除程序”应用程序中。

安装 Windows Vista 版本的二进制组件后,适用于 Application 和 TriEdit 的 DHTML 编辑控件的用户体验将与早期版本的 Windows 上的用户体验无法区分。 保留所有功能,并且所有 GUID、ProgID、类型库名称等都相同。 (安全脚本 DHTML 编辑控件的用户体验存在差异,这在 Windows Vista 上被省略。有关详细信息,请参阅本文档后面的对 Web 应用程序的影响部分。)

旧版应用程序

如果使用 Dhtmled.msi 安装程序,旧版应用程序将像往常一样在 Windows Vista 下工作。 如果尚未安装新的二进制组件,则包含适用于应用程序的 DHTML 编辑控件的旧应用程序在 Windows Vista 下执行时,它们将显示各种故障模式。 如果你是应用程序供应商,则可以直接向最终用户提供更新或发送获取 Windows Vista 安装程序的说明,然后用户可以自行安装 Windows Vista 版本并继续使用其应用程序。 安装 Windows Vista 后遇到错误的用户很可能在联系客户服务之前在 Web 上搜索错误消息文本和产品名称。 因此,应发布有关查找安装程序的信息。 对于大多数用户来说,下载和安装 Windows Vista 版本的二进制组件非常简单。

新建应用程序

对于新应用程序,可以将安装程序作为产品 (的一部分交付,并附带相应的许可) ,并从自己的安装程序链接到它。 安装程序可以静默运行,而无需将项添加到 Windows 中的已安装程序列表。 (有关详细信息,请参阅 MsiExec.exe.) 的文档

但是,我们建议安装程序允许将 DHTML 编辑控件添加到已安装程序列表。 此外,卸载应用程序时,请勿卸载控件;而是允许客户根据需要单独卸载它。

请注意,此安装方法不提供符合徽标标准的安装。 确定此缓解措施是可接受的,原因如下:

  • 包含组件的应用程序数量有限。
  • 单个计算机托管其中多个应用程序的可能性很低。
  • 如果应用程序被卸载 DHTML 编辑控件的另一个 应用程序破坏, 则可以使用 “添加或删除程序” 应用程序中提供的“修复”选项轻松修复损坏的应用程序。

如果应用程序需要徽标合规性,则必须指示用户单独安装适用于 Windows Vista 的 DHTML 编辑控件。

对 Web 应用程序的影响

自 Internet Explorer 5 发布以来,DHTML 编辑控件可用于 HTML、ASP 和 ASP.NET 页面,以及通过 HTTP 访问的其他文档。 在 Windows Vista 上,使用安全脚本 DHTML 编辑控件的网页将无法加载控件。 相反,将显示图像占位符:

Aa663363.htmleditinfuture01 (en-us,MSDN.10) .gif

此外,引用控件的任何脚本都将引发异常。 由于脚本异常会终止脚本评估,因此脚本控制的不相关功能很可能也会失效。 因此,必须修改或重新定位包含适用于脚本的安全 DHTML 编辑控件且可供 Windows Vista 客户端使用的页面。

注意 最初,应用程序的 DHTML 编辑控件 (在网页上使用不安全的脚本) 控件也 () 警告消息,但随着 Internet Explorer 6 的发布,控件中的安全强化使得应用程序版本在网页上几乎不可用。 任何功能网页都不可能实例化应用程序的 DHTML 编辑控件。

确定受影响的网页

包含安全脚本 DHTML 编辑控件的网页将实现它作为 <对象> 标记,如下所示:

<!-- The DHTML Editing Control; original GUID -->
<OBJECT id="editor" height=400 width=640
  classid="clsid:2D360201-FFF5-11d1-8D03-00A0C959BC0A">
</OBJECT>

许多使用 控件的网页是使用 Microsoft Visual InterDev 创建的,或者使用 Visual InterDev 生成的示例代码。 在这种情况下,标记将如下所示:

<OBJECT classid="clsid:2D360201-FFF5-11D1-8D03-00A0C959BC0A"
    class="anyClass" ID="editor" VIEWASTEXT>
  <PARAM name="ActivateApplets" value="0">
  <PARAM name="ActivateActiveXControls" value="-1">
  <PARAM name="ActivateDTCs" value="-1">
  <PARAM name="ShowDetails" value="0">
  <PARAM name="ShowBorders" value="0">
  <PARAM name="Appearance" value="0">
  <PARAM name="Scrollbars" value="-1">
  <PARAM name="ScrollbarAppearance" value="1">
  <PARAM name="SourceCodePreservation" value="-1">
  <PARAM name="AbsoluteDropMode" value="0">
  <PARAM name="SnapToGrid" value="0">
  <PARAM name="SnapToGridX" value="50">
  <PARAM name="SnapToGridY" value="50">
  <PARAM name="UseDivOnCarriageReturn" value="1">
</OBJECT>

其他标记表示控件支持的参数的初始化值。 保存控件的属性包的网页设计应用程序将在保存页面时将这些 PARAM 标记与 HTML 内容一起包含在内。

最有效的快速检查是在网页存储中搜索常见 GUID (2D360201-FFF5-11D1-8D03-00A0C959BC0A) 或仅搜索片段 2D360201。 包含此文本的页面几乎可以肯定包含安全脚本 DHTML 编辑控件。

Web 应用程序的缓解策略

为了响应从 Windows Vista 中删除 DHTML 编辑控件和 TriEdit,Microsoft 已将适用于应用程序和 TriEdit 的 DHTML 编辑控件作为系统组件提供,这些组件打包在签名的 Windows 安装程序 (.msi 文件中) 。 但是,DHTML 编辑控件的安全脚本版本将不包含在此包中。

DHTML 编辑控件实现的大部分功能都通过 MSHTML 编辑(即通过使用 designMode 属性)直接在 Internet Explorer 中提供。 因此,在许多情况下,控件的功能可以替换为 MSHTML 编辑,例如,将 <iframe> 元素置于设计模式,如本文档稍后所述。

使用替代控件

一种缓解策略是使用替代 ActiveX 控件或 ASP.NET 自定义控件作为替代项。 在 Web 上搜索“HTML 即所得编辑器控件”会建议多个候选项。 Microsoft 尚未对这些产品进行调查,也无法提出建议。 因此,必须确定最适合自己需求的方案。 任何替换项都可能具有与 DHTML 编辑控件不同的对象模型,并且需要使用 控件修改页面上的支持脚本。 此修改的难度取决于实现的复杂程度。

实现选择性重定向

只有 Windows 上运行的 Internet Explorer 浏览器才能实例化安全脚本 DHTML 编辑控件。 因此,如果你有一个适用于各种浏览器的“reach”应用程序,则可能已在应用程序中内置了浏览器检测和重定向。 例如,应用程序可能会将 Internet Explorer 请求重定向到包含 控件的页面,并将其他浏览器请求重定向到使用其他输入方式的页面。

可以通过检查随请求一起发送的用户代理字符串来确定请求是否源自 Windows Vista。 Windows Vista 上 Internet Explorer 7 的用户代理字符串如下所示:

Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; MSDigitalLocker Vista 
1.3; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; WinFX RunTime 
3.0.50727; InfoPath.1)

C# 中的以下示例演示了用于检测和重定向来自 Windows Vista 和 Internet Explorer 7 的请求的代码。

protected void Page_Load(object sender, EventArgs e) {
    string ua = Request.UserAgent.ToLower();
    bool isVista = ua.Contains("windows nt 6.");
    bool isIE7 = ua.Contains("msie 7.");
    Response.Redirect((isVista && isIE7) ?
        "Surrogate.htm" : "DHTMLEd.htm");
}

在 Visual Basic Scripting Edition (VBScript) for ASP 中,以下代码完成相同的任务。

<% @Language = "VBScript" %>
<%
Dim ua, isVista, isIE7
ua = LCase(Request.ServerVariables("HTTP_USER_AGENT"))
isVista = (0 < InStr(ua, "windows nt 6."))
isIE7   =  (0 < InStr(ua, "msie 7."))
If isVista AND isIE7 Then
    Response.Redirect "Surrogate.htm"
Else
    Response.Redirect "DHTMLEd.htm"
End If
%>

重新实现编辑功能

如果 DHTML 编辑控件的功能绝对必要,并且替换不切实际,则最佳策略可能是使用 MSHTML 编辑和脚本重新实现控件的功能。 INTERNET Explorer 5.5 及更高版本中提供 MSHTML 编辑功能;DHTML 编辑控件可用于 Internet Explorer 5.0 及更高版本。 因此,如果重新实现该功能,可能仍需要为拥有 Internet Explorer 5.0 的用户提供包含 DHTML 编辑控件的重定向页面。

本部分介绍使用 iframe> 元素重新实现安全脚本 DHTML 编辑控件功能的一种方法<。 可以使用如下所示的页面实现基本编辑功能:

<html>
<head>
<title>DHTML Editing Control Surrogate Example</title>
<script type="text/javascript">
function FillEditor() {
    var doc = editor.document;
    doc.designMode = "on";
    doc.write("<body><p><i>Visualize</i> <u>peace</u></p></body>");
    doc.close();
}
</script>
</head>
<body onload="FillEditor()">
  <iframe id="editor" scrolling="yes" height="100" width="300">
  </iframe>
  <p>
  <input type=button 
     value="Submit" 
     onclick=
       "alert(editor.document.getElementsByTagName('HTML')[0].outerHTML)">
</body>
</html>

此页面显示包含格式化 HTML 的可编辑区域。 可以在此区域中键入,并使用热键(如 CTRL+I)切换斜体,使用 Ctrl+you 切换下划线。 按“提交”按钮时,消息框会显示 iframe> 元素的< HTML 内容。 若要实现 DHTML 编辑控件的属性、方法和事件的等效项,必须使用脚本。

出于安全原因,只能跨 <iframe> 边界访问同一域中的内容。 若要确保可以访问帧的内容,请使用 src 属性从同一域中的 URL 对其进行初始化,如以下示例所示:

<iframe id="editor" 
  scrolling="yes" 
  height="100" 
  width="300" 
  src="templates/blank.htm">
</iframe>

有关在 Internet Explorer 中使用 designMode 属性进行编辑的详细信息,请参阅 Microsoft 网站上的 MSHTML 编辑简介 页。

方法

下表列出了安全脚本 DHTML 编辑控件中的方法,以及是否可以使用 Internet Explorer 中的脚本重新实现这些方法。

安全脚本 DHTML 编辑控件的方法

命令 是否可支持?
ExecCommand 部分
QueryStatus 部分
SetContextMenu
NewDocument
LoadURL
FilterSourceCode
“刷新” 不是必需

可以通过对 对象调用 editor.document.execCommand 和 查询命令editor.document来替换 ExecCommandQueryStatus 方法。 DHTML 编辑控件实现的命令子集可通过脚本获取,如本文档后面的 CommandID 值部分所述。

若要在 MSHTML 编辑中获取 QueryStatus 方法的功能,必须包含类似于以下内容的代码:

var NOTSUPPORTED =  0;
var DISABLED     =  1;
var ENABLED      =  3;
var LATCHED      =  7;
var NINCHED      = 11;
var result = NOTSUPPORTED;
if(editor.document.queryCommandSupported(cmdName)) {
    result = editor.document.queryCommandEnabled(cmdName) ?
        ENABLED : DISABLED;
    if(ENABLED == result) {
        if(editor.document.queryCommandIndeterm(cmdName)){
            result = NINCHED;
        }
        else if(editor.document.queryCommandState(cmdName)) {
            result = LATCHED;
        }
    }
}

有关方法的其他说明

SetContextMenu 方法采用字符串数组和状态数组 (MENU_UNCHECKED=0MENU_CHECKED=1MENU_GRAY=2) 并存储它们,直到编辑器引发 oncontextmenu 事件为止。 若要替换此方法,请使用许多可用的 HTML 上下文菜单实现之一 (大多数使用 createPopup 方法) 。

如果支持 UseDivOnCarriageReturn 属性,则重载时使用的内容取决于属性的值。 如果支持 Dirty 属性,请在创建新文档时将其清除。

NewDocument 方法将编辑器的内容替换为空白文档。 若要替换此命令,可以使用如下所示的脚本:

var htmlP = "<html><head><title>New Document</title></head>" + 
    "<body><p>&nbsp;</p></body></html>";
var htmlD = "<html><head><title>New Document</title></head>" + 
    "<body><div>&nbsp;</div></body></html>";
var useDivOnCR = false;
function NewDocument() {
    editor.document.write(useDivOnCR ? htmlD : htmlP);
    editor.document.close();
}

若要替换 LoadURL 方法,请使用等 editor.src=url代码。 如果支持 Dirty 属性,请在加载新文档时将其清除。

FilterSourceCode 方法用于源代码保留,不能在脚本中重新实现。 如果需要定义此方法以确保兼容性,只需返回其参数,如以下示例所示。

function FilterSourceCode(str) { return str; }

Refresh 方法使控件窗口的矩形失效,并可由不执行任何操作的方法替换,如以下重新实现中所示。

function Refresh() {}

属性

下表列出了安全脚本 DHTML 编辑控件中的属性,以及是否可以使用 Internet Explorer 中的脚本重新实现这些属性。

安全脚本 DHTML 编辑控件的属性

属性 数据类型 方向 是否可支持?
CurrentDocumentPath 字符串
DOM Object
DocumentHTML 字符串 输入/输出
IsDirty 布尔 部分
SourceCodePreservation 布尔 输入/输出
ActivateApplets 布尔 输入/输出
ActivateDPC 布尔 输入/输出
ActivateActiveXControls 布尔 输入/输出
ShowDetails 布尔 输入/输出
ShowBorders 布尔 输入/输出
AbsoluteDropMode 布尔 输入/输出
滚动条 布尔 输入/输出
外观 特殊 输入/输出
ScrollbarAppearance 特殊 输入/输出
SnapToGridX Long 输入/输出
SnapToGridY Long 输入/输出
SnapToGrid 布尔 输入/输出
BaseURL 字符串 输入/输出
DocumentTitle 字符串
UseDivOnCarriageReturn 布尔 输入/输出
布尔

有关属性的其他说明

可以通过返回 editor.location.href来实现 CurrentDocumentPath 属性。

DOM 属性等效于 editor.document

DocumentHTML 属性可以实现为 editor.getElementsByTagName('HTML')[0].outerHTML

无法完全替换 IsDirty 属性。 可以通过为修改文档的所有方法、属性和命令设置与编辑器 <iframe> 元素关联的全局变量来近似它。 各种事件都可能导致文档脏,例如 oncutonpasteondroponmove。 有关详细信息,请参阅本文档后面事件下的 DisplayChanged 事件的注释。 NewDocumentLoadURL 等方法必须清除全局脏标志。

无法在脚本中实现 SourceCodePreservationActivateAppletsActivateDDCActivateActiveXControlsShowDetailsShowBordersAbsoluteDropModeSnapToGridSnapToGridXSnapToGridY 属性。

Appearance 属性设置 DHTML 编辑控件本身边框的外观。 在重新实现中,可以设置 editor.frameBorder

Scrollbars 属性可以通过设置为editor.body.scroll“是”或“否”来实现。 可以使用比较 (editor.body.scroll=="no")

若要重新实现 ScrollbarAppearance 属性,请使用 CSS 属性。 (有关详细信息,请在 Web 上搜索“CSS 平面滚动条”。)

DocumentTitle 属性可以替换为 editor.document.title

UseDivOnCarriageReturn 属性旨在帮助指定 (间接) ENTER 键的行为。 默认情况下,在可编辑的 HTML 区域中按 Enter 会 <插入 p> 元素。 在 DHTML 编辑控件中,按下 Enter 键时,用户键入的块元素将拆分为两个类似的块。 如果游标位于 p> 元素中,则会创建另一个<<具有类似属性的 p> 元素。 如果光标位于 div> 元素中<,则会创建另一个 <div> 元素。

UseDivOnCarriageReturn 属性指定通过调用 NewDocument 方法创建空白文档时使用的默认块元素。 如果 属性设置为 true,则默认块为 <div> 元素,其初始文本如下所示:

<HTML>
<HEAD><TITLE></TITLE></HEAD>
<BODY><DIV>&nbsp;</DIV></BODY>
</HTML>

否则,初始文本将类似于以下内容:

<HTML>
<HEAD><TITLE></TITLE></HEAD>
<BODY><P>&nbsp;</P></BODY>
</HTML> 

Busy 属性指示当前正在加载控件。 这可以替换为 editor.document.readyState != "complete"

重新实现 BaseURL 属性

BaseURL 属性设置用于解析相对 URL 的 URL 的根部分。 DHTML 编辑控件和 MSHTML 编辑在这方面的工作方式之间存在显著差异。 当 DHTML 编辑控件最初在 Internet Explorer 4 中引入时,文档对象模型 (DOM) 不包含对 <head> 元素的访问权限,因此 <无法以编程方式将基> 元素添加到文档。 相反,控件在内部将相对 URL 与 BaseURL 属性中存储的基 URL 组合在一起。 在当前版本的 Internet Explorer 中, <基> 元素可以轻松添加到编辑器文档中,但使用此方法会导致行为与控件的 BaseURL 属性的行为不同,因为元素成为属性内容的一部分 editor.document 。 因此,若要模拟 BaseURL 属性的控件的行为,必须在从文档的内容获取 HTML 内容后从文档中删除 <基> 元素。 重新实现 BaseURL 属性并不简单,应仔细测试应用程序,以确保看到想要的行为。

另一个区别是,DHTML 编辑控件执行 IDM_NOFIXUPURLSONPASTE 命令,该命令在脚本中不可用。 此命令可防止将内容粘贴到可编辑区域时将相对 URL 更改为绝对 URL。 可以设置 <基> 元素来替代此修复,或使用正则表达式来更正此差异。

若要获取文档的 <基> 元素标记值,请使用如下所示的脚本:

var baseHref = "";
var h = editor.document.getElementsByTagName("head");
if((undefined != h) && (0 < h.length)) {
    var b = h[0].getElementsByTagName("base");
    if((undefined != b) && (0 < b.length)) {
        baseHref = b[0].href;
    }
}

若要设置文档的 <基> 元素,请使用如下所示的脚本:

var h = editor.document.getElementsByTagName("head");
if((undefined != h) && (0 < h.length)) {
    var b = h[0].getElementsByTagName("base");
    if((undefined == b) || (0 == b.length)) {
        var nb = editor.document.createElement("BASE");
        nb.href = newBaseHrefValue;
        h[0].insertAdjacentElement("afterBegin", nb);
    }
    else
        b[0].href = newBaseHrefValue;
}

若要从属性内容返回editor.document的文本中删除<基>标记,请使用如下所示的脚本:

var html = DocumentHTML();
var rex = new RegExp("<BASE[\\s]+[^>]*>", "i");
html = html.replace(rex, "");

事件

下表列出了安全脚本 DHTML 编辑控件中的事件,以及是否可以使用 Internet Explorer 中的脚本重新实现这些事件。

安全脚本 DHTML 编辑控件的事件

事件 可支持?
DocumentComplete
DisplayChanged 部分
ShowContextMenu (xPos,yPos) 是,修改后
ContextMenuAction (itemIndex) 是,修改后
Onmousedown
Onmousemove
Onmouseup
Onmouseout
Onmouseover
Onclick
Ondblclick
Onkeydown
Onkeypress
Onkeyup
Onblur
Onreadystatechange

可以在脚本中以编程方式附加大多数事件。 onmousedownonmousemoveonmouseuponmouseoutonmouseoveronclickondblclickonkeydownonkeypressonkeyup 事件都可以使用如下语法进行绑定:

editor.document.attachEvent(" EventName", EventHandlerFunction)

重新加载 iframe> 元素的内容<时,onreadystatechangeonfocusonblur 绑定可能会重置。 因此,如果需要,可以使用 iframe> 元素上的<属性以声明方式绑定这些事件,这将跨重载保留绑定。 以下示例显示了这些事件的声明性绑定:

<iframe ID="editor" SCROLLING="yes" onreadystatechange="editor_ReadyStateChange()"
  onfocus="editor_OnFocus" onblur="editor_Blur()"></iframe>

可以通过处理 onreadystatechange 事件并包括测试 editor.document.readyState=="complete"来重新实现 DocumentComplete 事件的功能。 这是重新附加其他事件的适当时机, (文档重载后) 之前记下的事件除外。

DisplayChanged 事件对于重新实现并不简单。 此事件在 DHTML 编辑控件 (频繁引发,包括每次移动鼠标) ,但对于保持 UI 元素(如工具栏)处于正确状态绝对是必需的。 DHTML 编辑控件将引发 DisplayChanged 事件,以响应控件的 IOleCommandTarget 对象上的 OLECMDID_UPDATECOMMANDS 命令,该命令是脚本不可访问的。 若要模拟 DisplayChanged 事件,请无条件地引发该事件,以响应 onmousedownonkeypressonfocusonreadystatechangeoncutonpasteondroponmoveonselectionchange 事件。 此外,当键是光标移动键时,应针对 onkeydown 引发,当键是执行格式更改的热键之一时,应针对 onkeyup 引发它。 当执行设置值的命令时,应引发 DisplayChanged 事件,并且 onmousemove 可能需要该事件,具体取决于应用程序是否更改 UI 以响应指针移动的元素。

可以使用如下代码检测是否已按下热键:

function IsHotKey(ev) {
    if(ev.ctrlKey && !ev.altKey) {
        var key = ev.keyCode;
        if((66 == key) || (73 == key) || (85 == key)) {
            return true;
        }
    }
    return false;
}

若要检测光标移动键是否已按下,请使用如下所示的脚本:

function IsCursorMovementKey(key) {
    if(key >= 37 && key <= 40 || key == 9) {
        return true;
    }
    return false;
}

ShowContextMenu 事件大致等效于 DHTML oncontextmenu 事件,但包含 X 和 Y 参数。 HTML 事件模型不提供任何将参数包含在事件中的方法。 因此,必须更改 ShowContextMenu 事件的任何处理程序;对 X 和 Y 参数的任何引用都可以替换为 editor.document.event.xeditor.document.event.y

ContextMenuAction 事件类似于 ShowContextMenu 事件,其中参数不能包含在事件中,因此代码需要修改。 若要替换它,请使用 createEventObject(editor.document.event) 为响应用户选择而引发的事件对象来创建该对象。 将事件对象的 returnValue 属性设置为上下文菜单实现中选择的菜单项的 ID。 在宿主代码中,计算 returnValue 而不是 ContextMenuAction 事件返回的 itemIndex 参数。

CommandID 值

下表列出了与 DHTML 编辑控件中的 ExecCommandQueryStatus 方法一起使用的命令 ID,如果任何) 与 DHTML execCommand 方法一起使用,则相应的命令 (。

ExecCommand 和 QueryStatus 使用的 CommandID 值

DHTMLEdit 命令 Cmd ID execCommand 备注
DECMD_BOLD 5000 “Bold” 切换
DECMD_COPY 5002 “Copy”  
DECMD_CUT 5003 “Cut”  
DECMD_DELETE 5004 “Delete”  
DECMD_DELETECELLS 5005   无表格编辑
DECMD_DELETECOLS 5006   无表格编辑
DECMD_DELETEROWS 5007   无表格编辑
DECMD_FINDTEXT 5008   无对话框
DECMD_FONT 5009   无对话框
DECMD_GETBACKCOLOR 5010 “BackColor” 特殊值
DECMD_GETBLOCKFMT 5011   重新实现
DECMD_GETBLOCKFMTNAMES 5012   重新实现
DECMD_GETFONTNAME 5013 “FontName”
DECMD_GETFONTSIZE 5014 “FontSize”
DECMD_GETFORECOLOR 5015 “ForeColor” 特殊值
DECMD_HYPERLINK 5016 “CreateLink”  
DECMD_IMAGE 5017 “InsertImage”  
DECMD_INDENT 5018 “缩进”  
DECMD_INSERTCELL 5019   无表格编辑
DECMD_INSERTCOL 5020   无表格编辑
DECMD_INSERTROW 5021   无表格编辑
DECMD_INSERTTABLE 5022   无表格编辑
DECMD_ITALIC 5023 “Italic” 切换
DECMD_JUSTIFYCENTER 5024 “JustifyCenter”  
DECMD_JUSTIFYLEFT 5025 “JustifyLeft”  
DECMD_JUSTIFYRIGHT 5026 “JustifyRight”  
DECMD_LOCK_ELEMENT 5027   Z 排序
DECMD_MAKE_ABSOLUTE 5028 “2D 位置”
DECMD_MERGECELLS 5029   无表编辑
DECMD_ORDERLIST 5030 “InsertOrderedList”  
DECMD_OUTDENT 5031 “Outdent”  
DECMD_PASTE 5032 “Paste”  
DECMD_REDO 5033   无撤消
DECMD_REMOVEFORMAT 5034 “RemoveFormat”  
DECMD_SELECTALL 5035 “SelectAll”  
DECMD_SEND_BACKWARD 5036   Z 排序
DECMD_BRING_FORWARD 5037   Z 排序
DECMD_SEND_BELOW_TEXT 5038   Z 排序
DECMD_BRING_ABOVE_TEXT 5039   Z 排序
DECMD_SEND_TO_BACK 5040   Z 排序
DECMD_BRING_TO_FRONT 5041   Z 排序
DECMD_SETBACKCOLOR 5042 “BackColor”
DECMD_SETBLOCKFMT 5043 “FormatBlock”
DECMD_SETFONTNAME 5044 “FontName”
DECMD_SETFONTSIZE 5045 “FontSize”
DECMD_SETFORECOLOR 5046 “ForeColor”
DECMD_SPLITCELL 5047   无表编辑
DECMD_UNDERLINE 5048 “下划线” 切换
DECMD_UNDO 5049   无撤消
DECMD_UNLINK 5050 “取消链接”  
DECMD_UNORDERLIST 5051 “InsertUnorderedList”  

命名命令 (上表中 execCommand 列中具有名称的命令) 可以使用以下调用之一执行: editor.document.execCommand(commandName)editor.document.execCommand(commandName, 0, parameter)。 未命名命令表示的功能在 MSHMTL 编辑中不可用,但标记为“重新实现”的命令除外。

无法重新实现通过 DHTML 编辑控件的 ExecCommandQueryStatus 方法提供的未命名命令,因为 INTERNET Explorer 中的 MSHTML 编辑施加了以下限制:

  • 撤消。 不支持撤消和恢复命令。
  • Z 排序。 可以实现 Z 顺序命令,例如“向后发送”“前移”。 但是,由于 designMode 编辑不支持重新定位和调整绝对定位元素的大小,因此三维编辑太弱而无法使用,因此本文档中不会介绍这些命令。
  • 表编辑。 DHTML 编辑控件包含一些表编辑命令。 MSHMTL 编辑不支持这些命令,但有一个表对象模型可以帮助在必要时重新实现这些命令。

读取块格式信息

MSHMTL 编辑不支持 与 DECMD_GETBLOCKFMT 命令等效。 在 控件中,此命令使用 DECMD_SETBLOCKFMTDECMD_GETBLOCKFMTNAMES 命令使用的名称返回包含当前选定内容块的名称。 更新格式块的命令栏 UI 需要 DECMD_GETBLOCKFMT 等命令。 可以使用如下所示的脚本来估计其功能:

var _blockFormats = {
    "BODY"    : "Normal",
    "P"       : "Normal",
    "PRE"     : "Formatted",
    "ADDRESS" : "Address",
    "H1"      : "Heading 1",
    "H2"      : "Heading 2",
    "H3"      : "Heading 3",
    "H4"      : "Heading 4",
    "H5"      : "Heading 5",
    "H6"      : "Heading 6",
    "OL"      : "Numbered List",
    "UL"      : "Bulleted List",
    "DIR"     : "Directory List",
    "MENU"    : "Menu List",
    "DT"      : "Definition Term",
    "DD"      : "Definition"
};

function GetBlockFmt() {
    try {
        var sel = editor.document.selection;
        if(undefined != sel) {
            var selEl = sel.createRange().parentElement();
            do {
                if(undefined == selEl) {
                    return "Normal";
                }
                var item = _blockFormats[selEl.tagName];
                if(undefined != item) {
                    return item;
                }
                selEl = selEl.parentElement;
            } while(true);
        }
    }
    catch(e) {
    }
    return "Normal";
}

GetBlockFmtNames 命令在 DHTML 编辑控件中并不常见,因为它返回枚举名称的自定义帮助程序对象。 这是 Visual Basic 和 JScript 之间兼容性所必需的,但在任何重新实现中都不需要这样做。 可以使用对话框帮助程序对象 ({3050f819-98b5-11cf-bb82-00aa00bdce0b}) 获取块格式名称和字体列表的枚举列表。 有关详细信息,请在 Web 上搜索“对话框帮助程序对象”。 必须修改托管代码以枚举此集合,而不是访问原始帮助程序对象。

其他重新实现注意事项

本部分讨论重新实现 DHTML 编辑控件功能的一些其他注意事项。

对话框

在 Internet Explorer 中实现且控件使用命令 ID 调用的 “查找 ”和“ 字体 ”对话框不会向脚本公开。 如果你有用于选取字体的 UI,则需要将其替换为从对话框帮助程序对象获取的字体名称列表。

可以使用如下所示的脚本实现 Find 命令:

function Find() {
    var rng = editor.document.body.createTextRange();
    var txt = prompt("Enter text to search for", "");
    var found = rng.findText(txt);
    if(found) {
        rng.select();
    }
}

颜色值

DHTML BackColorForeColor 属性返回十进制值,而 DHTML 编辑控件返回十六进制字符串。 如果代码依赖于十六进制颜色值,请使用如下所示的脚本将十进制值转换为十六进制值。

function DecToHexColor(dVal) {
    var hVal = dVal.toString(16);
    if (hVal.length < 6) {
        var temp = "000000".substring(0,6-hVal.length);
        hVal = temp.concat(hVal);
    }
    return hVal;
}

命名命令

上表中的其余命令具有可传递给 editor.document.execCommand 方法的名称。 有关每个命令的详细信息,请参阅 Microsoft 网站上的 “方法 ”页中提供的命令标识符文档。

上表中标记为“切换”的命令不采用任何参数,在执行当前选定内容时切换其状态。 调用 set 命令时,标记为“Value”的命令需要值,并在调用 get 命令时返回值。 不带注释的命令在没有参数的情况下执行。

使用 HTML 组件

作为实际重新实现的示例,我们改造了 Microsoft Outlook Web Access (OWA) ,无需安全脚本 DHTML 编辑控件即可工作。 控件已嵌入多个版本的 Web 应用程序中,因此代码严重依赖于控件的对象模型。

一个重要要求是能够重新实现控件的行为,同时尽可能少地对托管应用程序进行更改。 因此,我们使用 Internet Explorer HTML 组件 (HTC) 一种行为。 这是一个以 DHTML 和脚本编写的组件,然后可以使用自定义标记标记在网页上实例化该组件。 实际上,我们不仅重新实现了 DHTML 编辑控件的功能,还使用此 HTC 模拟了控件。 结果是,我们只需要对支持代码进行少量更改,在 OWA 上投入的努力有可能转移到其他应用程序。

为了避免在 HTC 脚本中定义的元素与页面上的元素之间可能发生的冲突,我们将该行为实现为“视图链接”的 HTC。 这封装了行为的元素,使它们对宿主应用程序不可见。

OWA 已编码为重定向到特定浏览器的不同页面,因此我们能够创建新的模板,向特定浏览器提供相应页面。 模拟控件减少了修改支持模板的代码的需求。

在名为 Surrogate.htc 的文件中声明 HTC 可能类似于以下内容:

<PUBLIC:COMPONENT tagName="SurrogateDhtmlEditor" supportsEditMode="true">
<PUBLIC:DEFAULTS tabStop="true" viewMasterTab="false"
  viewLinkContent="true"/>
  ...
  <PUBLIC:METHOD NAME="MethodName"/>
  ...
  <PUBLIC:PROPERTY NAME="PropName" PUT="put_Prop" GET="get_Prop"/>
  ...
</PUBLIC:COMPONENT>

<IFRAME ID="editor"
  SCROLLING="yes"
  onreadystatechange="EditorReadyStateChange()"
  onfocus="EditorFocus()"
  onblur="EditorBlur()">
</IFRAME>

<OBJECT ID="dlgHelper" WIDTH="0px" HEIGHT="0px"
  CLASSID="clsid:3050f819-98b5-11cf-bb82-00aa00bdce0b">
</OBJECT>
<SCRIPT language="javascript" src="SurrogateDhtmlEditor.js">

若要在网页中实例化此 HTC,可以执行以下操作:

<HTML xmlns:editing>
<HEAD>
<?IMPORT namespace="editing" implementation="controls/surrogate.htc" >
...
</HEAD>
<BODY>
...
<editing:SurrogateDhtmlEditor class="EditorClass" id="editor" height="200" width="100%" />
...
</BODY>
</HTML>

下表提供了有关前面示例中所示的元素的说明,你将用自己的值替换这些元素。

元素 备注
xmlns: 编辑 为 XML 命名空间选择所需的任何名称。
namespace=“editing 这必须与指定的 XML 命名空间匹配。
implementation=“controls/surrogate.htc 这是你正在使用的 HTC 文件的相对路径。
< editing:SurrogateDhtmlEditor> ) (editing 标记前缀必须与指定的 XML 命名空间匹配。 ) (SurrogateDhtmlEditor 标记名称必须与 HTC 文件第一行中的 tagName 属性的值匹配。
id=“editor 这是用于引用应用程序中的编辑组件的 ID。

通过使用 HTC,我们能够以与 Windows Vista 兼容的方式维护最初使用 DHTML 编辑控件实现的所有功能。 HTC 未实现 DHTML 编辑控件的所有功能,但我们能够实现 OWA 所需的所有功能。

总结

安全脚本 DHTML 编辑控件在 Windows Vista 中不可用。 如果 Web 应用程序当前依赖于 控件,则可以执行以下操作:

  • 查找第三方替换控件。
  • 使用 <iframe> 元素和脚本重新实现所需的功能。
  • 将 控件替换为 INTERNET Explorer HTML 组件 (HTC,这是一种行为) 以封装所需功能的脚本形式编写。 我们能够在依赖于安全脚本 DHTML 编辑控件(即 Outlook Web Access)的最突出的应用程序之一中成功使用此方法。

适用于应用程序的 DHTML 编辑控件和 TriEdit ActiveX 文档对象也不会包含在 Windows Vista 中,但可以单独下载,并且可以获得分发许可。 在 Windows Vista 上安装这些对象后,控件或文档对象的用户体验与早期版本的 Windows 上的用户体验相同。