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

带实时预览的代码项目文章编辑器

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.84/5 (58投票s)

2008年2月1日

CPOL

5分钟阅读

viewsIcon

118387

downloadIcon

3952

帮助作者在 CodeProject 上撰写文章的工具

screenshot_small.png

点击图片查看完整截图 - 306 KB

目录

{ 自动生成的目录 }

引言

这是一篇关于我用特别支持来撰写 Code Project 文章的 HTML 编辑器的短文。

背景

Office 2007 中没有 Frontpage 的版本,我以前曾用它来写文章。我不想在 Office 2007 上安装 Frontpage 2003“以防万一!”。所以,我找了一个可以一边显示 HTML 源代码一边进行预览的 HTML 编辑器。Visual Studio 是我找到的最好的,但预览必须在 HTML 的下方,这不适合我的宽屏显示器。所以我决定自己写一个。这是我的作品,希望您觉得它有用。

注意: 正如 Derek Bartram 在下面的讨论区指出的,Visual Studio 2008 可以将源代码和设计视图垂直分割。设置如下:

Tools | Options | HTML Designer | General | Split views vertically

组装说明

这是一个基础的 Windows Forms 应用程序,使用了 Weifen Luo 的 DockPanel Suite [^],所以您可以按照自己的意愿排列窗格。编辑器是来自 ic#code [^] 的 #develop 项目的一部分。我也使用了他们的 #ziplib。预览窗格是一个普通的 WebBrowser 控件。

使用 BobBuilder

窗口类型

BobBuilder 中有两种类型的窗口:编辑器和预览。每个文档必须正好有一个编辑器窗口打开,但是您可以任意数量的预览窗口打开。

编辑器窗口

来自 #developTextEditor 控件有很多不错的特性,如撤销/重做和语法高亮。它还提供了许多选项,我在“工具 | 选项”对话框中公开了它们。我为一些 HTML 标签添加了快捷方式,例如 <code><pre>,这些标签在 Code Project 的文章中很常见。另外,当您在开标签内时,按下 TAB 键会自动关闭标签并把光标放在中间。

自动完成

为了防止渲染非法 HTML,有一些“自动完成”的字符。首先,如果您输入 <,您将得到 <>。然后,如果您在标签内,引号 " 和单引号 ' 会成对出现。

预览窗口

预览窗口在您使用编辑器时会不断更新。如果您为“导航开始”事件设置了系统声音,您可能想禁用它!预览窗口会尝试在每次更新时记住它们的滚动位置,但如果渲染了非法 HTML,这是不可能的。

工具条

有用于标准格式化(如粗体斜体)的按钮。还有一个用于插入“clickety”的 Action

目录

有一个菜单项和一个工具条按钮用于插入目录。此命令使用 Regex 解析 HTML 中的所有 <hN> 标签,并在它们周围插入锚点。然后它会添加链接的无序列表来构成目录。如果目录已存在,则会被替换。否则,新目录将被插入到当前光标位置。

已知问题

链接

任何相对超链接,例如到锚点的链接,在预览窗口中都无法工作。这是因为 HTML 是通过它们的 DocumentText 属性传递给 WebBrowser 控件的。发生这种情况时,WebBrowser 会将 URI 设置为 about:blank,然后问题就来了……

但是,在 HTML 传递给 WebBrowser 控件之前,它会被稍作修改。会添加一些 JavaScript 来帮助维护滚动位置,并添加一个 <base> 标签来使诸如图像之类的内联引用工作正常。您可以随时保存文档并使用“工具 | 外部浏览器”来快速检查您的相对链接是否正常工作。

注意: 当您上传文章时,HTML 会被放在主目录之一,但所有其他文件(图片、ZIP 等)都会被放在与文章基本名称同名的子目录中。例如,BobBuilder.aspx 位于 /KB/cs/,而所有其他文件都位于 /KB/cs/BobBuilder/。在撰写文章时,您可能希望在本地复制这种结构。

关注点

有几点需要强调

设计模式

我实现了 MVC 模式,但有所变通:我使用了 Observer 模式,视图订阅(Singleton)控制器作为发布者。当一个动作被触发时,一个命令通过普通的函数调用发送到控制器。控制器完成其工作,触发事件来与任何参与的视图进行通信。

Observer 的 .NET event 实现的一个很棒的特性是订阅者可以修改 EventArgs 派生参数,从而将信息传递回发布者。这在 CurrentDocument 属性的实现中得到了体现。

partial class Controller
{
   public static Document CurrentDocument
   {
      get
      {
         return Instance
            .ExecuteCore( null, new Command.GetCurrentDocument() )
            .Document;
      }
   }
}

Instance 获取 Singleton 实例,而 ExecuteCore 是一个返回其 Command 参数的成员方法。对于 GetCurrentDocument 命令,所有 ExecuteCore 所做的就是触发静态 Execute 事件。所有视图都订阅了这个事件,当当前活动的视图处理它时,它会用自己的(当前)文档填充命令的 Document 属性。因此,当 event 在调用其调用列表中的所有视图后返回时,Document 属性已经被当前视图设置,并返回给任何需要它的地方。

这种模式比让控制器维护一个视图接口集合更容易。现在所有这些都由内置的 event 处理来完成,同时减少了控制器和视图之间的耦合。

System.Windows.Forms.Keys

我找不到一种 .NET 方法来为给定的 char 确定该枚举的正确成员。最后,我写了这段代码片段。

[System.Runtime.InteropServices.DllImport( "user32.dll" )]
static extern short VkKeyScan( char ch );
   
static Keys ConvertToKeys( char c )
{
   short vk = VkKeyScan( c );
   int key = vk & 0x00FF;
   int mod = vk & 0xFF00;
   int iKeys = ( mod << 8 ) | key;
   Keys eKeys = ( Keys ) iKeys;
   return eKeys;
}

待办事项

这是一个可能进行增强的简短列表。如果您有任何意见或想法,请在下方留言。

  • 拼写检查器
  • 更多常用格式
  • 可配置的快捷键
  • 宏编译器
  • 记住工具条位置
  • 更好地处理异常

参考文献

历史

2008 年 2 月 1 日

首次发布

2008 年 2 月 1 日 移除了表情符号
2008 年 2 月 3 日 添加了目录的自动生成
2008 年 2 月 7 日 修复了目录的自动生成
2009 年 8 月 5 日 修复了模板中新 DOCTYPE 的预览放置问题
© . All rights reserved.