Developing Plugins for Windows Live Writer

download Developing Plugins for Windows Live Writer

of 23

Transcript of Developing Plugins for Windows Live Writer

  • 8/14/2019 Developing Plugins for Windows Live Writer

    1/23

    Developing Plugins forWindows Live Writer

    Plugins for Windows Live Writer are simple to create and canprovide many extra features.

    This article will show you how to start writing plugins for

    Windows Live Writer, including how to get started, how todebug, and how to package the final plugin.

    Before you can begin writing a plugin for Windows

    Live Writer (http://writer.live.com/), you need tounderstand what it is and what it actually does.

    Windows Live Writer is a free desktop blog authoringtool from Microsoft that allows you to write an entry

    for your blog without having to be online and do itright from your desktop. Live Writer doesnt just

    support Microsofts own blogging site (Windows LiveSpaces), it supports a multitude of different blog

    engines: basically any that support the MetaWeblogAPI or Atom Publishing Protocol. This list includes

    Wordpress, Community Server, LiveJournal, andBlogger. You can write your blog entry in the style of

    your own blog as well because Live Writer downloadsyour blog style and uses it as a template.

    Whether youre someone just starting out with their

    first blog, or a seasoned pro, Windows Live Writermakes the blogging experience that much better.

    And the features that dont come with the program

    can come in the form of plugins that add extraextensibility and improve the blogging experience

    even more.

    Your DevelopmentEnvironment Pre-requisites

    Live Writer plugins are written in .NET, but while youcan use .NET 1.1, it is recommended to use .NET

    2.0. You will need Visual Studio 2005 or aboveinstalledthis can be any version of Visual Studio

    2005 or 2008 (http://msdn.microsoft.com/vstudio),including the free Express Editions of Visual Studio

    (http://www.microsoft.com/express/). You will alsoneed to download Windows Live Writer

    (http://writer.live.com/) as this has the required APIDLL on which the plugins are based.

    As plugins are developed in .NET, you can use any

    language that uses it, but for my examples, I will beusing C#.

  • 8/14/2019 Developing Plugins for Windows Live Writer

    2/23

    Writing Your Plugin

    Open up Visual Studio and create a new Class

    Library project, giving it a meaningful name for your

    plugin. Rename the default class1.cs to plugin.cs(this isnt essential, but will allow you to quickly see

    the main plugin class).

    Next you need to add the Windows Live Writer APIreference: bring up the Add Reference window, pointto your Windows Live Writer install folder (typically

    C:\Program Files\Windows Live\Writer\), and thenselect WindowsLive.Writer.API.dll. As a best practice

    for this reference, set the property of Copy Local tobe false for this reference (this will stop older

    versions of the API DLL being copied into the LiveWriter Plugins folder). Open plugin.cs and include the

    following using statement:

    using WindowsLive.Writer.Api;

    You also need to add a reference to the WindowsForms namespace, so add System.Windows.Forms

    as a reference and also include the following:

    using System.Windows.Forms;

    Now you can add the Plugins attributes: these tell

    Live Writer about who made the plugin, the link tothe developers Web site, the description, whether

    the plugin has options, and the location of the image

    to be used as the plugins icon within the Live WriterUI. These details go in just after the namespace

    (before the main class).

    The code for this is as follows:

    [WriterPlugin("d39bba2b-9522-49b1-8731-61030ccd6c95", "My First Plugin",

    Description = "This is my first plugin",HasEditableOptions = false,Name = "My First Plugin",PublisherUrl = "http://www.liveside.net")]

    [InsertableContentSource ("Bold Text")]

    Please note: The GUID is unique for each plugin and

    you shouldnt reuse it in other plugins as this cancause problems for Writer and may cause your

    plugin not to be loaded.

    To add an icon for your plugin, you should includethe code:

    ImagePath = "icon.gif",

    The value of this attribute must be the file name ofthe icon you wish to use. Its location is relative to

  • 8/14/2019 Developing Plugins for Windows Live Writer

    3/23

    where it is stored in your project. The image itselfmust be 20 x 18 pixels in size.

    After this, you need to create your plugin class. The

    plugin class has to inherit from the Live Writer APIand there are two choices to inherit from:

    ContentSource and SmartContentSource.ContentSource plugins are very basic plugins and will

    only insert text into the blog entry. The plugin

    cannot change that text again. SmartContentSourceplugins can do a lot more and will be covered lateron in the article. For this example, I am going to

    inherit just from the ContentSource interface:

    public class LiveWriterExamplePlugin:ContentSource

    Then you need to include how the plugin will insertthe text. There are three different types:

    CreateContent(from the Insert menu).

    CreateContentFromUrl(when pasting a URL into the blog entry area or from a Blog This

    action).

    CreateContentFromLiveClipboard(using the LiveClipboard, although this method isnt widely

    used as there isnt much LiveClipboard content out there due to documentation).

    CreateContent is the most commonly used method,although there are examples where the FromUrl

    method has been used. The plugin code overrides allof these methods and they are not mutually

    exclusive; you can have more than one type in aplugin.

    Override CreateContent Method

    You can see that there is a string reference of

    content. There are two things of note about thisreference:

    1. The initial value of content is whatever may have been highlighted in the editing window. If

    no text was highlighted, then content will be empty, if you had text highlighted, then the

    full HTML code will be what content equals.2. Whatever content is equal to, that is what will be put back into the blog entry. This must

    include any HTML formatting that might be required for the plugins functionality.

    Remove the base code that is put in, this is just a

    placeholder. To start off with, for this first example,just return DialogResult.OK. This first part will justbe a simple plugin to make the highlighted text bold,

    so the code for the CreateContent method is simply:

    publicoverrideDialogResult CreateContent(IWin32Window dialogOwner,refstring content)

    { if (!string.IsNullOrEmpty(content))

    content = string.Format("{0}",content);

    returnDialogResult.OK;

  • 8/14/2019 Developing Plugins for Windows Live Writer

    4/23

    }

    Using this code, the plugin will take in whatever textwas highlighted and the bold HTML tags to either end

    of that content. Listing 1 shows just how simple thecode can be for a Live Writer plugin.

    Compiling and Debugging

    There are several little tricks to know about

    compiling and debugging your plugins for Live Writeras they are DLL files and so cant be run on their

    own. The two main tricks are for copying the built

    DLL to Live Writers plugin directory and how to startLive Writer so that you can debug your plugin.

    Figure 1 shows the command needed for copying

    the built plugin to the Live Writer plugin directory,the command being:

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

    Note: If your Program Files folder is in a differentlocation to the Windows default, you will need to

    change this for the way in which your system isconfigured.

    Alternatively, you can simply set the output folder of

    the project to point to your Live Writer Plugins

    folder.

    Figure 2 shows you the setting needed to be able to

    debug your plugin. You must start Windows LiveWriter as an external application in order to debug

    your plugin. This will only work if you have donewhat is in Figure 1, otherwise the plugin wont have

    been copied to the plugin directory and Writer wontpick it up.

    Once you have these two settings configured in

    Visual Studio, you can press F5 as you wouldnormally, which will then build your project, copy it

    to the plugin directory, and then load Windows LiveWriter with your plugin in debug mode.

    Now you are in debug mode, Figure 3, Figure 4,

    and Figure 5 will show the stages of using theplugin. In Figure 3 you have your text as it was

    typed, in normal font style. In Figure 4 you see thetext is highlighted so that the plugin will pick up that

    text and use it. Figure 5 shows the results ofclicking the plugin name from the Insert section of

    Writer.

  • 8/14/2019 Developing Plugins for Windows Live Writer

    5/23

    Using Forms

    Windows Forms can be an integral part of your

    plugin, so its important to know how to call themcorrectly from your plugin code. Forms can control

    exactly what you want the user to put into their blogentry. This can range from putting in video URLs,

    selecting an emoticon from a range of differentemoticons, or even searching for a book from

    Amazon; you can use Forms in a multitude ofdifferent ways.

    You call the Form from within the CreateContent

    method like so:

    publicoverrideDialogResult CreateContent(IWin32Window dialogOwner,refstring content)

    { using (frmMain form = newfrmMain())

    { DialogResult result = form.ShowDialog();

    if (result == DialogResult.OK)content = form.NewContent;

    return result;}

    }

    In this snippet of code I have a simple Form with aproperty called NewContent, which will give me the

    new content value I want to have inserted into theblog entry. Usually the final code to be put in the

    plugin will be a property of the Form.

    Its important to note that in the code for yourAccept button in your Form, you have to put

    this.DialogResult = DialogResult.OK; so that whenthe Form closes the If condition checking for that

    result is actually met.

    Using Settings

    Settings, like Forms, can be an integral part of your

    plugin if you would like the user to be able to setdefaults for the plugin. Typically this would be done

    by the user going to the Options area of Live Writer,selecting the plugin, and then choosing the Options

    button as shown in Figure 6.

    To start with, Live Writer has to be told that yourplugin has an options Form, which is done by making

    sure you set HasEditableOptions=true in the PluginAttributes. Next you have to create a Settings class,

    as this makes it easier to access the settings.

    The Settings class also has to useWindowsLive.Writer.Api, as you need to pass it an

  • 8/14/2019 Developing Plugins for Windows Live Writer

    6/23

  • 8/14/2019 Developing Plugins for Windows Live Writer

    7/23

    class, which you then pass to the PluginSettingsclass that you created so you can read/write to

    them.

    Now you have that done, you need to create yourOptions Form. For this example, I created a Form

    that looks like Figure 7. You will need to pass thePluginSettings object to the Form itself:

    PluginSettings m_settings;public frmOptions(PluginSettings settings){

    InitializeComponent();m_settings = settings;

    // This sets the check box to be// whatever the default option waschBoldOption.Checked =

    m_settings.DefaultBoldOption;}

    The Save button will have the following action for itsClick event:

    privatevoid btnSave_Click(object sender, EventArgs e)

    { // Sets the option to whatever // the check box is currently at

    m_settings.DefaultBoldOption =chBoldOption.Checked;

    this.Close();}

    This example only has one setting, but the principle

    is the same for however many settings your pluginhas.

    Back to the original plugin class, you now need to

    override the EditOptions method to call your OptionsForm:

    public override void EditOptions(IWin32Window dialogOwner)

    { PluginSettings settings =

    new PluginSettings(this.Options); frmOptions op =

    new frmOptions(settings);op.ShowDialog();

    }

    All thats left to do now is apply that setting to what

    the plugin actually does, so in the CreateContentcode, you need to change it to the following:

    using (frmMain form = newfrmMain()){ DialogResult result = form.ShowDialog(); if (result == DialogResult.OK)

    {content = form.NewContent;

  • 8/14/2019 Developing Plugins for Windows Live Writer

    8/23

    if (m_defaultsettings.DefaultBoldOption){

    content = string.Format("{0}",content);

    }}

    return result;}

    SmartContentSource Plugins

    SmartContentSource plugins have a lot more aboutthem than basic ContentSource plugins. The biggest

    difference about the two types is that ContentSourceplugins insert HTML code into the blog entry and this

    cannot be changed or edited using the plugin at alater time. SmartContentSource plugins store as

    much information about what code its inserted asthe developer wants it to, which allows the user to

    open that blog entry in Writer at a later time and editthat bit of their blog entry using the plugin without

    having to go through the whole process again.

    Planning Whats Needed

    With SmartContentSource plugins, its often best to

    plan out what you want internally for your plugin,like settings and which bits of the content you would

    like the end user to be able to edit if required.Knowing what parts you want them to edit at a later

    date will help you determine what settings you needfor the plugin. These settings are held within the

    IProperties property of the ISmartContent object,which gets passed to the plugin from Live Writer.

    You will also want to work out where you would like

    the end user to edit the content, whether its a Formsimilar to the original Form they used or its done

    from the sidebar of Writer.

    Listing 2 shows the code used in the exampleplugins PluginSettings class.

    To write a SmartContentSource plugin, you must

    inherit from SmartContentSource, rather thanContentSource:

    publicclassHiddenText : SmartContentSource

    Override CreateContent Method

    Like ContentSource plugins, you need to override theCreateContent method, but this time its slightly

    different:

  • 8/14/2019 Developing Plugins for Windows Live Writer

    9/23

    publicoverrideDialogResult CreateContent(IWin32Window dialogOwner,ISmartContent newContent)

    { PluginSettings settings =

    newPluginSettings(newContent.Properties); using (frmMain main = newfrmMain(settings))

    { DialogResult result = main.ShowDialog(); return result;

    }}

    This time, Writer does not pass you a string

    reference, which means whatever is highlighted inthe editor gets ignored. Instead youre given an

    ISmartContent object. ISmartContent objectscontain everything about an instance of a plugins

    usage, which includes an IProperties property (asused when including settings). However, those

    properties are for that ISmartContent object andonly that objectthey are not global like you saw

    before.

    From the code snippet, you can see that I havecreated a PluginSettings class, which takes in the

    IProperties property of the ISmartContent object;this then gets passed to the Form, which makes it

    easier for the Form to write the required settings tothe PluginSettings class.

    GeneratePublishHTML Method

    In the main plugin class, there are three new

    methods that you can override: two of these are

    compulsory, the third is optional. The first of these isthe GeneratePublishHTML method, which is the

    method where the HTML is what will be published toyour actual blog. This method is compulsory; you

    have to have it there. This code snippet is a verysmall example of what is required:

    publicoverridestring GeneratePublishHtml(ISmartContent content,IPublishingContext publishingContext)

    { PluginSettings settings =

    newPluginSettings(content.Properties); return settings.FinalText;}

    In this snippet, the text that would actually bepublished comes from a setting that you would have

    written to using the CreateContent method.

    The IPublishingContext object that gets passed holdsinformation about the type of blog youre writing to,

    which includes a GUID for the individual blog (thiscomes from Live Writer itself) and the Service Name,

  • 8/14/2019 Developing Plugins for Windows Live Writer

    10/23

    which is whatever the current publishing service is(e.g., "Windows Live Spaces", "LiveJournal",

    "WordPress.com", etc.).

    CreateEditor Method

    This is the second compulsory method that you need

    to override. This method creates the sidebar thatappears in Live Writer when a SmartContentSource

    object is selected in the Live Writer editor:

    publicoverrideSmartContentEditor CreateEditor(ISmartContentEditorSite editorSite)

    { returnnewContextEditor();}

    This method is usually just as simple as that. TheContextEditor class that I call in this snippet will be

    explained later in the article.

    GenerateEditorHTML

    Sometimes in a plugin, what you want to display inthe blog entry isnt always something that you want

    to appear in the editor of Live Writer, JavaScript

    functions for example. So sometimes you might needto have something else appear in the actual Live

    Writer editing area. For this you need to override theGenerateEditorHTML method:

    publicoverridestring GenerateEditorHtml

    (ISmartContent content,IPublishingContext publishingContext)

    { PluginSettings settings =

    newPluginSettings(content.Properties); return settings.PlaceHolder;}

    As you can see, you get passed the same objects asthe GeneratePublishHTML method, so you can use

    the same information for putting your HTML codeinto the editor.

    This method is the optional method; your plugindoes not require it. If this isnt overridden, LiveWriter will simply use what is in the

    GeneratePublishHTML method.

    Listing 3 shows the full code for the exampleplugins main class.

    Using Forms

  • 8/14/2019 Developing Plugins for Windows Live Writer

    11/23

    Using Forms is mostly the same as when doing abasic ContentSource plugin, the main difference

    being that instead of creating the final HTML andpassing that back, you just save the settings into the

    PluginSettings class, which will then be used in alater method in the plugins main class.

    Listing 4 shows the full code for the main Form

    used in this example plugin.

    The Sidebar (ContextEditor)

    When you select a SmartContentSource within theLive Writer editor, the editor activates a sidebar on

    the right-hand side of the Live Writer window, as

    shown in Figure 8.

    For this, you need to create a new User Control toyour plugin project. I call mine ContextEditor. Now,

    rather than inherit the UserControl interface, it needs

    to inherit from the SmartContentEditor interface(make sure youre using WindowsLive.Writer.API):

    public partial class ContextEditor :SmartContentEditor

    The constructor for the editor has to be like the

    following or your plugin could end up with somestrange behavior:

    PluginSettings m_settings;ISmartContent m_content;public ContextEditor()

    {InitializeComponent();

    this.SelectedContentChanged +=newEventHandler(

    SelectedContentNowChanged);}

    Notice the EventHandler you have had to listen out

    for. This is important as this is what detects that youhave selected a different instance of a

    SmartContentSource object (dont forget, your usercould have used your plugin to insert two separate

    objects in their blog entry).

    The code for the EventHandler method is alsoimportant to get right:

    void SelectedContentNowChanged(object sender, EventArgs e)

    {m_content = SelectedContent;m_settings =

    newPluginSettings(m_content.Properties);textBox1.Text = m_settings.PlaceHolder;textBox2.Text = m_settings.FinalText;

    }

  • 8/14/2019 Developing Plugins for Windows Live Writer

    12/23

    Important: You must not use

    SelectedContent.Properties if you wish to get theIProperties property of the ISmartContentthis will

    not work. This is why I assign SelectedContent to alocal variable, and then use that local variable when

    passing the IProperties object to the PluginSettingsclass.

    As a best practice, you should also use thisEventHandler method to either set the currentsettings to what you have in your sidebar or call the

    method that applies these settings.

    If the user makes a change to the content using the

    sidebar, nothing will change in the editor until youcall the OnContentEdited() method. You can call this

    from a single button after all changes or each time

    anything is changed; it is up to you as the developerto decide when to update the editor.

    Listing 5 shows you the code needed for the sample

    plugins ContextEditor.

    Much Much More

    If you look through the Live Writer APIs, you will find

    so much more that you can do with your plugins,including an excellent screen-scraping method that

    will take a screenshot of a given URL and return animage. I would highly recommend taking a good look

    at the rest of the API documentation on MSDN(http://msdn2.microsoft.com/en-

    us/library/aa738852.aspx).

    Sctt Lovegrove

    [email protected]

    http://scottisafooldev.spaces.live.com

    Sctt is a Windows Live MVP for

    Microsoft and is very heavilyinvolved with Windows Live, not

    just with Windows Live Writer. He

    is one of the main writers forLiveSide.net, a community Website dedicated to Windows Live and

    his main area of blogging forLiveSide is developing on Windows

    Live.

    Sctt has written a number ofpopular plugins for Windows Live

    Writer and can often be found inthe Live Writer Support forum, for

    http://msdn2.microsoft.com/en-us/library/aa738852.aspxhttp://msdn2.microsoft.com/en-us/library/aa738852.aspxhttp://scottisafooldev.spaces.live.com/http://scottisafooldev.spaces.live.com/http://msdn2.microsoft.com/en-us/library/aa738852.aspxhttp://msdn2.microsoft.com/en-us/library/aa738852.aspxhttp://scottisafooldev.spaces.live.com/http://scottisafooldev.spaces.live.com/
  • 8/14/2019 Developing Plugins for Windows Live Writer

    13/23

    both general support and thedeveloper forums.

    Fast Facts!Windows Live Writer doesnt just

    support Microsofts own Windows

    Live Spaces blogging platform, it

    supports a number of different and

    popular blog engines, such as

    Wordpress or Community Server.

    Useful Windows Live

    Writer Links

    There are many places you canfind information on Live Writer.

    Here are some of myrecommended sites for both

    general Live Writer information anddeveloping for Live Writer.

    Live Writer blog:

    http://windowslivewriter.spaces.live.com

    Joe Chengs blog:

    http://jcheng.wordpress.com

    MSDN Developer forum:http://forums.microsoft.com/MSDN

    /ShowForum.aspx?

    ForumID=994&SiteID=1

    Live Writer Support Forum:http://groups.msn.com/WindowsLiveWriter

    Settings, like Forms, can be an

    integral part of your plugin if

    you would like the user to be

    able to set defaults for the

    plugin.

    ContentSource plugins are

    very basic plugins and will

    only insert text into the blog

    entry. You can edit

    SmartContentSource plugins

    content again at a later time.

    While the examples given in

    this article are C#, the Live

  • 8/14/2019 Developing Plugins for Windows Live Writer

    14/23

    Writer API is .NET, so youre

    not limited to just C#.

    Figure 1: What you need to get the plugin to copy to the plugins folder.

    Figure 2: What you need to debug your plugin.

    Figure 3: Some sample text to be made bold.

    Figure 4: The highlighted text.

    Figure 5: Having used the plugin the highlighted text is now bold.

    Figure 6: How your plugins options are accessed in Live Writer.

    Figure 7: How the options Form looks for this sample plugin.

    Figure 8: The sidebar in Live Writer appears on the right-hand side when a SmartContentSource is

    selected.

    Listing 1: Full code for a very basic Live Writer plugin.using System;using System.Collections.Generic;using System.Text;using WindowsLive.Writer.Api;using System.Windows.Forms;

    namespace LiveWriterExample{

    [WriterPlugin("d2c99304-8648-4696-9ef1-6a82a2d070c9","LiveWriterExamplePlugin",Description = "Makes highlighted text bold.",HasEditableOptions = true,ImagePath = "icon.gif",

    Name = "Bold Text Plugin",PublisherUrl = "http://www.liveside.net")]

    [InsertableContentSource("Bold Text")]

    publicclassLiveWriterExamplePlugin : ContentSource{

    publicoverrideDialogResult CreateContent(IWin32Window dialogOwner, refstring content)

    { // If nothing is highlighted, content will be empty. // If this is the case, the plugin does nothing. if (!string.IsNullOrEmpty(content))

    content = string.Format("{0}", content);

    returnDialogResult.OK;}

    }}

    Listing 2: This is the code for the PluginSettings class in the

    SmartContentSource plugin.using System;using System.Collections.Generic;using System.Text;

  • 8/14/2019 Developing Plugins for Windows Live Writer

    15/23

    using WindowsLive.Writer.Api;

    namespace EditPublish{ publicclassPluginSettings

    { IProperties m_properties; privateconststring PLACEHOLDER = "PLACEHOLDER"; privateconststring ACTUALCODE = "ACTUALCODE";

    public PluginSettings(IProperties properties){

    m_properties = properties;}

    publicstring PlaceHolder{

    get{

    return m_properties.GetString(PLACEHOLDER, "");}

    set{

    m_properties.SetString(PLACEHOLDER, value);}}

    publicstring FinalText{

    get{

    return m_properties.GetString(ACTUALCODE, "");}

    set{

    m_properties.SetString(ACTUALCODE, value);}

    }}

    }

    Listing 3: This is the code for the plugin class for the SmartContentSource

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

    namespace EditPublish{

    [WriterPlugin("18d43e01-4549-4fde-8ca6-c7b4b7385fac",

    "Insert Placeholder",PublisherUrl = "http://scottisafooldev.spaces.live.com",Description ="Lets you put in a placeholder for the editor, "+

    "to be replaced with other text when published.",ImagePath = "writer.png",HasEditableOptions = false)]

    [InsertableContentSource("Placeholder")]

    publicclassHiddenText : SmartContentSource{

    publicoverrideDialogResult CreateContent(IWin32Window dialogOwner,

  • 8/14/2019 Developing Plugins for Windows Live Writer

    16/23

  • 8/14/2019 Developing Plugins for Windows Live Writer

    17/23

    {m_settings.PlaceHolder = textBox1.Text;

    } else

    { MessageBox.Show("You need to set a placeholder",

    "Big Fat Hairy Error",MessageBoxButtons.OK,MessageBoxIcon.Error);

    return;

    } if (textBox2.Text != "")

    {m_settings.FinalText = textBox2.Text;

    } else

    { MessageBox.Show("Enter some text",

    "Big Fat Hairy Error",MessageBoxButtons.OK,MessageBoxIcon.Error);

    return;}

    this.DialogResult = DialogResult.OK; this.Close();

    }

    /// /// Required designer variable. /// private System.ComponentModel.IContainer components = null;

    /// /// Clean up any resources being used. /// protectedoverridevoid Dispose

    (bool disposing){

    if(disposing && (components != null)){

    components.Dispose();}

    base.Dispose(disposing);}

    #region Windows Form Designer generated code

    /// /// Required method for Designer support - do not modify

    /// the contents of this method with the code editor. /// privatevoid InitializeComponent()

    {System.ComponentModel.ComponentResourceManager resources =

    newSystem.ComponentModel.ComponentResourceManager(typeof(frmMain)); this.textBox1 = new System.Windows.Forms.TextBox(); this.textBox2 = new System.Windows.Forms.TextBox(); this.label1 = new System.Windows.Forms.Label(); this.label2 = new System.Windows.Forms.Label(); this.label3 = new System.Windows.Forms.Label(); this.button1 = new System.Windows.Forms.Button();

  • 8/14/2019 Developing Plugins for Windows Live Writer

    18/23

    this.button2 = new System.Windows.Forms.Button(); this.SuspendLayout(); //

    // textBox1 //

    this.textBox1.Location =new System.Drawing.Point(13, 124);

    this.textBox1.Multiline = true; this.textBox1.Name = "textBox1"; this.textBox1.Size = new System.Drawing.Size(407, 48);

    this.textBox1.TabIndex = 0; //

    // textBox2 //

    this.textBox2.Location =new System.Drawing.Point(13, 203);

    this.textBox2.Multiline = true; this.textBox2.Name = "textBox2"; this.textBox2.Size = new System.Drawing.Size(407, 56); this.textBox2.TabIndex = 1; //

    // label1 //

    this.label1.AutoSize = true; this.label1.Location =new System.Drawing.Point(13, 105);

    this.label1.Name = "label1"; this.label1.Size = new System.Drawing.Size(168, 13); this.label1.TabIndex = 2; this.label1.Text =

    "Text to appear in the Writer editor:"; //

    // label2 //

    this.label2.AutoSize = true; this.label2.Location =

    new System.Drawing.Point(13, 185);

    this.label2.Name = "label2"; this.label2.Size = new System.Drawing.Size(189, 13); this.label2.TabIndex = 3; this.label2.Text =

    "Text to appear in the actual blog entry:"; //

    // label3 //

    this.label3.Anchor =((System.Windows.Forms.AnchorStyles)

    (((System.Windows.Forms.AnchorStyles.Top |System.Windows.Forms.AnchorStyles.Left) |System.Windows.Forms.AnchorStyles.Right)));

    this.label3.Location = new System.Drawing.Point(13, 9); this.label3.Name = "label3"; this.label3.Size = new System.Drawing.Size(407, 96); this.label3.TabIndex = 4; this.label3.Text = resources.GetString("label3.Text"); //

    // button1 //

    this.button1.DialogResult =System.Windows.Forms.DialogResult.Cancel;

    this.button1.Location =new System.Drawing.Point(264, 272);

    this.button1.Name = "button1";

  • 8/14/2019 Developing Plugins for Windows Live Writer

    19/23

    this.button1.Size = new System.Drawing.Size(75, 23); this.button1.TabIndex = 5; this.button1.Text = "Insert"; this.button1.UseVisualStyleBackColor = true; this.button1.Click +=

    new System.EventHandler(this.button1_Click); //

    // button2 //

    this.button2.DialogResult =

    System.Windows.Forms.DialogResult.Cancel; this.button2.Location =

    new System.Drawing.Point(345, 272); this.button2.Name = "button2"; this.button2.Size = new System.Drawing.Size(75, 23); this.button2.TabIndex = 6; this.button2.Text = "Cancel"; this.button2.UseVisualStyleBackColor = true; //

    // frmMain //

    this.AcceptButton = this.button1; this.AutoScaleDimensions =

    new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode =System.Windows.Forms.AutoScaleMode.Font;

    this.CancelButton = this.button2; this.ClientSize = new System.Drawing.Size(432, 307); this.Controls.Add(this.button2); this.Controls.Add(this.button1); this.Controls.Add(this.label3); this.Controls.Add(this.label2); this.Controls.Add(this.label1); this.Controls.Add(this.textBox2); this.Controls.Add(this.textBox1); this.FormBorderStyle =

    System.Windows.Forms.FormBorderStyle.FixedSingle;

    this.MaximizeBox = false; this.MinimizeBox = false; this.Name = "frmMain"; this.ShowIcon = false; this.ShowInTaskbar = false; this.StartPosition =

    System.Windows.Forms.FormStartPosition.CenterParent; this.Text = "Insert Placeholder Plugin"; this.ResumeLayout(false); this.PerformLayout();

    }

    #endregion

    private System.Windows.Forms.TextBox textBox1; private System.Windows.Forms.TextBox textBox2; private System.Windows.Forms.Label label1; private System.Windows.Forms.Label label2; private System.Windows.Forms.Label label3; private System.Windows.Forms.Button button1; private System.Windows.Forms.Button button2;

    }}

  • 8/14/2019 Developing Plugins for Windows Live Writer

    20/23

    Listing 5: The code for the ContextEditor in the SmartContentSource

    plugin.using System;using System.Collections.Generic;using System.ComponentModel;using System.Drawing;using System.Data;using System.Text;using System.Windows.Forms;

    using WindowsLive.Writer.Api;

    namespace EditPublish{ publicclassContextEditor : SmartContentEditor

    { PluginSettings m_settings; ISmartContent m_content; public ContextEditor()

    {InitializeComponent();

    this.SelectedContentChanged +=newEventHandler(

    SelectedContentNowChanged);}

    void SelectedContentNowChanged(object sender, EventArgs e)

    {m_content = SelectedContent;m_settings =

    newPluginSettings(m_content.Properties);textBox1.Text = m_settings.PlaceHolder;textBox2.Text = m_settings.FinalText;

    }

    privatevoid button1_Click

    (object sender, EventArgs e){

    if (textBox1.Text != ""){

    m_settings.PlaceHolder = textBox1.Text;}

    else{

    MessageBox.Show("No placeholder","Big Fat Hairy Error",MessageBoxButtons.OK,MessageBoxIcon.Error);

    return;

    } if (textBox2.Text != ""){

    m_settings.FinalText = textBox2.Text;}

    else{

    MessageBox.Show("No text","Big Fat Hairy Error",MessageBoxButtons.OK,MessageBoxIcon.Error);

    return;}

  • 8/14/2019 Developing Plugins for Windows Live Writer

    21/23

    OnContentEdited();}

    ////// Required designer variable.

    /// private System.ComponentModel.IContainer components = null;

    ////// Clean up any resources being used.

    /// protectedoverridevoid Dispose(bool disposing)

    { if (disposing && (components != null))

    {components.Dispose();

    } base.Dispose(disposing);

    }

    #region Component Designer generated code

    ///

    /// Required method for Designer support - do not modify/// the contents of this method with the code editor. /// privatevoid InitializeComponent()

    { this.textBox1 = new System.Windows.Forms.TextBox(); this.label1 = new System.Windows.Forms.Label(); this.textBox2 = new System.Windows.Forms.TextBox(); this.label2 = new System.Windows.Forms.Label(); this.button1 = new System.Windows.Forms.Button(); this.label3 = new System.Windows.Forms.Label(); this.SuspendLayout(); //

    // textBox1

    //this.textBox1.Location =

    new System.Drawing.Point(3, 91); this.textBox1.Multiline = true; this.textBox1.Name = "textBox1"; this.textBox1.Size = new System.Drawing.Size(178, 58); this.textBox1.TabIndex = 0; //

    // label1 //

    this.label1.AutoSize = true; this.label1.Location = new System.Drawing.Point(0, 73); this.label1.Name = "label1";

    this.label1.Size = new System.Drawing.Size(168, 13); this.label1.TabIndex = 3; this.label1.Text =

    "Text to appear in the Writer editor:"; //

    // textBox2 //

    this.textBox2.Location =new System.Drawing.Point(3, 182);

    this.textBox2.Multiline = true; this.textBox2.Name = "textBox2"; this.textBox2.Size = new System.Drawing.Size(178, 58); this.textBox2.TabIndex = 4;

  • 8/14/2019 Developing Plugins for Windows Live Writer

    22/23

    //// label2

    //this.label2.AutoSize = true;

    this.label2.Location =new System.Drawing.Point(0, 164);

    this.label2.Name = "label2"; this.label2.Size = new System.Drawing.Size(171, 13); this.label2.TabIndex = 5; this.label2.Text =

    "Text to appear in actual blog entry:"; //

    // button1 //

    this.button1.Location =new System.Drawing.Point(3, 255);

    this.button1.Name = "button1"; this.button1.Size = new System.Drawing.Size(75, 23); this.button1.TabIndex = 6; this.button1.Text = "Apply"; this.button1.UseVisualStyleBackColor = true; this.button1.Click +=

    new System.EventHandler(this.button1_Click);

    //// label3 //

    this.label3.Anchor =((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top |System.Windows.Forms.AnchorStyles.Left) |System.Windows.Forms.AnchorStyles.Right)));

    this.label3.BackColor = System.Drawing.Color.White; this.label3.Font =

    new System.Drawing.Font("Microsoft Sans Serif",14F, System.Drawing.FontStyle.Regular,System.Drawing.GraphicsUnit.Point, ((byte)(0)));

    this.label3.Location = new System.Drawing.Point(0, 0);

    this.label3.Name = "label3"; this.label3.Size = new System.Drawing.Size(190, 32); this.label3.TabIndex = 7; this.label3.Text = "Insert Placeholder"; //

    // ContextEditor //

    this.AutoScaleDimensions =new System.Drawing.SizeF(6F, 13F);

    this.AutoScaleMode =System.Windows.Forms.AutoScaleMode.Font;

    this.Controls.Add(this.label3); this.Controls.Add(this.button1);

    this.Controls.Add(this.label2); this.Controls.Add(this.textBox2); this.Controls.Add(this.label1); this.Controls.Add(this.textBox1); this.Name = "ContextEditor"; this.Size = new System.Drawing.Size(190, 482); this.ResumeLayout(false); this.PerformLayout();

    }

    #endregion

  • 8/14/2019 Developing Plugins for Windows Live Writer

    23/23

    private System.Windows.Forms.TextBox textBox1; private System.Windows.Forms.Label label1; private System.Windows.Forms.TextBox textBox2; private System.Windows.Forms.Label label2; private System.Windows.Forms.Button button1; private System.Windows.Forms.Label label3;

    }}