Ritesh’s Technical Blog

Build Your Own Windows Vista Sidebar Gadget

Posted on: February 22, 2009

Before starting let us know some basics.

What Is a Sidebar Gadget?

You already know what a sidebar is, but for those who dont know see the below image-
A Sidebar is shown with a lot of gadgets in it at the right side of the desktop in the above image.
A sidebar gadget is a powerful and handy little tool. A gadget is made up of nothing more than a
  • HTML file and
  • an XML definition file.

Apart from that, most gadgets include other files, such as

  • image files (PNG and JPG),
  • style sheets (CSS), and
  • scripting (JavaScript and VBScript source files)

which give them good look and feel. All of the content is stored in a ZIP file that is renamed with a .gadget extension. If you have read my tutorial on how to create window media player skin, then I may assure you, that this is also as simple as that one. If you want, you can grab a gadget online, rename it with a .zip extension, and easily explore its contents.

XML Definition File

The XML definition file, or manifest, is the glue that holds a gadget together. It only contains links to the main HTML file (which has links to the other files), a few icon files, and the gadget author’s Web site.
A typical XML definition file is shown below. As you can see, it is a standard XML file with a base element of gadget.
<gadget>
  <name>Gadget Name Here</name>
  <namespace>YourCompanyNameHere</namespace>
  <version>1.0.0.0</version>
  <author name=”Company Name Here”>
    <info url=”http://contoso.com” text=”Vist our Web site” />
    <logo src=”logo.png” />
  </author>
  <copyright>© 2007</copyright>
  <description>your gadget description</description>
  <icons>
    <icon width=”64” height=”64” src=”icon.png” />
  </icons>
  <hosts>
    <host name=”sidebar”>
      <base type=”HTML” apiVersion=”1.0.0” src=”gadget.html” />
      <permissions>full</permissions>
      <platform minPlatformVersion=”0.3” />
    </host>
  </hosts>
</gadget>
 Here is a list of the elements you should be most concerned with:
  • name: Title of your gadget.
  • version: Version number of your gadget.
  • author: Your name or your company’s name.
  • info url: Web site address.
  • info text: Friendly name for your Web site.
  • logo src: Name of company’s logo image file.
  • copyright: Copyright notice.
  • description: Description of the gadget.
  • icon src: Name of icon image file for the gadget.
  • base src: Name of gadget’s main HTML file.
Most of the elements in the definition file are used for displaying the gadget in the gallery. The one truly functional element is the src attribute of the base element—this points to the HTML file that will kickstart the gadget. I make it a practice to name this file gadget.html, but any valid filename will do.

The Main HTML File

The implementation of a gadget is nothing more than an HTML page that is a maximum of 130 pixels wide. Though this isn’t readily evident, the main HTML file (the one referenced in the XML definition file) is actually loaded into an Internet Explorer® 7 window. There is, of course, no chrome surrounding this window and its location is controlled by Sidebar, but everything inside is basically a Web application.
You can also use APIs from the Sidebar Gadget Object Model. These APIs provide a way for your gadget to interface with the system. For example, you can read the signal strength of your wireless network card, play a sound file, or determine the CPU usage.
As you look at the HTML for a gadget, you’ll notice that there is absolutely nothing that distinguishes it from HTML that you would code for a regular Web page. Here is the HTML code I use to start practically all of my Sidebar gadget projects:
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN”
   “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>
<html xmlns=”http://www.w3.org/1999/xhtml”>
<head>
   <title></title>
   <meta http-equiv=”Content-Type” content=”text/html; charset=utf-8” />
   <link href=”style.css” rel=”stylesheet” type=”text/css” />
   <script src=”local.js” type=”text/javascript”></script>
   <script src=”gadget.js” type=”text/javascript”></script>
</head>
<body>
   <div id=”gadget” class=”gadget”></div>
</body>
</html>
In the sample presented here, all of the HTML for the gadget is created dynamically from within the gadget.js JavaScript file. You could include most of the markup in the main HTML file, but what fun would that be?
Notice that I use CSS style sheets. This is what will drive the look of my gadget. As with any Web page, style sheets are an essential part of designing good-looking gadgets. Thus a good understanding of CSS is critical when producing a professional-looking gadget.
I should point out that while developing the main HTML file for a gadget is entirely like building a page that will be deployed online, the gadget implementation has a major advantage. You don’t have to worry about cross-browser issues. Since your gadget will always be run under Internet Explorer, you can rely on support for Internet Explorer features, such as native PNG alpha support, and there’s no need to write code to account for browser incompatibilities.
When I started developing Sidebar gadgets, I found this very refreshing. Over time, I began to take this for granted and when I recently had to design a Web page, I found myself getting very aggravated when I had to deal with cross-browser issues once again.

JavaScript

If you plan on doing anything interesting within your gadget, you’d better brush up on your JavaScript. You can code with any scripting language that is supported by Internet Explorer 7, but you will find that most of the gadget samples on “the Internets” are written in JavaScript.
If you have worked with JavaScript for any time at all, you have probably heard the phrase “eval is evil.” If not, go ahead and look it up online. I’ll wait.
Now that you understand why you should never use eval, I’m going to amend that rule to include that you should never place JavaScript text in an attribute inside of your HTML nor pass a string to setInterval or setTimeout. And when I say that you should never place JavaScript text in an attribute inside your HTML, this includes the body onload attribute, as this is interpreted internally just as an eval statement would be.
I’m sure some of you are saying, “No body onload? How will my code execute?” I suggest that you get in the habit of attaching a function to the onload event of the window object. This code snippet shows how to attach to the onload and onunload events:
function pageLoad() {
    window.detachEvent(“onload”, pageLoad);
    window.attachEvent(“onunload”, pageUnload);
    //page initalization here
}

function pageUnload() {
    window.detachEvent(“onload”, pageUnload);
    //gadget is closing, clean up
}

window.attachEvent(“onload”, pageLoad);
By using this method, function pageLoad is called well after the page loads (when the DOM is complete). Notice that the first thing I do in pageLoad is detatch the event. It is always a good idea to clean up after yourself in JavaScript to prevent memory leaks.
Next, I set up the onunload event that will be called as the gadget is destroyed—either as the user closes the gadget or when Sidebar is shut down. Again, this is done to free up any references that may cause memory leaks. It is also your last chance to save any settings if need be. I’ll talk all about settings a little later in the article.
You may have noticed by now that I’m a bit of a stickler for writing good, clean JavaScript, so please indulge me one more time on the subject. I strongly suggest that you “lint” your code before deployment. This will not only make your code better, but it may even root out some bugs before they happen.
Lint was the original name given to a tool that flagged problem areas in C source code. It is now a general term applied to many source languages. One of the better lint applications for JavaScript is a free online tool called JSLint (available at www.jslint.com).
The May 2007 issue of MSDN Magazine has an excellent feature on JavaScript titled “Create Advanced Web Applications with Object Oriented Techniques” by Ray Djajadinata. You should check it out if you haven’t already done so. This article will go a long way to helping you write a better gadget.

Docked and Floating

When a gadget is nestled in the Sidebar, it is considered to be in the docked state. Once dragged onto the desktop, it is floating or undocked. As I mentioned, the maximum width for a docked gadget is 130 pixels. An undocked gadget has no restriction on width, allowing you to design an expanded view. You can take advantage of this extra room to provide a richer experience. (Microsoft recommends that you don’t exceed 400 pixels square for an undocked gadget.) Figure 2 shows my MSDN Magazine Ticker gadget (that shows scrolling article headlines from the most recent issue) and a weather gadget (that ships with Windows Vista) in both their docked and floating states. The weather gadget is an excellent example of a gadget that provides a richer experience when floating—it goes from giving just the current temperature to giving a detailed three day forecast. The MSDN Magazine Ticker gadget doesn’t display any additional information; it simply expands to show the same information in a wider format.
Figure 2 Docked and Floating Gadgets (Click the image for a larger view)
Note that there is an undocumented minimum height of 57 pixels for a gadget (whether docked or floating). The reason for this minimum is simple: the height of the toolbar when a gadget is in its floating state is 57 pixels (see Figure 3).
Figure 3
You can query the current state of a gadget with System.Gadget.docked. It returns true if docked, false if undocked. There are also two events that you can monitor, System.Gadget.onDock and System.Gadget.onUndock, to determine when the docking state changes.
You cannot simply change the class of the document.body from within an onDocked or onUndocked event to change the height, width, or background image of a gadget (this is contrary to my initial expectations). Instead, you must specifically set the properties of the style object of the body element. To change the background image, use the System.Gadget.background API to set the filename of the background image. Here’s an example:
// called when the docked state changes
function dockStateChanged() {
    if (System.Gadget.docked) {
        System.Gadget.background = “images/background.png”;
        document.body.style.width = “130px”;
    } else {
        System.Gadget.background = “images/background-undocked.png”;
        document.body.style.width = “230px”;
    }
}

Flyouts

A flyout extends the user interface outside of the gadget’s own borders. You can use this window for anything you wish. (There is no maximum size imposed for flyout windows.) A good example of a gadget that uses a flyout is the Stocks gadget that ships with Windows Vista. Clicking on a stock causes a window to fly out to the side of the gadget, displaying a graph of that stock’s activity (see Figure 4). The Live Search gadget also uses a flyout, displaying search results for the query you entered. Figure 5 shows a flyout from our MSDN Magazine Ticker gadget. Notice that when a headline is clicked, the UI extends out from the docked gadget to show the article title, a description, and the author’s name.
Figure 4 Stocks Gadget Displaying a Flyout (Click the image for a larger view)
Figure 5Ticker Gadget Displaying a Flyout (Click the image for a larger view)
Note that Sidebar gadget flyouts are system modal—only one can be displayed at a time. If the user clicks on Gadget A, causing a flyout, and then clicks on Gadget B, causing another flyout, Gadget A’s flyout will close. Furthermore, when a gadget loses focus, its flyout will close.
The flyout APIs are exposed from the System.Gadget.Flyout object. A flyout lives in a completely isolated window (with its own DOM) from that of the main HTML window. As such, you need to provide a separate flyout HTML file, along with any other necessary supporting files. The flyout file is specified by setting System.Gadget.Flyout.file to the name of the flyout HTML file.
There is an API you can use to facilitate communication between the main and flyout windows. System.Gadget.Flyout.document returns the Document object of the flyout window. You can use this from the main gadget window to dynamically generate HTML in the flyout window.
There are also events that can be captured by both the main and flyout code. These include onShow, which is called just after the flyout document has been created, and onHide, which is called just before the flyout document is destroyed.
You can programmatically show or hide the flyout by setting System.Gadget.Flyout.show to true or false, respectively. And reading this value will tell you the current state of the flyout window.
Keep in mind that you cannot control the location of the flyout. Sidebar determines the location based on screen real estate and the position of the gadget itself. For example, the flyout could be displayed to the left or to the right of the gadget. Or even below it.

Options Dialog

The options dialog allows you to present the user with a list of gadget preferences. The user experience can be most anything you want. The dialog can be just like a regular Web page with radio buttons, checkboxes, and textboxes.
A user can access the options dialog by clicking on the wrench icon in the gadget’s toolbar (see Figure 3), which appears when you hover over the gadget. When a user opens the options dialog of a gadget, Sidebar takes a snapshot of the gadget and displays the image as a small icon (see Figure 6).
Figure 6 

Options Dialog

I would like to point out that there is some ambiguity when it comes to the name of this dialog. When you right-click on a gadget, the gadget UI presents a menu that refers to this as “Options.” The API, however, refers to this as “settings.”
I was a bit surprised to find that user settings are stored in a circa 1990 INI file instead of a more modern XML file. Fortunately, there are gadget APIs to read and write settings, so where and how the settings are stored is of little concern to you or your application.
There are a few caveats when it comes to creating your options UI. The width of the user area of the dialog is limited to a maximum of 300 pixels. There is no height limit, but the Microsoft UX Guide for Windows Vista Gadgets recommends a maximum width of 278 pixels and a height of no more than 400 pixels. If you need more room, you should probably create a tabbed dialog. I won’t talk about how to implement a tabbed UI in this article, but there are plenty of resources on the Web to learn how you can do this.
You need to instruct the gadget to enable the options icon. This is done by setting System.Gadget.settingsUI to the name of the HTML file, generally in the gadget initialization area of your script. You also need to set up a callback function for when the options dialog closes (so your gadget can read the new user preferences). You do this by setting System.Gadget.onSettingsClosed to the name of your handler, as shown here:
System.Gadget.settingsUI = “settings.html”;
System.Gadget.onSettingsClosed = settingsClosed; 

function settingsClosed(p_event) {
    //OK clicked?
    if (p_event.closeAction == p_event.Action.commit) {
        //yes, read settings here
    }
}
As you can see from this example, when the handler is called, it is passed an event object— specifically the System.Gadget.Settings.ClosingEvent event object. If the closeAction property of the ClosingEvent object contains a value of commit, this means the user selected OK and you will likely want to read the new settings. Otherwise, the options dialog was canceled and you can bypass reading of the preferences.

Reading and Writing Settings

Settings are written using System.Gadget.Settings.write or System.Gadget.Settings.writeString. Both are passed a key/value pair. Conversely, settings are read with System.Gadget.Settings.read or System.Gadget.Settings.readString. Both of these functions take a key and return a value. If the key does not exist (for instance if it has never been written) both will return a value of undefined.

JavaScript is not a strongly typed language and if you use write and read, Sidebar will attempt type conversion. If you want to be absolutely sure what is written and read, consider using writeString and readString as these will assume strings. Depending on the type of data in question, you will have to determine which methods will work best.

Localization

Sidebar gadgets support localization by way of “localized folders.” Whenever Sidebar tries to load an asset (a gadget manifest, style sheet, image file, JavaScript file), it searches for the file in folders in the following order:
  • Full locale (en-us, es-us, ja-jp)
  • Language portion of the locale (en, es, ja)
  • Gadget root folder
For example, if you are running a US version of Windows Vista and your preferences are set to Spanish, Sidebar will first look in the folder es-us. If the file is not found there, Sidebar will then search the es folder. And finally, if the file is still not found, Sidebar will search the gadget root folder.
Language is obviously important, but why is location important? Location is actually very important for certain gadgets. Consider the weather gadget. You may display the word sunny to users in both the United States and the United Kingdom, but the location will determine whether you should display the temperature in Fahrenheit (US) or Celsius (UK).
Many developers will likely support an English-only gadget, but if locale is important to you I recommend that you put all of your language-specific strings and location-specific variables in a single JavaScript file called local.js and place this file in the gadget root folder. Then create a folder for each locale that you are going to support and copy the translated versions of local.js into their respective folders. Here is an example of a local.js file in the root folder, representing en-us:
var L_Hello = “Hello”;
var L_Degrees = 0;
The same file in the \es-es folder may look like this:
var L_Hello = “Hola”;
var L_Degrees = 1;
When you want to display Hello, you would use the variable L_Hello rather than the hardcoded string. And when querying the weather feed, you would use L_Degrees to request the proper format. This produces a greeting in the appropriate language and gives the temperature according to the user’s preferences. In your main JavaScript code, when you want to use a string or determine what to use for degrees, you would do something like this:
element.innerHTML = L_Hello;
if (L_Degrees === 0) {
    //load the Fahrenheit feed
} else {
    //load the Celsius feed
}
As you can see, your code will react differently depending on which local.js file is loaded by Sidebar. Cool, huh?
Note that with the English local.js in the gadget root, the gadget will still function for non-supported locales, albeit in the fallback language (in this case English). It is very important to support a default language in your gadget’s root folder. If you don’t provide a default language and someone uses a language that isn’t supported by your gadget (meaning a language for which you have not created a subfolder), your gadget will display blank strings.

What Happened to Alert and Confirm?

We’ve all been on Web sites and received the “Invalid input, please try again” alert and the “Delete record. Are you sure?” confirmation dialog. Developers often want to pop up informational messages like these.
Sidebar, however, has disabled these JavaScript functions. Using popup dialogs goes against the Windows Vista UX guidelines for Sidebar gadgets. If you still feel compelled to use popups, you can emulate these functions.
To do this, first insert a simple one line tag into the head element of your HTML:
<script src=”alert.vbs” type=”text/vbscript”></script>
Then create a file that contains the code shown below and name it alert.vbs. Now you can continue to use alert and confirm as you wish.
‘simulate JavaScript alert() function
sub alert(prompt)
    MsgBox prompt, 48 , “Sidebar Gadget”
end sub

‘simulate JavaScript confirm() function
function confirm(prompt)
    dim res
    res = MsgBox (prompt, 33, “Sidebar Gadget”)
    if res=1 then
        confirm = true
    else
        confirm = false
    end if
end function

Debugging

Debugging JavaScript has always been tricky. Many developers have resorted to placing alerts in their code to display the values of certain variables. This, however, is not an elegant solution. A better method involves using Visual Studio® (or even the free Visual Web Developer™ 2005 Express Edition). 

Simply place debugger statements in your code, wherever you need to check the value of a variable, then run the gadget. When JavaScript executes the debugger statement, you should see a popup that asks if you want to debug the application (see Figure 8 ). Choosing Yes will allow you to browse the entire gadget environment, including the DOM, and view the value of any variable created. Your gadget is essentially frozen in time.
Figure 8 Do You Want to Debug Your Gadget? (Click the image for a larger view) 

Figure 9 shows a section of debugged code where the value of the variable refreshRate is 24. This form of debugging is very powerful. Once you try it, you’ll never go back to spattering your code with alert statements. Note that JavaScript debugging is vastly improved in the next version of Visual Studio code-named “Orcas.” You can read more about these new features at JScript Debugging in Visual Web Developer Orcas, and you can download “Orcas” Beta 1 at msdn2.microsoft.com/aa700831.

Figure 9Debugging a Gadget in Visual Studio (Click the image for a larger view)

Packaging Your Gadget

The simplest way to create a package is with Windows Explorer. Select the files that make up your gadget, right-click, and select Send To | Compressed (zipped) Folder.
You can also package your gadget as a CAB file, which is the Microsoft native compressed archive format. Just generate the CAB file and then rename it with a .gadget extension. (By the way, if you ever try renaming a .gadget file with a .zip extension and Windows Explorer complains when you try to open this ZIP file, try renaming the file with a .cab extension instead.)
There are a few different methods you can use if you want to programmatically generate a gadget. In my projects, I create the following batch file called make.bat:
@echo off

rem ** remove/create a test gadget folder
rd “%LOCALAPPDATA%\Microsoft\Windows Sidebar\
    Gadgets\MSDNSample.gadget\” /s /q
md “%LOCALAPPDATA%\Microsoft\Windows Sidebar\Gadgets\MSDNSample.gadget\”

rem ** copy all of the files into test area
xcopy . “%LOCALAPPDATA%\Microsoft\Windows Sidebar\
    Gadgets\MSDNSample.gadget\” /y /s /q /EXCLUDE:exclude.txt

cd “%LOCALAPPDATA%\Microsoft\Windows Sidebar\Gadgets\MSDNSample\”
cabarc -r -p n “%HOMEPATH%\Documents\MSDNSample.gadget” *
This uses the Cabarc.exe utility to generate a CAB file. (Cabarc.exe is a free Microsoft tool that is installed with Visual Studio. It’s also available separately as part of the Cabinet SDK, which you can download from support.microsoft.com/kb/310618.)
From within Visual Studio 2005, I run make.bat, which I have set up as an external tool. The batch file creates a folder under the user gadgets folder (which is where gadgets are created when installed) and copies all of the gadget files into the new folder. My batch file also generates a .gadget file that is ready for distribution and places it in the Documents folder. When you use this method, there is no need to double-click on the .gadget file to install the gadget on your development machine. I love the technique as it allows me to keep other source files in my Visual Studio project folder (such as Photoshop PSD files) that I don’t want to package with the gadget. If you do this, just be sure to place the names of the files you want to exclude in the exclude.txt file.

The MSDN Magazine Ticker

Now that I’ve covered all the basic components of a gadget, I’d like to present a sample gadget that pulls all the parts together. The MSDN Magazine Ticker gadget is available as a download so you can install it or simply explore its contents.
I wanted my sample gadget to use all of the major features of a Sidebar gadget (flyouts, docked versus floating states, options, localization, and so on). But I also wanted the sample gadget to be simple. And it had to be somewhat useful. Read complete here (Actual Source)

 

 

Download our free tools bar to get latest update without even visiting our website.

untitled

Download it from here

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Archives

Blog Stats

  • 54,643 hits
%d bloggers like this: