隨筆 - 117  文章 - 72  trackbacks - 0

          聲明:原創作品(標有[原]字樣)轉載時請注明出處,謝謝。

          常用鏈接

          常用設置
          常用軟件
          常用命令
           

          訂閱

          訂閱

          留言簿(7)

          隨筆分類(130)

          隨筆檔案(123)

          搜索

          •  

          積分與排名

          • 積分 - 155796
          • 排名 - 390

          最新評論

          [標題]: 開發自己的Windows Live Writer插件
          [時間]:2009-10-04
          [摘要]: 開發一個Windows Live Writer插件,在寫博客時,添加自己的代碼樣式。最終效果是,在Windows Live Writer中選中代碼,然后點擊插件,將代碼包含在<div class="mycode">your code</div>中。
          [關鍵字]: plugin、Windows Live Writer、code、format、highlight、 插件、博客、blog、msi、package、打包、C#、前綴、后綴、簡單代碼、樣式
          [環境]: Windows Live Writer 14.0.8089.726 zh-cn, Visual Studio 2008 , Windows XP SP3 , Wordpress 2.8.4
          [作者]:Winty  (wintys@gmail.com) http://www.aygfsteel.com/wintys

          [正文]:

                   開發一個Windows Live Writer插件,在寫博客時,添加自己的代碼樣式。最終效果是,在Windows Live Writer中選中代碼,然后點擊插件,將代碼包含在<div class="mycode">your code</div>中。當然要在最終發表的博客上添加.mycode 的CSS樣式才有效果。

                  .mycode樣式如下:

          .mycode {
              margin: 10px;
              padding: 10px;
              background: #DDEDFB;
              border: 1px solid #428EDE; 
              text-align: left;
              /*width:500px;*/
              overflow-x:auto;
              font-size:20px;
              white-space:nowrap;
              *white-space: normal;
              WORD-WRAP: break-word;/*IE*/
              word-break:break-all;/*IE*/
          }
          選中代碼,點擊"WintyCodeArea":
          image 
           
          效果如下圖
          (在Writer需啟用"使用主題編輯",并已從博客中獲取主題,才能立即看到效果):
          image 
           

          0、準備工作

          • 在Visual Studio 2008中新建C#"Class Library"項目
          • 在項目中添加References:"C:\Program Files\Windows Live\Writer\WindowsLive.Writer.Api.dll"
          • 在項目屬性的"Build Events"=>"Post Build Event command line"添加:(XCOPY /D /Y /R "$(TargetPath)" "C:\Program Files\Windows Live\Writer\Plugins")

           

          1、"Class Library"主類,繼承于ContentSource

          WintyCodeArea.cs:

          using System.Windows.Forms;
          using WindowsLive.Writer.Api;

          /*
          2009-10-02

          Winty

          wintys@gmail.com

          http://www.aygfsteel.com/wintys
            */
          namespace MyWindowsLiveWriterPlugin
          {
              /*Plugin 主類*/
              [WriterPlugin("{7DFB5431-D7DA-4e61-9E4B-056D30DFDB63}",
                  "WintyCodeArea",
                  PublisherUrl = "http://www.aygfsteel.com/wintys",
                  ImagePath = "image.jpg",
                  HasEditableOptions = true,
                  Description = "Insert <div class=\"mycode\">your code</div>\nhttp://www.aygfsteel.com/wintys\nwintys@gmail.com")]
              [InsertableContentSource("WintyCodeArea")]
              public class WintyCodeArea : ContentSource
              {
                  WintyCodeAreaSettings m_settings;

                  public override void Initialize(IProperties pluginOptions)
                  {
                      base.Initialize(pluginOptions);
                      m_settings = new WintyCodeAreaSettings(pluginOptions);
                  }
                  public override DialogResult CreateContent(IWin32Window dialogOwner, ref string content)
                  {
                      string originalContent = content;

                      content = m_settings.FrontCode;
                      if(m_settings.EscapeCode)
                          content +=  System.Web.HttpUtility.HtmlEncode(originalContent);
                      else
                          content += originalContent;
                      content += m_settings.BackCode;

                      return DialogResult.OK;
                  }

                  public override void EditOptions(IWin32Window dialogOwner)
                  {
                      SettingForm settingForm = new SettingForm(m_settings);
                      settingForm.ShowDialog(dialogOwner);
                  }
              }
          }

           

                   Initialize()、EditOptions()并不是必須的,這里因為用到了"設置選項"窗口,才需要。

          CreateContent(IWin32Window dialogOwner, ref string content)在此為必須,content傳入值為Live Writer當前被選中的高亮區的HTML代碼,無論在編輯還是在源代碼視圖中都是這樣的。content的傳出值為你修改后的HTML代碼,最終將在Live Writer中顯示的。

                  在CreateContent()中也可以彈出窗體,此處并未用到。以下是代碼示例:

          public override DialogResult CreateContent(IWin32Window dialogOwner, ref string content)
          {
              using (InsertCodeForm insertCodeForm = new InsertCodeForm())
              {
                  DialogResult result = insertCodeForm.ShowDialog();
                  content = insertCodeForm.MyCode;
                  return result;
              }
          }

                  相應的InsertCodeForm類的部分代碼如下:

          public partial class InsertCodeForm : Form
          {
              private string m_MyCode;
              public string MyCode
              {
                  get { return m_MyCode; }
                  set { m_MyCode = value; }
              }

              public InsertCodeForm()
              {
                  InitializeComponent();
              }

              private void buttonInsert_Click(object sender, EventArgs e)
              {
                  if (textBoxCode.Text == string.Empty)
                  {
                      return;
                  }

                  m_MyCode = "<div class=\"mycode\">";
                  m_MyCode += System.Web.HttpUtility.HtmlEncode(textBoxCode.Text);
                  m_MyCode += "</div>";           

                  this.DialogResult = DialogResult.OK;
              }
          }


           

          2、用于設置WintyCodeArea插件行為的類

          WintyCodeAreaSettings.cs:

          using WindowsLive.Writer.Api;

          namespace MyWindowsLiveWriterPlugin
          {
              class WintyCodeAreaSettings
              {
                  IProperties m_properties;

                  private const string FRONT_CODE = "FRONT_CODE";//前綴代碼
                  private const string BACK_CODE = "BACK_CODE";//后綴代碼
                  private const string ESCAPE_CODE = "ESCAPE_CODE";//是否轉義代碼

                  public const string DEFAULT_FRONT_CODE = "<div class=\"mycode\">";
                  public const string DEFAULT_BACK_CODE = "</div>";
                  public const bool   DEFAULT_ESCAPE_CODE = false;

                  public WintyCodeAreaSettings(IProperties properties)
                  {
                      m_properties = properties;
                  }

                  public string FrontCode
                  {
                      get
                      {
                          return m_properties.GetString(FRONT_CODE, DEFAULT_FRONT_CODE);
                      }
                      set
                      {
                          m_properties.SetString(FRONT_CODE, value);
                      }
                  }

                  public string BackCode
                  {
                      get
                      {
                          return m_properties.GetString(BACK_CODE, DEFAULT_BACK_CODE);
                      }
                      set
                      {
                          m_properties.SetString(BACK_CODE, value);
                      }
                  }

                  public bool EscapeCode
                  {
                      get
                      {
                          return m_properties.GetBoolean(ESCAPE_CODE, DEFAULT_ESCAPE_CODE);
                      }
                      set
                      {
                          m_properties.SetBoolean(ESCAPE_CODE, value);
                      }
                  }

              }
          }

           

          3、"設置窗口"的代碼

                  點擊"工具=>選項"就可以找到這個設置窗口。

          image

                  WintyCodeArea的設置窗口:

          image

                  所謂的轉義原始內容,就是將所選內容中的特殊HTML字符進行編碼(空格與換行不變)。

           

          SettingForm.cs:

          using System;
          using System.Windows.Forms;

          namespace MyWindowsLiveWriterPlugin
          {
              partial class SettingForm : Form
              {
                  WintyCodeAreaSettings m_settings;

                  public SettingForm(WintyCodeAreaSettings settings)
                  {
                      InitializeComponent();
                      //Winty's initialization
                      m_settings = settings;
                      txtFrontCode.Text = m_settings.FrontCode;
                      chkEscapeCode.Checked = m_settings.EscapeCode;
                      textBackCode.Text = m_settings.BackCode;
                  }

                  /*保存設置*/
                  private void btnOK_Click(object sender, EventArgs e)
                  {
                      m_settings.FrontCode = txtFrontCode.Text;
                      m_settings.EscapeCode = chkEscapeCode.Checked;
                      m_settings.BackCode = textBackCode.Text;

                      Close();
                  }

                  /*恢復默認設置*/
                  private void btnRestoreDefault_Click(object sender, EventArgs e)
                  {
                      m_settings.FrontCode = WintyCodeAreaSettings.DEFAULT_FRONT_CODE;
                      m_settings.EscapeCode = WintyCodeAreaSettings.DEFAULT_ESCAPE_CODE;
                      m_settings.BackCode = WintyCodeAreaSettings.DEFAULT_BACK_CODE;

                      txtFrontCode.Text = m_settings.FrontCode;
                      chkEscapeCode.Checked = m_settings.EscapeCode;
                      textBackCode.Text = m_settings.BackCode;
                  }
              }
          }

           

          SettingForm.Designer.cs(這是Visual Studio根據設計的窗體生成的代碼):

          namespace MyWindowsLiveWriterPlugin
          {
              partial class SettingForm
              {
                  /// <summary>
                  /// Required designer variable.
                  /// </summary>
                  private System.ComponentModel.IContainer components = null;

                  /// <summary>
                  /// Clean up any resources being used.
                  /// </summary>
                  /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
                  protected override void Dispose(bool disposing)
                  {
                      if (disposing && (components != null))
                      {
                          components.Dispose();
                      }
                      base.Dispose(disposing);
                  }

                  #region Windows Form Designer generated code

                  /// <summary>
                  /// Required method for Designer support - do not modify
                  /// the contents of this method with the code editor.
                  /// </summary>
                  private void InitializeComponent()
                  {
                      this.btnOK = new System.Windows.Forms.Button();
                      this.chkEscapeCode = new System.Windows.Forms.CheckBox();
                      this.labelFont = new System.Windows.Forms.Label();
                      this.labelBack = new System.Windows.Forms.Label();
                      this.txtFrontCode = new System.Windows.Forms.TextBox();
                      this.textBackCode = new System.Windows.Forms.TextBox();
                      this.btnRestoreDefault = new System.Windows.Forms.Button();
                      this.SuspendLayout();
                      //
                      // btnOK
                      //
                      this.btnOK.Location = new System.Drawing.Point(222, 211);
                      this.btnOK.Name = "btnOK";
                      this.btnOK.Size = new System.Drawing.Size(113, 29);
                      this.btnOK.TabIndex = 0;
                      this.btnOK.Text = "設置";
                      this.btnOK.UseVisualStyleBackColor = true;
                      this.btnOK.Click += new System.EventHandler(this.btnOK_Click);
                      //
                      // chkEscapeCode
                      //
                      this.chkEscapeCode.AutoSize = true;
                      this.chkEscapeCode.Location = new System.Drawing.Point(127, 94);
                      this.chkEscapeCode.Name = "chkEscapeCode";
                      this.chkEscapeCode.Size = new System.Drawing.Size(96, 16);
                      this.chkEscapeCode.TabIndex = 1;
                      this.chkEscapeCode.Text = "轉義原始內容";
                      this.chkEscapeCode.UseVisualStyleBackColor = true;
                      //
                      // labelFont
                      //
                      this.labelFont.AutoSize = true;
                      this.labelFont.Location = new System.Drawing.Point(48, 12);
                      this.labelFont.Name = "labelFont";
                      this.labelFont.Size = new System.Drawing.Size(53, 12);
                      this.labelFont.TabIndex = 2;
                      this.labelFont.Text = "前綴代碼";
                      //
                      // labelBack
                      //
                      this.labelBack.AutoSize = true;
                      this.labelBack.Location = new System.Drawing.Point(48, 125);
                      this.labelBack.Name = "labelBack";
                      this.labelBack.Size = new System.Drawing.Size(53, 12);
                      this.labelBack.TabIndex = 4;
                      this.labelBack.Text = "后綴代碼";
                      //
                      // txtFrontCode
                      //
                      this.txtFrontCode.Location = new System.Drawing.Point(125, 12);
                      this.txtFrontCode.Multiline = true;
                      this.txtFrontCode.Name = "txtFrontCode";
                      this.txtFrontCode.Size = new System.Drawing.Size(247, 64);
                      this.txtFrontCode.TabIndex = 5;
                      //
                      // textBackCode
                      //
                      this.textBackCode.Location = new System.Drawing.Point(125, 125);
                      this.textBackCode.Multiline = true;
                      this.textBackCode.Name = "textBackCode";
                      this.textBackCode.Size = new System.Drawing.Size(247, 64);
                      this.textBackCode.TabIndex = 6;
                      //
                      // btnRestoreDefault
                      //
                      this.btnRestoreDefault.Location = new System.Drawing.Point(88, 211);
                      this.btnRestoreDefault.Name = "btnRestoreDefault";
                      this.btnRestoreDefault.Size = new System.Drawing.Size(106, 29);
                      this.btnRestoreDefault.TabIndex = 7;
                      this.btnRestoreDefault.Text = "恢復默認設置";
                      this.btnRestoreDefault.UseVisualStyleBackColor = true;
                      this.btnRestoreDefault.Click += new System.EventHandler(this.btnRestoreDefault_Click);
                      //
                      // SettingForm
                      //
                      this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
                      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
                      this.ClientSize = new System.Drawing.Size(420, 252);
                      this.Controls.Add(this.btnRestoreDefault);
                      this.Controls.Add(this.textBackCode);
                      this.Controls.Add(this.txtFrontCode);
                      this.Controls.Add(this.labelBack);
                      this.Controls.Add(this.labelFont);
                      this.Controls.Add(this.chkEscapeCode);
                      this.Controls.Add(this.btnOK);
                      this.Name = "SettingForm";
                      this.Text = "WintyCodeArea Settings";
                      this.ResumeLayout(false);
                      this.PerformLayout();

                  }

                  #endregion

                  private System.Windows.Forms.Button btnOK;
                  private System.Windows.Forms.CheckBox chkEscapeCode;
                  private System.Windows.Forms.Label labelFont;
                  private System.Windows.Forms.Label labelBack;
                  private System.Windows.Forms.TextBox txtFrontCode;
                  private System.Windows.Forms.TextBox textBackCode;
                  private System.Windows.Forms.Button btnRestoreDefault;
              }
          }

           

          4、總結

                  工程最終生成WintyCodeArea.dll,將其復制到"C:\Program Files\Windows Live\Writer\Plugins"目錄,啟動Windows Live Writer就可以使用這個插件了。或將其做成WintyCodeAreaWLWPluginSetup.msi(見附件),點安裝即可(msi制作方法參考[11])。

                 此插件主要供自己使用,其他人可能不會想要我的這種效果,所以暫命名WintyCodeArea。但是除了添加<div class="mycode">your code</div>外,還可以進行代碼轉義設置,并且前后綴代碼都可以自定義,根據需要自己添加前綴后綴代碼就行了,所以,希望對別人有點用處。

           

          補充:

                如果插件需要訪問剪貼板,可參考如下代碼:

          //System.Windows.Forms.Clipboard

          IDataObject iData = Clipboard.GetDataObject();
          if (iData.GetDataPresent(DataFormats.Text))
          {
              str = (String)iData.GetData(DataFormats.Text);
              ......
          }

           

          [參考資料]:

          [1]*《Developing Plugins for Windows Live Writer 》 : http://www.devx.com/codemag/Article/38214/1954

          [2]*《為Windows Live Writer開發插件——InsertSearchPageLink》 : http://www.cnblogs.com/dflying/archive/2006/12/03/580602.html

          [3]*《Writing a simple Windows Live Writer plugin》 : http://blog.boyet.com/blog/blog/writing-a-simple-windows-live-writer-plugin/

          [4] 《The New Live Writer SDK》: http://www.liveside.net/developer/archive/2008/06/03/the-new-live-writer-sdk.aspx

          [5] 《Writing Plugins For Windows Live Writer - Working With Forms》  : http://www.liveside.net/developer/archive/2006/10/19/Writing-Plugins-For-Windows-Live-Writer-_2D00_-Working-With-Forms.aspx

          [6] 《Writing Plugins For Windows Live Writer - Using PluginHttpRequest Instead of HttpWebRequest》 : http://www.liveside.net/developer/archive/2007/10/20/writing-plugins-for-windows-live-writer-using-pluginhttprequest-instead-of-httpwebrequest.aspx

          [7] 《Windows Live Writer Plugin - Properties Panel》 : http://blog.benhall.me.uk/2007/09/windows-live-writer-plugin-properties.html

          [8] 《Windows Live Writer Plugin - Display a form / OpenFileDialog》 :  http://blog.benhall.me.uk/2007/09/windows-live-writer-plugin-display-form.html

          [9] LiveSide Source Code : http://cid-fabdddc5cad93494.skydrive.live.com/self.aspx/LiveSide%20-%20Public/SourceCode/MyNewPlugin%20-%20Adding%20An%20Icon.zip?wa=wsignin1.0&sa=732043521

          [10] 《Windows Live Writer Plugin - Hello World!》 : http://blog.benhall.me.uk/2007/09/windows-live-writer-plugin-hello-world.html

          [11]*《Windows Live Writer Plugin - Installation》 : http://blog.benhall.me.uk/2007/10/windows-live-writer-plugin-installation.html

          [12] MSDN Windows Live Writer SDK : http://msdn.microsoft.com/en-us/library/aa738906.aspx

          [13] Windows Live Writer Blog : http://www.live-writer.net/

          [14] Windows Live Gallery : http://gallery.live.com/results.aspx?bt=9&pl=8


          [附件]:

          [1] WintyCodeAreaProject.zip(Visual Studio工程) : WintyCodeAreaProject.zip

          [2] WintyCodeAreaWLWPluginSetup.zip(WintyCodeArea插件安裝程序,msi格式) : http://www.aygfsteel.com/Files/wintys/WintyCodeAreaWLWPluginSetup.zip

          原創作品,轉載請注明出處。
          作者:Winty (wintys@gmail.com)
          博客:http://www.aygfsteel.com/wintys

           

          posted on 2009-10-05 19:26 天堂露珠 閱讀(2687) 評論(1)  編輯  收藏 所屬分類: .NET

          FeedBack:
          # re: [原]開發自己的Windows Live Writer插件 2013-04-02 10:03 天堂露珠
          引用1:《修改LiveWriter插件WintyCodeArea,生成google-code-prettify適用的代碼塊》: http://freewind.me/blog/20130101/1367.html
          上述引用修改后的代碼已由freewind上傳到Github: https://github.com/freewind/WintyCodeArea

          引用2:Windows Live Writer的code插件: http://tooktang.blogcn.com/2011/09/19/windows-live-writer%E7%9A%84code%E6%8F%92%E4%BB%B6/  回復  更多評論
            

          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 比如县| 贵州省| 个旧市| 灵川县| 金沙县| 斗六市| 积石山| 邢台县| 乳源| 朝阳市| 彭水| 延长县| 南溪县| 七台河市| 广饶县| 中西区| 资阳市| 西充县| 张家港市| 泸水县| 瑞金市| 长治市| 正阳县| 怀来县| 龙口市| 阿坝县| 孟村| 灵石县| 虹口区| 莱州市| 宜城市| 黄大仙区| 武安市| 政和县| 邵阳市| 榕江县| 丰都县| 怀远县| 光山县| 齐齐哈尔市| 贵溪市|