Создание гаджетов для Windows Sidebar
Евгений, 9 марта 2009
Гаджеты отличное дополнение к веб-сайту или сервису, они могут сообщать пользователю о новых публикациях, сообщениях, письмах, показывать постоянно изменяющуюся информацию (курсы валют, погоду), ускорять регулярные действия пользователя. Гаджет — это небольшая веб-страница, поэтому его создание не требует от веб-разработчика значительных усилий или освоения новых технологий.
Содержание статьи:
- Hello World!
- Пример гаджета к статье
- Файлы гаджета
- Состояния гаджета: docked и undocked
- Фон
- Фоновый текст и изображения: g:text, g:image
- Настройки
- Flyout
- Протокол gimage
- Локализация
- Особенности
- Отладка
- Юзабилити гаджетов
- Безопасность
- Распространение и установка
- Ссылки
Hello World!
По старой традиции начнем с создания гаджета Hello World!
Создайте два файла:
gadget.xml — манифест гаджета
<?xml version="1.0" encoding="utf-8" ?>
<gadget>
<name>Hello World!</name>
<version>1.0</version>
<hosts>
<host name="sidebar">
<base type="HTML" apiVersion="1.0.0" src="gadget.html" />
<permissions>full</permissions>
<platform minPlatformVersion="0.3" />
</host>
</hosts>
</gadget>
gadget.html — основной файл гаджета
<!DOCTYPE html>
<html>
<head>
<title></title>
<style>
body {
width: 130px;
height: 30px;
}
</style>
</head>
<body>
<p>Hello World!</p>
</body>
</html>
Запакуйте их в zip архив с расширением gadget.

Это и есть дистрибутив гаджета. Устанавливайте.

После установки гаджет автоматически добавляется на сайдбар.

Убедившись в простоте создания гаджета, перейдем к деталям.
Пример гаджета
Все описанное в статье собрано воедино в примере ExampleGadget.
Файлы гаджета
Пользовательские гаджеты находится в директории %USERPROFILE%AppDataLocalMicrosoftWindows SidebarGadgets
Простейший гаджет состоит из двух файлов, манифеста и основного, находящихся в поддиректории GadgetName.gadget.
Подробный манифест включает информацию об авторе, описание, иконку и изображение, видимое при его перетаскивании на сайдбар:
<?xml version="1.0" encoding="utf-8" ?>
<gadget>
<name>Пример гаджета</name>
<version>1.0</version>
<author name="Евгений Абашкин">
<info url="designformasters.info" />
</author>
<copyright>2009</copyright>
<description>Гаджет для Windows Sidebar</description>
<icons>
<!-- Иконка гаджета -->
<icon width="128" height="128" src="icon.png" />
</icons>
<hosts>
<host name="sidebar">
<!-- имя и тип стартового файла гаджета -->
<base type="HTML" apiVersion="1.0.0" src="main.html" />
<permissions>full</permissions>
<platform minPlatformVersion="0.3" />
<!-- Изображение видимое при перетаскивании гаджета на сайдбар -->
<defaultImage src="images/dockedBg.png" />
</host>
</hosts>
</gadget>
HTML в основном файле гаджета практически ничем не отличается, от кода обычной веб-страницы.
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link rel="stylesheet" type="text/css" href="main.css">
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="locale.js"></script>
<script type="text/javascript" src="localize.js"></script>
<script type="text/javascript" src="main.js"></script>
</head>
<body id="main">
<g:background id="background" style="position:absolute;z-index:-1;top:0;left:0;"></g:background>
<div id="gadgetContent">
<p><a id="toggle-flyout" href="#"></a></p>
<div id="systemData">
<p><span id="CPU"></span>%</p>
<p><span id="memory"></span> <span localize="megabyte"></span></p>
</div>
</div>
</body>
</html>
Состояния гаджета: docked и undocked
У гаджетов есть два состояния docked и undocked. Максимальная ширина docked гаджета 130px, для undocked нет ограничений, рекомендуется не превышать 400px. Текущее состояние гаджета отражает переменная System.Gadget.docked, а при его изменении происходит событие System.Gadget.onUndock или System.Gadget.onDock. В обработчике изменения состояния нужно задать размеры body. Изменение класса body позволяет удобно управлять отображением внутренних элементов.
function dockStateChanged() {
if (System.Gadget.docked) {
$(document.body).removeClass('undocked')
.addClass('docked')
.css('width', '130px')
.css('height', '145px');
// ...
} else {
$(document.body).removeClass('docked')
.addClass('undocked')
.css('width', '260px')
.css('height', '240px');
// ...
}
}
Фон
Фон гаджета задается с помощью элемента
g:background:
<body>
<g:background id="background" style="position:absolute;z-index:-1;top:0;left:0;">
</g:background>
<div id="gadgetContent">
</div>
</body>
Существует альтернативный способ задать фоновое изображение, через свойство
System.Gadget.background, но тогда объект g:background не будет
представлен в DOM.
Большинство гаджетов используют разное фоновое изображение для docked и undocked
состояний, изменение изображения и размеров фона происходит в функции
dockStateChanged.
function dockStateChanged() {
if (System.Gadget.docked) {
// ...
$('#background').css('width', '130px')
.css('height', '145px')
.attr('src', 'images/dockedBg.png');
} else {
// ...
$('#background').css('width', '260px')
.css('height', '240px')
.attr('src', 'images/undockedBg.png');
}
}
К фону могут быть применены эффекты, например, тень:

$('#background').get(0).addShadow("black", 20, 80, 5, 5);
Эффекты несколько замедляют работы гаджета, но иногда могут быть полезны.
Фоновый текст и изображения: g:text, g:image
Элементы g:text и g:image добавляют текст или изображение к фоновому слою гаджета. Создать их можно с помощью методов addImageObject и addTextObject объекта g:background:
var background = $('#background').get(0);
var text = background.addTextObject('rotation', 'Arial', 25, 'white', 10, 10);
var image = background.addImageObject('images/arrow.png', 10, 10);
Также как и к фону, к этим элементам можно применить эффекты, например, blur и rotation:

Несмотря на то, что их можно создать и в HTML, такие объекты не будут обладать всей присущей им функциональностью.
Настройки
Сохранить и получить параметры гаджета можно с помощью методов System.Gadget.Settings.writeString, System.Gadget.Settings.readString.
System.Gadget.Settings.writeString('uri', 'http://designformasters.info/');
var uri = System.Gadget.Settings.readString('uri');
Ключи должны быть короче 1024 символов, а значения 2048 символов, значения длиннее урезаются.
Параметры сохраняются при перезапуске сайдбара или компьютера, но удаляются при закрытии гаджета. Чтобы сохранять настройки гаджета при его удалении с сайдбара или хранить больше данных, чем позволяет сайдбар, используйте файлы (библиотека Persistent Settings упрощает работу с файлами настроек).
Страница настроек
Чтобы включить страницу настроек, нужно указать файл с ее разметкой:
System.Gadget.settingsUI = 'settings.html';
После этого на тулбаре гаджета появиться пиктограмма, клик на которой открывает настройки гаджета.
При закрытии окна настроек вызывается обработчик события System.Gadget.onSettingsClosed:
System.Gadget.onSettingsClosed = settingsClosed;
function settingsClosed(e) {
if (e.closeAction == e.Action.commit) {
//читаем и применяем настройки
}
}
Пример скрипта для окна настроек:
function settingsClosing(event) {
if (event.closeAction == event.Action.commit) {
// убираем выделение ошибок
$('.error').removeClass('error');
var backgroundOpacity = parseInt($('#backgroundOpacity').val());
if(isNaN(backgroundOpacity) || backgroundOpacity > 100 || backgroundOpacity < 0) {
// если backgroundOpacity не число от 0 до 100
// отменяем закрытие окна настроек
event.cancel = true;
// показываем ошибку
$('#backgroundOpacity').parent().addClass('error');
}
// если не было ошибок сохраняем значения
if(!event.cancel) {
System.Gadget.Settings.writeString('backgroundOpacity', backgroundOpacity);
// ...
}
}
}
function main() {
System.Gadget.onSettingsClosing = settingsClosing;
// считываем старые значения настроек и показываем их в форме
$('#backgroundOpacity').val(System.Gadget.Settings.readString('backgroundOpacity'));
// ...
}
$(document).ready(main);
Ширина страницы настроек не более 300px, а высота не ограничена (рекомендуется не превышать размеры 278x400px).
Flyout
Флайаут это дополнительная страница позволяющая расширить интерфейс гаджета. За работу с флайаутом отвечает объект System.Gadget.Flyout.
Флайаут для состояния undocked:

Флайаут для состояния docked:

Так же как и для страницы настроек, для флайаута нужно указать файл разметки:
System.Gadget.Flyout.file = 'flyout.html';
Отображением управляет свойство System.Gadget.Flyout.show.
При открытии и закрытии флайаута происходят события System.Gadget.Flyout.onShow и System.Gadget.Flyout.onHide соответственно.
Документ флайаута доступен через свойство System.Gadget.Flyout.document,
основной документ гаджета доступен из флайаута через свойство
System.Gadget.document. Поскольку флайаут может исчезнуть в любой
момент, работа с ним из основного документа гаджета может привести к ошибкам.
Пример работы с флайаутом:
function onFlyoutShow() {
$('#toggle-flyout').text(strings.hideFlyout);
try {
var fd = System.Gadget.Flyout.document;
fd.getElementById('header').innerHTML = strings.flyoutHeader;
fd.getElementById('description').innerHTML = strings.flyoutDescription;
} catch (e) {
}
}
function onFlyoutHide() {
$('#toggle-flyout').text(strings.showFlyout);
}
function initFlyout() {
// указываем файл флайаута
System.Gadget.Flyout.file = 'flyout.html';
System.Gadget.Flyout.onShow = onFlyoutShow;
System.Gadget.Flyout.onHide = onFlyoutHide;
$('#toggle-flyout').text(strings.showFlyout);
// открываем и закрываем флайаут
$('#toggle-flyout').get(0).onclick = function() {
System.Gadget.Flyout.show = !System.Gadget.Flyout.show;
return false;
}
}
Чтобы изменять вид флайаута в зависимости от состояния гаджета меняем класс элемента body, сделать это нужно до того как флайаут отрендерится (фон и рамка не обновляются если изменены после отображения флайаута).
<body id="flyout" class="undocked">
<script type="text/javascript">
document.body.className = System.Gadget.document.body.className;
</script>
<div id="content"><div>
</body>
Протокол gimage
Протокол gimage позволяет эффективно получать превью изображений (пытается использовать кеш превью Windows для изображений меньше 256x256px).
Желаемый размер превью должен быть указан в запросе с помощью параметров width и height, если параметры не указаны, то они считаются равными 120, пропорции изображения сохраняются.
<img src="gimage:///c:garden.jpg?width=80&height=80">

Для файлов не являющихся изображениями gimage позволяет получить иконки.
function addIcons() {
var files = [
System.Gadget.path + '\\gadget.xml',
System.Gadget.path + '\\main.html',
System.Gadget.path + '\\main.css',
System.Gadget.path + '\\main.js',
'C:\\Windows\\System32\\calc.exe',
'C:\\Program Files\\Windows Sidebar\\sidebar.exe'
];
var icons = $('#icons').get(0);
for(var i in files) {
var icon = new Image();
icon.src = 'gimage:///' + files[i] + '?width=32&height=32';
icons.appendChild(icon);
}
}
![]()
Несмотря на схожесть в названиях протокол gimage никак не связан с элементом g:image.
Локализация
Гаджеты поддерживают механизм локализации по папкам, т.е. при открытии любого ресурса (манифест, html, css, js, image) сайдбар ищет его в папках в следующем порядке:
- Локаль полностью (en-us, es-us, ja-jp)
- Языковая часть локали (en, es, ja)
- Корневая папка гаджета
Чтобы не хранить несколько версий каждого файла, отличающиеся только языком, создадим файл, содержащий определения строк и других локальных ресурсов, и будем подключать его в каждом файле, где они потребуются.
locale.js
var strings = {
about: 'Gadget page',
aboutTitle: 'En',
aboutHref: 'http://designformasters.info/'
}
В скрипте вместо строк используются соответствующие элементы strings:
if(html == '') throw strings.dataError;
В html элементам требующим замены, зададим атрибут localize с именем строки из массива strings, а для локализации атрибутов будем использовать формат attrName:stringName:
<div id="about"><p><a localize="about,href:aboutHref,title:aboutTitle"></a></p></div>
В результате преобразования нам нужно получить:
<p><a href="http://designformasters.info/" title="En">Gadget page</a></p>
JQuery позволяет быстро реализовать такую локализацию:
$(document).ready(function localize() {
$('*[localize]').each(function() {
var localize = $(this).attr('localize');
if(localize != '') {
var list = localize.split(',');
for(var i = 0, c = list.length; i < c; i++) {
var parts = list[i].split(':');
if(parts.length == 1) {
$(this).html(strings[parts[0]]);
} else {
$(this).attr(parts[0], strings[parts[1]]);
}
}
}
});
});
Сохраним этот код в localize.js и подключим после скрипта locale.js
в файлах требующих локализации.
<script type="text/javascript" src="locale.js"></script>
<script type="text/javascript" src="localize.js"></script>
В корневой папке гаджета обязательно должны быть файлы локали по умолчанию, иначе его невозможно использовать в локали для которой нет локализованных файлов.
Особенности
alarm и confirm
В гаджетах эти функции не работают, но хороший интерфейс и не предполагает их использования.
onclick
Обработчик click не добавляется методами:
element.attachEvent('onclick', function(){})
$(element).bind('click', function(){})
используйте свойство onclick:
element.onclick = function(){}
$(element).get(0).onclick = function(){}
Скорее всего, это связано с обработчиком перетаскивания гаджета. Если задан element.onclick то за этот элемент гаджет уже не перетаскивается.
Отладка
Гаджет можно отлаживать с помощью Visual Studio. Для этого нужно разрешить использование отладчиков в настройках Internet Explorer.

Добавить в нужном месте кода гаджета строку:
debugger;
и перезапустить гаджет.

Юзабилити гаджетов
Гаджет стоит использовать для отображения важной и регулярно обновляющейся информации, или для функционала, который часто требуется пользователю.
Информация, которую отображает гаджет, должна быть доступной для периферического зрения, но не должна отвлекать внимание от повседневных задач.
Не нужно стремиться к универсальности лучше оптимизировать гаджет для единственной задачи.
Графическое оформление должно быть привлекательным и отражать задачу гаджета.
Интерфейс гаджета должен быть привычным для Windows пользователя.
Юзабилити гайдлайн по гаджетам
Безопасность
Гаджеты могут использовать любые установленные ActiveX объекты (но не могут их устанавливать) и получать доступ к любому домену. К файлам и приложениям гаджет получает доступ с правами пользователя, от имени которого запущен (за исключением администратора в Windows Vista). К установке гаджетов следует относиться не менее ответственно, чем к установке приложений.
Gadgets for Windows Sidebar Security
Распространение и установка
Установочный файл гаджета, это zip архив с расширением gadget. При запуске такого файла
сайдбар распакует его в папку пользовательских гаджетов
%USERPROFILE%AppDataLocalMicrosoftWindows SidebarGadgets. Гаджеты, доступные всем пользователям компьютера, находятся в папке %SYSTEM_ROOT%Program FilesWindows SidebarGadgets.
Кроме zip, можно использовать форматы cab и msi.
Чтобы гаджет устанавливался кликом по ссылке, mime-тип файлов .gadget должен быть application/x-windows-gadget:
AddType application/x-windows-gadget .gadget


Спасибо за такой материал - вкусно ^_^
А в W7 заработает?
Не проверял, но со стороны MS было бы глупо отказаться от совместимости с множеством готовых гаджетов.
Спасибо интересный материал, все хотел занятся этим делом а тут такая статья полезная :)
У меня пару гаджетов на W7 не заработало.
Цитаты оформлены не удачно разбили комментарий на два :(
в W7 работает так же как и в Vista - проверял лично
Принимается. Сделал попроще.
Каких? По какой причине?
Нужно страницу index.html перевести в Unicode и тогда будет работать в W7.
Материал действительно отличный. Спасибо большое! Вместе собрана все необходимая информация, да и еще переведена.
Добавлю от себя:
Таблицы стилей для страниц должны лежать в корне гаджета.
Скрипты и изображения могут лежать в подкаталогах.
Если нет нужды в эффектах, то вместо g:background можно просто использовать CSS body { background: };
Не обязательно, могут и в подкаталогах.
Я точно не помню но какие то связанные со системой. Всего скорей разработчики напортачили с недокументированными функциями.
Вот сотворил Хабра гаджет :)
У кого есть локальный мсдн -
ms-help://MS.MSDNQTR.v90.ru/sidebar/sidebar/overviews/gdo.htm
Открылась только, версия en версия:
ms-help://MS.MSDNQTR.v90.en/sidebar/sidebar/overviews/gdo.htm
Статья очень хорошая. Не могли бы прояснить как гаджет настроить на работу через локальный прокси-сервер с авторизацией.
Не пробовал, но скорее всего там HTTP авторизация,
нужно указать логин и пароль в ajax запросах
request.open(method, URL, async, login, password)в jQuery нужно
usernameиpasswordустанавливатьhttp://docs.jquery.com/Ajax/jQuery.ajax#options
Кто может подсказать еще ссылки по этой теме, можно и на зарубежные сайты, покуда покопался по сайту мелкософта, ничего путного толком не нашел, или к примеру был бы признателен автору сайта за разбор уже собранного гаджета(допустим на примере GisMeteo). Думаю это многим бы пригодилось.
Отличная статья, спасибо большое! Намного больше информации, чем в русскоязычных статьях схожей тематики, которые я видел до этого.
Спасибо, невероятно полезная статья! Только интересует один вопрос - как настроить смену фонового рисунка в зависимости от времени суток? Нигде ничего по этому поводу не нашел. Нужно 4 стостояния - утро, полдень, вечер и ночь.
Посмотри гаджет Центр Погоды (weathercenter.narod2.ru)
В нем меняется фон день на ночь... вот и узнаешь как, а на четыре состояния принцип тотже.
>_< эх где вы были раньше... Такой подробный help... а я все скаблил и скаблил по нету
Столкнулся с такой проблемой, когда текст на прозрачном фоне, он(текст) обводится розовым по контуру
Если мне не изменяет память, g:text должен корректно работать в таком случае, а обычный текст обводится розовым.
А у меня в Вин7 не открывается почему-то.. "неопознанная ошибка" и все тут.
Может кто сталкивался?
Сам спросил, сам отвечу..
Разархивировал Ваш файл без установки, переименовал в Example.Gadget, далее скопировал папку в C:\Program Files\Windows Sidebar\Gadgets
Спасибо за статью, очень интересно, познавательно, полезно!
Подскажите можно ли сделать из swf гаджет для Windows 7 ?
Интересует тот же вопрос, можно ли объект swf вставить в код? и какой должен быть синтаксис?
А как сделать так чтобы запускался ява апплет в гаджете?
Я гаджет сделал, рабоатет.
Добавляю апплет, тестирую через простое открытие в Explorer тоже работает.
Пакую все в файл с расширением gadget, устанавливаю на панель, что-то думает.
И... ничего, белый фон, чистая hTML страница.
Все параметры Explorer настроены так что окно с предупреждением безопасности не выдается Апплет запускается без проблем.
Как решить эту багу?
А кто может написать Гаджет под заказ?
[URL=http://radikal.ru/F/i061.radikal.ru/1008/04/82f10ebfbcd5.jpg.html][IMG]http://i061.radikal.ru/1008/04/82f10ebfbcd5t.jpg[/IMG][/URL] может кто нить видел гаджет типо таково, чтобы он отображал логотип проигрываемой станции????
p.s : помогите "знающие люди" с написанием gadgeta, охото такой гаджет а знаний мало в этой области!!!
Создал гаджет упаковал в архив, но дальше про Неизвестного издателя не идет. Ваш example гаджет устанавливается.... думал, что-то в моих файлах, поэтому провел следующее тестирование:
распаковал ваш гаджет, запаковал обратно, попробовал установить - не работает
причем не выдает никаких ошибок...
С чем это связано? Может ли быть это связано с "подписью" центра сертификации?