Converting to a Vista Gadget
The next step is to convert it to a Vista gadget. This step is actually the easiest of all. In the same folder, create a new file called Gadget.xml, open it in Notepad, and paste the following into it:
<?xml version="1.0" encoding="utf-8" ?>
<gadget>
<name>Guitar Tuner</name>
<namespace>GuitarTuner</namespace>
<version>1.0</version>
<author name="[Your Name here]">
</author>
<copyright>2007</copyright>
<description>Guitar Tuner for tuning by ear</description>
<icons>
</icons>
<hosts>
<host name="sidebar">
<base type="HTML" apiVersion="1.0.0"
src="GuitarTuner.html" />
<permissions>full</permissions>
<platform minPlatformVersion="0.3" />
</host>
</hosts>
</gadget>
Make sure that when you save it, do a "save as" and ensure you select the encoding as UTF-8. This is very critical; otherwise, the gadget will not be recognized as a valid gadget by Vista. Actually , that is all there is to convert it to a gadget because the gadget framework also is an application hosting a browser for each gadget and thus, if you have a HTML page working, you pretty much have got it working in the gadget.
The only thing you need to work on now is to make the gadget compliant with the gadget development guidelines and make it look pretty and behave normally. Have a look at the Vista gadget UI guidelines.
I think you have addressed the following well:
- Guideline says, A good gadget provides functionality that is useful all the time. I think your tuner gadget does it well. It is a useful gadget for those who install it.
- Guideline says, An effective gadget works well in the periphery. You will address this soon. But overall, you are in the right direction in that you don't distract users if not in use (provision for stopping media and animation when done with tuning)
- Guideline says, A great gadget does a single, well-defined task very well. Again, you are on the right track. It helps in tuning and that's it. No more frills.
- Guideline says, The best gadgets use a visual theme that suitably indicates their singular task. Again, I think you have done it right. You have the representation of a guitar body and the strings.
The one thing you need to do is to restrict the size of the gadget in docked state. You do this for now by specifying the size of the body element in the GuitarTuner.HTML like below:
<head>
<title>Guitar Tuner</title>
<style>
body
{
width: 130px;
height: 130px;
margin: 0px;
font-size:11px;
font:10px segoe ui,tahoma;
}
</style>
<script type="text/javascript" src="Silverlight.js"></script>
<script type="text/javascript" src="guitartuner.js"></script>
</head>
This puts you in compliance with gadget guidelines.
If you have been using gadgets on Vista, you would know that a gadget could either be docked to the sidebar, or it could undocked. Microsoft guidelines recommends a 130px X 130px size for docked gadgets, but for undocked ones, the restrictions are little more lenient. Microsoft recommends a 400px X 400px size in the undocked state.
A 130px by 130px size is pretty restrictive; all you can fit in there is 6 strings. However, with a 400px X 400px square area, you could do much more. One of the pushes for gadget developers is to make the gadgets look cool. So, I just thought it would be cool if, in the undocked state, you could show the curved shape of a guitar body.
So, how do you know when this docking and undocking happens? Gadgets can listen to these events by registering handlers. This is part of the Vista gadget API. One just has to register to these notifications and do the necessary in those handlers. You register these handlers when the body is loaded and, in the handler, you change the body size from 130 to 400 depending on the state. I hope the code below is self explanatory.
In GuitarTuner.HTML, do the changes like below:
<script type="text/javascript" src="guitartuner.js"></script>
</head>
<script type="text/javascript">
function loadMain()
{
System.Gadget.onDock = dockStateChanged;
System.Gadget.onUndock = dockStateChanged;
}
function dockStateChanged()
{
if(System.Gadget.docked)
{
document.body.style.width = "130px";
document.body.style.height = "130px";
}
else
{
document.body.style.width = "400px";
document.body.style.height = "290px";
}
}
</script>
<body onload="loadMain()">
<div id="SilverLightControlHost">
This will ensure that the sizes stretch accordingly. You now need a guitar body shape for the gadget. I do this by setting a proper background image for the body. The background image is BKGND.png in the media zip file in the downloads section. Change the style in the HTML like below:
<style>
body
{
width: 130px;
height: 130px;
margin: 0px;
font-size:11px;
font:10px segoe ui,tahoma;
background-image:url(bkgnd.png);background-repeat:no-repeat;
}
</style>
Open the guitarTuner.js file and change the background color to white as shown below:
inplaceInstallPrompt:false,
background:'#00000000', // Background color of plugin.
isWindowless:'true', // Determines whether to display plugin
If you were to launch the HTML now, you would see something like below:

Not good. The location is not right. The background image needs to be pushed a little to the left and top. So, you add this to the body style.
background-image:url(bkgnd.png);
background-position: -80px -70px;
background-repeat:none;
There is another challenge with these positions that will come up. In the docked state, the background image needs to be moved as you did. If you did that, the strings and so forth are in the right location with respect to the guitar body shape.
In the undocked state though, you need to do the opposite. You need to bring the background image's left-top to align with the body's left-top. So, you need to set the position of the background image to 0 , 0. Also, now that image has shifted, so should the strings and the rest. You have to do this for all elements; this is tedious. Is there a simpler way? Yes, of course. If you remember, when I started off explaining the canvas and so on, I mentioned that a canvas itself can hold another canvas. This is a boon. What you could do is simply put all the elements into a canvas which in turn is an element of the root canvas. You then have to just move the child canvas and automatically, all the elements within it are moved.
These are the changes for what I discussed.
<Canvas xmlns="http://schemas.microsoft.com/winfx/2006/xaml/
presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="400" Width="290" >
<Canvas x:Name="MainDrawing" Canvas.Left="0" Canvas.Top="0"
Height="130" Width="130" >
<MediaElement x:Name="sound" Width="0" Height="0"
MediaEnded="endofmedia"/>
.....
</Canvas>
</Canvas>
You now handle the dockstatechanged to move these elements like below:
In GuitarTuner.HTML
function dockStateChanged()
{
if(System.Gadget.docked)
{
document.body.style.width = "130px";
document.body.style.height = "130px";
document.body.style.backgroundPosition = "-80px -70px";
document.getElementById("guitarTunerControl").content.
findName("MainDrawing")["Canvas.Left"]="0";
document.getElementById("guitarTunerControl").content.
findName("MainDrawing")["Canvas.Top"]="-10";
}
else
{
document.body.style.width = "400px";
document.body.style.height = "290px";
document.body.style.backgroundPosition = "0px 0px";
document.getElementById("guitarTunerControl").content.
findName("MainDrawing")["Canvas.Left"]="80";
document.getElementById("guitarTunerControl").content.
findName("MainDrawing")["Canvas.Top"]="70";
}
}
</script>
That's it. You are finally done. All that is pending is to install this gadget. The easiest way is to select all files (exclude media.zip file if there is one) in the folder (Ctrl-A), , right-click and select Send to-> Compressed (zipped) folder to zip up the contents of the GuitarTuner folder, and rename the zip extension to, say, GuitarTuner.gadget. (Make sure to zip up the contents only and not the folder itself.) Now, on a Vista machine, double-click on the GuitarTuner.gadget file. After confirmation, you should see the gadget and should be able to play around with the gadget. Check out undocking it and see how it looks.
References
Downloads
GuitarTuner.zip - Finished gadget files ( rename .zip to .gadget extension to install as Vista sidebar gadget )
media.zip - Media files ( media.zip )
* This article originally appeared on CodeGuru.