为Windows Live Writer开发插件——InsertSearchPageLink

两周前,我曾经发布了一个Windows Live Writer的小插件——InsertSearchPageLink,用来在Windows Live Writer中插入一个指向某个搜索引擎的某个搜索关键字页面的超链接(关于这个插件的功能介绍以及下载,请参考《为Windows Live Writer写了一个小插件——插入搜索页面链接》)。今天终于有空,把编写的过程写出来与大家分享,希望能起到抛砖引玉的作用,让朋友们都能编写出自己的插件,扩展Windows Live Writer的功能,方便大家!

 

Windows Live Writer扩展综述

目前为止,Windows Live Writer的扩展功能还不是很强,它提供给我们如下两个方面对其扩展的可能:

  1. 应用程序级别的API:这部分API让我们能够在外部程序中启动并调用到Windows Live Writer的功能,以COM组件的形式提供。如果你要编写一个Firefox工具条上的小按钮,例如“Blog It!”之类,那么显然应该使用这类API。
  2. 文章内容插件:这部分API允许开发者对正在书写的文章内容进行修饰,实现与Windows Live Writer中自带的“Insert Link...”、“Insert Picture...”等类似的功能。

若要编写文章内容插件,则需要从ContentSource或SmartContentSource两个基类中选择其一并继承自它。这两个基类提供了编写文章内容插件所需要的基础设施。ContentSource和SmartContentSource的区别如下:

  1. ContentSource:如果你需要编写的插件将要在内容中插入一段简单的,插入之后不再修改(所谓“单向插入”)的内容片断,例如一个超链接,或是自定义的一段版权信息等,那么应该选择该类型的基类。Windows Live Writer中自带的“Insert Link...”就属于这类插件。
  2. SmartContentSource:如果你需要编写的插件将在内容中插入一段较为复杂的,插入之后还可能要修改(所谓“双向交互”)的内容片杜阿,例如一张图片、一幅地图等,那么则应该选择这个类型的基类。Windows Live Writer中自带的“Insert Picture...”就属于这类插件。

对于继承于SmartContentSource基类的插件,在Windows Live Writer的编辑器中选择用该插件插入的内容,你将会在右边看到该内容的可设置属性。例如用“Insert Picture...”插入一幅图片之后,选中该图片,可以看到Windows Live Writer窗口的右边变成了如下的配置面板:

而对于继承于ContentSource基类的插件,一旦内容插入之后,将自动变成HTML形式,于其他的手工输入内容没有任何区别。

我们将要编写的InsertSearchPageLink,就是一个最简单的,继承于ContentSource基类的插件。

 

在Visual Studio中创建项目

打开Visual Studio,创建一个“Class Library”类型的项目。

然后在项目中添加WindowsLive.Writer.Api.dll程序集的引用(一般位于C:\Program Files\Windows Live Writer\文件夹中),以及相应的System.Drawing、System.Windows.Forms等引用。添加好之后Solution Explorer如下:

右键单击Class Library项目,选择“Properties”。在“Build Event”选项卡中的“Post Build Event command line”中写入如下命令,让每次编译完成之后自动将该插件拷贝到Windows Live Writer的插件目录下:

XCOPY /D /Y /R "$(TargetPath)" "C:\Program Files\Windows Live Writer\Plugins\"

 

继承于ContentSource基类

接下来,让我们在这个Class Library中新建一个类,并继承于WindowsLive.Writer.Api.ContentSource基类:

[WriterPlugin("CA5ACC8E-5007-4df8-B110-DD6420C4CD4F", "Search Page Link",
    PublisherUrl = "http://dflying.cnblogs.com",
    ImagePath = "Icon.bmp",
    Description = "Insert Search Page Link.")]
[InsertableContentSource("Search Page Link")]
public class InsertSearchPageLinkPlugin : ContentSource
{
    //......
}

注意我们为该类添加了WriterPlugin属性:

  1. 第一个参数为一个Guid,我们可以用Visual Studio自动生成,其标识的作用。
  2. 第二个参数为该插件的名称,将在Windows Live Writer的插件管理器中看到,如图:
  3. PublisherUrl为发布者的网站地址,这里就写了我的Blog地址。
  4. ImagePath为插件的图标文件路径,注意该图标应为18*16大小,且一定以Embedded Resource形式编译在程序集中。如下:
  5. Description为插件的一小段描述介绍。

该类还应用了InsertableContentSource属性,其中的参数表示“Insert”菜单和“Insert”快捷面板(在Windows Live Writer的的右下角)中该插件的名称。

 

覆写基类的CreateContent()方法

CreateContent()方法用来得到该插件所生成的一个HTML字符串,一旦用户点击了“Insert”菜单或“Insert”快捷面板中的“Insert XXX”链接,Windows Live Writer就将自动调用该方法,所以我们应该在该方法中弹出一个小窗口用来配置讲要插入的内容。

该方法的代码如下:

public override DialogResult CreateContent(IWin32Window dialogOwner, ref string newContent)
{
    using (InsertLinkForm insertLinkForm = new InsertLinkForm())
    {
        DialogResult result = insertLinkForm.ShowDialog();
        newContent = insertLinkForm.LinkHTMLString;
 
        return result;
    }
}

注意到CreateContent()方法的第二个参数为ref string newContent,这个ref string就表示由该插件生成的HTML代码。

该方法的实现也非常简单,仅仅是创建了一个InsertLinkForm,然后就将所有任务都交给了它。

 

编写InsertLinkForm

InsertLinkForm就是一个再普通不过的WinForm了,一个TextBox、一个ListBox、一个CheckBox和一对“OK”“Cancel”按钮。设计期界面如下:

切换到代码部分,在其构造函数中为该ListBox添加一系列的选项:

public InsertLinkForm()
{
    InitializeComponent();
 
    // whatever method you like to fill the list
    List<SearchEngineEntry> searchEngines = new List<SearchEngineEntry>();
    searchEngines.Add(new SearchEngineEntry("Google.com", "http://www.google.com/search?q={0}"));
    searchEngines.Add(new SearchEngineEntry("Google.cn", "http://www.google.cn/search?q={0}"));
    searchEngines.Add(new SearchEngineEntry("Baidu.com", "http://www.baidu.com/s?wd={0}"));
    searchEngines.Add(new SearchEngineEntry("Search.live.com", "http://search.live.com/results.aspx?q={0}"));
    searchEngines.Add(new SearchEngineEntry("Search.yahoo.com", "http://search.yahoo.com/search?p={0}"));
    searchEngines.Add(new SearchEngineEntry("Search.cn.yahoo.com", "http://search.cn.yahoo.com/search?p={0}"));
    searchEngines.Add(new SearchEngineEntry("Answers.com", "http://www.answers.com/main/ntquery?s={0}"));
 
    // bind to search engine list
    lbSearchEngines.DataSource = searchEngines;
    lbSearchEngines.DisplayMember = "DisplayText";
    lbSearchEngines.SelectedIndex = 0;
}

注意到这里用到了一个名为SearchEngineEntry的类,该类非常简单:

class SearchEngineEntry
{
private string m_displayText;
public string DisplayText
{
get { return m_displayText; }
set { m_displayText = value; }
}
private string m_baseUrl;
public string BaseUrl
{
get { return m_baseUrl; }
set { m_baseUrl = value; }
}
public SearchEngineEntry()
{
}
public SearchEngineEntry(string displayText, string baseUrl)
{
m_displayText = displayText;
m_baseUrl = baseUrl;
}
}

回到InsertLinkForm的代码中,为该类添加一个公有属性,用来表示该Form配置后生成的HTML字符串:

private string m_linkHTMLString;
public string LinkHTMLString
{
get { return m_linkHTMLString; }
set { m_linkHTMLString = value; }
}

然后是“OK”按钮的事件处理函数,只是简单地格式化并生成一段HTML,然后保留在m_linkHTMLString中而已:

private void btnOK_Click(object sender, EventArgs e)
{
// ensure there's input in keyword field
if (tbKeyword.Text == string.Empty)
{
epKeyword.SetError(tbKeyword, "Please input the Keyword.");
tbKeyword.Focus();
return;
}
// build result HTML link string
SearchEngineEntry selectedSearchEngine = lbSearchEngines.SelectedItem as SearchEngineEntry;
m_linkHTMLString = string.Format(
"<a href=\"{0}\" {1} title=\"Search '{2}' using {3}\" >{4}</a>",
string.Format(selectedSearchEngine.BaseUrl, tbKeyword.Text),
cbNewWindow.Checked ? "target=\"_blank\"" : string.Empty,
tbKeyword.Text,
selectedSearchEngine.DisplayText,
tbKeyword.Text
);
// result should be ok to close this dialog.
this.DialogResult = DialogResult.OK;
}

这样,当用户在InsertLinkForm中配置完成之后点击“OK”按钮,将执行上述事件处理函数,其中生成HTML字符串并保留在m_linkHTMLString中,然后该Form将被关闭。

之后该Form的调用者——CreateContent()方法将得到该InsertLinkForm的LinkHTMLString属性,并将其交给Windows Live Writer。以后的事情,自有Windows Live Writer为我们完成。搞定!

 

调试插件

编写程序不需要调试是不可思议的,哪怕这个最简单的小程序也不例外。可是,这个“插件”类型的程序应该如何调试呢?

记得在前面我们已经设置了项目的Post Build Event,每次编译成功之后将自动将编译结果拷贝到Windows Live Writer的插件目录中。这时若你启动Windows Live Writer,则可以看到该插件已经被顺利加载了进去,当然,前提是插件没有致命错误。

然后,我们可以在Visual Studio中点击Debug\Attach to Process,然后手工将Visual Studio的Debugger附加到这个Windows Live Writer的实例中。注意我们需要Attach to Managed Code:

这样在Visual Studio中的插件代码中加入断点,然后切换回Windows Live Writer,启动该插件,Visual Studio将顺利开始调试。

 

代码下载

下在前请先阅读Dflying版权说明。若您下载或使用该软件,表示您理解并接受该协议;若您不同意,请勿下载或使用。

  1. 本程序用到的InsertSearchPageLink源代码可以在此下载(62K):Dflying.LiveWriter.InsertSearchPageLinkPlugin-Source.zip
  2. 若您只是想使用该插件,请下载编译好的DLL(4K):Dflying.LiveWriter.InsertSearchPageLinkPlugin.zip。将其解压缩至Windows Live Writer的安装目录(默认为C:\Program Files\Windows Live Writer\Plugins)中。然后重新启动Windows Live Writer,即可在界面右下角看到这个插件。

 

相关资源

  1. Windows Live Writer的主页:http://windowslivewriter.spaces.live.com/
  2. Windows Live Writer的SDK:Windows Live Writer SDK
  3. Writer DevZone

 

(PS:我基本没用WinForm开发过什么东西,更是没有这方面的什么开发经验。其中代码如由不得体之处,还请各位不吝指出。谢谢!)

posted on 2006-12-03 16:32  Dflying Chen  阅读(6372)  评论(9编辑  收藏  举报