Google Desktop plugin (Google Gadgets) & C#

Couple of weeks ago I was involved in a project in which I supposed to make a google display widget (gadget). As features it supposed to have changeable skins, transparency, and because of couple of technical difficulties which seemed to be impossible to get over by using javascript, I choosed to make it in C# (because one of our ex-coworkers had some experience in developing gadgets in C#, and various other reasons). So I fired up the browser looking for help / samples tutorials, and VS2005 to start producing something useful.
Anyway, to cut a long story short, all samples I’ve seen were based on helper classes provided by Google, which I also used, unfortunately, however later I figured out it is impossible to have the helper classes for functionality and your own user control for the gadget content. While they are nice and provide lot of already existing functionality, they are not so good when you have to do your own drawings.
The solution? Forget about the helper classes provided by Google, and use the provided interfaces to create the helper class equivalent, and be sure you implement all interfaces specified in the IDL file (do not trust visual studio’s object browser, sometimes is acting plain stupid).
So, all you have to do is create your own user control, and then implement one of the IGoogleDesktopDisplayPlugin* interfaces and IObjectWithSite interface:

namespace YourNameSpace
{
    [ComVisible(true)]
    [GuidAttribute("Your GUID ")]
    public partial class Plugin : UserControl,IGoogleDesktopDisplayPlugin2,
    IObjectWithSite
    {
        ...... implement your control and required google interface functions ....
    }
}

For registering and unregistering the plugin, use the RegisterFunction and UnregisterFunction methods, and for both provide your plugin GUID:

[ComRegisterFunctionAttribute]
static void RegisterFunction(Type t)
{
    try
    {
        string keyName = @"CLSID\" + t.GUID.ToString("B");
        using (RegistryKey key = Registry.ClassesRoot.OpenSubKey(keyName, true))
        {
            key.SetValue("", "Plugin Name");
            key.CreateSubKey("Control").Close();
            using (RegistryKey subkey = key.CreateSubKey("Description"))
            {
                subkey.SetValue("", "Plugin description");
            }
        }

        // Create the registrar object
        GoogleDesktopRegistrarClass registrar = new
        GoogleDesktopRegistrarClass();
        if (registrar == null)
        {
            MessageBox.Show("Please install google desktop first!");
            return;
        }

        object[] descriptions = {
            "Title", "Title",
            "Description", "Description",
            "Icon",""
        };

        registrar.StartComponentRegistration("{49F8F35E-B275-4d6e-9747-5653DD678E77}",
            descriptions);

        // A single component can register for multiple plugins
        //with Google Desktop.
        // Here we register a single display plug-in.
        IGoogleDesktopRegisterDisplayPlugin displayRegistration =
            (IGoogleDesktopRegisterDisplayPlugin)

        registrar.GetRegistrationInterface(
        "GoogleDesktop.DisplayPluginRegistration");

        //our plugin
        displayRegistration.RegisterPlugin(
            "{Your GUID}", true);

        // Done with component registration.
        registrar.FinishComponentRegistration();
    }
    catch (Exception e)
    {
        MessageBox.Show("Exception thrown during registration.
        Description=" + e.Message);
    }
}

[ComUnregisterFunctionAttribute]
static void UnregisterFunction(Type t)
{
    try
    {
        // Create the registrar object
        GoogleDesktopRegistrarClass registrar = new
        GoogleDesktopRegistrarClass();

        // Unregister ourselves
        registrar.UnregisterComponent("Your GUID");
    }
    catch (Exception e)
    {
        MessageBox.Show("Exception thrown during registration.
        Description=" + e.Message);
    }
}

To set plugin window size, use GetInfo method of IGoogleDisplayPlugin:

public void GetInfo(ref GoogleDesktopDisplayTileInfo tile_info)
{
    tile_info.ideal_size.x = 345;
    tile_info.ideal_size.y = 307;
    tile_info.host_window_size.x = 345;
    tile_info.host_window_size.y = 307;
    tile_info.max_size.x = 345;
    tile_info.max_size.y = 307;
    tile_info.min_size.x = 345;
    tile_info.min_size.y = 307;
    tile_info.mask = GoogleDesktopDisplayInfoMasks.GDD_INFO_MASK_IDEAL_SIZE |
       GoogleDesktopDisplayInfoMasks.GDD_INFO_MASK_MIN_SIZE |
       GoogleDesktopDisplayInfoMasks.GDD_INFO_MASK_MAX_SIZE;
    this.MaximumSize = new Size(345, 307);
    this.MinimumSize = new Size(345, 307);
}

Unfortunately seems like this cannot be done dynamically
From IObjectWithSite you have to implement SetSite() method, in order to remove the default gadget frame:

IGoogleDesktopDisplaySite displaySite;

public void SetSite(Object site)
{
    displaySite = (IGoogleDesktopDisplaySite)site;

    // Display our content here...
    if (site != null)
    {
        displaySite.flags = GoogleDesktopDisplayPluginFlags.GDD_PLUGIN_FLAG_NO_FRAME;
        // init sub-components:idea:
     }
}

All other methods can remain doing nothing. Please note: some methods if are not implemented by throwing exception, it will make google desktop not loading the plugin.
At this moment you should have a gadget which is written in c# and can show itself.
There are still couple of issues to solve, such as dragging the gadget by mouse, transparency, etc. but the first step is made 😛
Happy coding 🙂

  1. You have tested it and writing form your personal experience or you find some information online?

  2. I usually test all the code I blog about.

Leave a Comment