Please create new project ClassLibrary in Visual Studio.NET and call it: firstPlugin, then add reference do dsidebarpia.dll which is included in dssdk.zip in Desktop Sidebar installation folder. Now we have project prepared and we should start coding.

Please add class firstPlugin. Something like this should appear:

using System;

namespace firstPlugin
{
   public class firstPlugin
   { 
      public firstPlugin()
      {
      }
   }
}

now please add using directive for DesktopSidebar namespace and inherit firstPlugin class from two interfaces IPlugin and IPanelCreator. Result should be like this:

using System;
using DesktopSidebar;

namespace firstPlugin
{
   public class firstPlugin : IPlugin, IPanelCreator
   {
      public firstPlugin()
      {
      }
      public void Load(
         out string author, 
         out string authorEMail, 
         out string description, 
         out string website, 
         int sidebarBuild, 
         Sidebar Sidebar, 
         IXmlNode pluginConfig, 
         int pluginCookie)
      {
      }
      public void Unload()
      {
      }
      public void OnPluginLoaded(string plugin)
      {
      }
      public void CreatePanel(ref IPanel panel, string panelClass)
      {
      }
   }
}

IPlugin interface includes three methods: Load, Unload and OnPluginLoaded. Now the most interesting is Load method. This method is called by Desktop Sidebar when plugin is loaded and in it we should inform DS that our plugin is able to create panels.

Please add following lines of code:

   Sidebar.RegisterPanel(
      "firstPanel",
      "First .NET Panel",
      "This is description of First Panel",
      0,
      "",
      "This is category of First Panel",
      "",
      "",
      "",
      pluginCookie);

   author = "DS Team";
   authorEMail = "support@desktopsidebar.com";
   description = "";
   website = "http://www.desktopsidebar.com";

We register panel in sidebar and two parameters of RegisterPanel method are very important. First parameter is panelClass and the last parameter is pluginCookie. One plugin can implement many panels so we have to distinguish panels in some way. We will use textual identifier called panelClass to do this. pluginCookie is used when user add our plugin to sidebar. DS will find plugin with given pluginCookie and will call method CreatePanel passing panelClass parameter.

We also returns some additional information about our plugin which is displayed in "Plugins" window in Desktop Sidebar

Now we should create panel class. Please create new class in Visual Studio.NET and call it "firstPanel", add "using DesktopSidebar;" and then inherit firstPanel class from IPanel, IPanelWindow and ITextOutputParent interfaces.

IPanel is basic interface of panel. The most important method of this interface is Create which of course is called when panel is created

If panel doesn't use canvases and implements its window manually it has to implement IPanelWindow interface. Methods of this interface allows Desktop Sidebar communicate with window of panel.

You can use .NET forms to implement panel window but in case of simple panels with just one window we can use controls provided by Desktop Sidebar. These controls have one big advantage over .NET controls - they are skin-aware. In order to use ITextOutput control which is equivalent of .NET Label Control panel has to implement ITextOutputParent interface

Please add such fields to firstPanel class

Sidebar sidebar;
IPanelParent parent;
int cookie;

ITextOutput textOutput;

and now add such code to Create method

// we store some data for later use
sidebar=Sidebar;
parent=Parent;
cookie=Cookie;

// we set caption of our panel
parent.SetCaption(cookie,"First .NET Panel");

// we create textOutput control 
textOutput=Sidebar.GetControlFactory().CreateTextOutput();
textOutput.Init(Sidebar.GetGlobalSettings(),Sidebar.GetSkinManager(),this,true);
textOutput.Create(hwndParent,true);

// we will display "Hello World" on our panel
textOutput.SetText("Hello World");

implementation of IPanelWindow should look like this:

// IPanelWindow Members
public System.IntPtr GetHwnd()
{
   return (System.IntPtr)textOutput.GetHwnd();
}

public int GetFitHeight(int width)
{
   return textOutput.GetFitHeight();
}

When DS asks as about our HWND we will return HWND from textOutput.

Desktop Sidebar allows user to set arbitrary height of panel but user can also enable "Autofit" and then DS automatically calculates height of panel base on its content. To make it possible we have to implement GetFitHeight method but in our case it is easy. We will just pass this call to textOutput control

And now ITextOutputParent implementation

public void OnDrawBackground(ITextOutput textOutput, IGraphics graphics)
{
   parent.DrawControlBackground(graphics,cookie,textOutput.GetHwnd());
}

public void OnClick(ITextOutput textOutput, bool dbclk)
{
   sidebar.MsgBox("Hello World clicked","First .NET panel",0);
}

Controls don't know too much about their background because it depends on your panel and group in which your panel is placed by user so controls call OnDrawBackground and your panel should draw their background. In our case we just ask our parent to draw this background

To make our example a little more interactive we will add implementation of OnClick method and we display Message Box when user clicks on our panel

Now we have complete source of our panel

using System;
using DesktopSidebar;

namespace firstPlugin
{
   public class firstPanel: IPanel, IPanelWindow, ITextOutputParent
   {
      Sidebar sidebar;
      IPanelParent parent;
      int cookie;

      ITextOutput textOutput;

      public firstPanel()
      {
      }

      // IPlugin Members
      public void Create(
         int hwndParent, 
         Sidebar Sidebar, 
         IPanelParent Parent, 
         IPanelConfig config, 
         ICanvas canvas, 
         IXmlNode configRoot, 
         IXmlNode panelConfig, 
         IXmlNode settingsRoot, 
         IXmlNode panelSettings, 
         int Cookie)
      {
         sidebar=Sidebar;
         parent=Parent;
         cookie=Cookie;

         parent.SetCaption(cookie,"First .NET Panel");

         textOutput=Sidebar.GetControlFactory().CreateTextOutput();
         textOutput.Init(Sidebar.GetGlobalSettings(),Sidebar.GetSkinManager(),this,true);
         textOutput.Create(hwndParent,true);

         textOutput.SetText("Hello World");
      }

      public void Close()
      {
         textOutput.Close();
      }

      public bool Tick(bool minute)
      {
         return false;
      }

      public void Save(IXmlBuilder panelItem, IXmlBuilder settingsRoot)
      {
      }

      // IPanelWindow Members
      public int GetFitHeight(int width)
      {
         return textOutput.GetFitHeight();
      }

      public System.IntPtr GetHwnd()
      {
         return (System.IntPtr)textOutput.GetHwnd();
      }

      // ITextOutputParent Members
      public void OnDrawBackground(ITextOutput textOutput, IGraphics graphics)
      {
         parent.DrawControlBackground(graphics,cookie,textOutput.GetHwnd());
      }

      public void OnClick(ITextOutput textOutput, bool dbclk)
      {
         sidebar.MsgBox("Hello World clicked","First .NET panel",0);
      }

      public void OnMouseLeave(ITextOutput textOutput)
      {
      }

      public void OnShowDetails(ITextOutput textOutput)
      {
      }

      public void OnMouseHover(ITextOutput textOutput)
      {
      }

   }
}

And we can go back to plugin and finish implementation of CreatePanel method. In this method we should create object of firstPanel class and return it to Desktop Sidebar

Complete source of our plugin should look like this:

using System;
using DesktopSidebar;

namespace firstPlugin
{
   public class firstPlugin : IPlugin, IPanelCreator
   {
      public firstPlugin()
      {
      }
      public void Unload()
      {
      }
      public void OnPluginLoaded(string plugin)
      {
      }
      public void Load(
         out string author, 
         out string authorEMail, 
         out string description, 
         out string website, 
         int sidebarBuild, 
         Sidebar Sidebar, 
         IXmlNode pluginConfig, 
         int pluginCookie)
      {
         Sidebar.RegisterPanel(
            "firstPanel",
            "First .NET Panel",
            "This is description of First Panel",
            0,
            "",
            "This is category of First Panel",
            "",
            "",
            "",
            pluginCookie);

         author = "DS Team";
         authorEMail = "support@desktopsidebar.com";
         description = "";
         website = "http://www.desktopsidebar.com";
      }

      public void CreatePanel(ref IPanel panel, string panelClass)
      {
         if (panelClass=="firstPanel")
         {
            panel=new firstPanel();
         }
      }
   }
}

So we have finished coding and now we should force Desktop Sidebar to load our plugin. This is done by DSPLUGIN file.

Please create such xml file and save it as firstPlugin.dsplugin in Desktop Sidebar directory

<?xml version="1.0" encoding="utf-8" ?>
<plugin progid="firstPlugin.firstPlugin" compatible="85">
</plugin>

Attribute progid="firstPlugin.firstPlugin" is the most important here. It tells Desktop Sidebar that in order to load this plugin it should create COM component with firstPlugin.firstPlugin ProgId. In order to make your .NET class accessibly as COM object we have to enable "Register for COM Interop" in Project Settings in Visual Studio.NET.

Now compile everything, restart Desktop Sidebar and you should be able to add your "First .NET Panel" to Desktop Sidebar

DSSDK.ZIP from Desktop Sidebar installation directory includes additional samples and wizards which creates such boilerplate code for you

You can debug your panel with the Visual Studio.NET debugger: set Project->[ProjectName] Properties->Configuration Properties->Build->Debug Mode to "Program". Click Apply, and then in Start Application point to the Desktop Sidebar execuatble (usually C:\Program Files\Desktop Sidebar\dsidebar.exe). Now every time you Debug->Start your project, Desktop Sidebar will open. You will be able to set breakpoints in your code and debug it as if it was a regular Windows Forms project.