上次在SideShow Gadget開發[1]中介紹了本地Gadget的開發,現在介紹一下正常Gadget的開發。
在介紹Gadget之前,我們先說一下我們認識上的一個誤區,很多開發人員認為正常Gadget和本地Gadget類似,是一個.Net Micro Framework應用程式(至少是一個DLL),在連接配接時,由PC端把該DLL下載下傳到Sideshow裝置上去,Sideshow主程式加載并運作該程式。我一開始也是這樣認為的,但是随着開發的深入,對Sideshow的運作機理也越來越了解,其實正常Gadget更像一個網頁應用,普通的網頁浏覽基于http協定,而Gadget基于SCF(Simple Content Format,目前sideshow支援兩種協定,另一種是ICAL,在Sideshow中不稱為通信協定,專業術語是endpoint)協定,此時的Gadget更像一個網頁,而Sideshow裝置更像一個IE用戶端。
從以上描述,你就會明白了,其實沒有什麼DLL,對于Sideshow裝置來說僅有一些基于SCF格式的資料流而已。
是以開發正常Gadget理論上不拘于什麼開發語言,隻要能輸出符合SCF格式的資料流即可。不過這裡還是推薦使用C#(或基于.NET開發平台開發語言),可以直接引用相關開發庫,非常簡單的生成符合SCF格式的界面要素。
下面先“秀”一下我們已經開發好的圖檔浏覽Gadget,然後再介紹一下是如何開發的。
1、 安裝後,會在Sideshow控制台上出現如下圖示

5、顯示圖檔,也可以通過listbox進行選擇
下面簡單介紹一下相關代碼:
1、 兩個GUIO
一個是Gadget的GUID,Sideshow管理程式通過這個GUID加載相對應的Gadget。
一個是該Gadget對應的屬性頁的GUID(在代碼中,屬性頁其實就是一個辨別了GUID的控件,該控件派生于Microsoft.SideShow.GadgetPropertyPage),Sideshow管理程式加載并顯示屬性對話框。
注意:在注冊時,一定保證VS2008或相關程式具有管理者權限,否則操作系統資料庫會失敗。
2、 注冊代碼
GadgetRegistration.Register
(
false, //true 對全部使用者有效 false 對目前使用者有效
GadgetId, //本gadget的ID
ScfSideShowGadget.ScfEndpointId, //内容端點,需要使用SCF
"Picture Share", //SideShow控制台中顯示的名字
"/"" + Assembly.GetEntryAssembly().Location + "/"", //程式所在的路徑
String.Format("/"{0}/",{1}", Assembly.GetEntryAssembly().Location, -GadgetRegistration.DefaultIconResourceId), //程式圖示位置
false, //True 連接配接時才顯示内容,false 不用連接配接也能顯示内容
GadgetCachePolicies.KeepNewest, //接收消息項的政策 KeepNewest保留最新 KeepOldest保留最老 KeepFrequentlyAccessed保留最頻繁 KeepRecentlyAccessed保留最近以前沒有收到的消息
new Guid("9B84055E-E253-4119-8719-F684ECB9FBC1") //屬性頁ID
);
3、 事件設定
YFGadget = new Microsoft.SideShow.SimpleContentFormat.ScfSideShowGadget(new Guid(GadgetEntry.Gadget_GUID));
#region Listen to SideShow Events
// Subscribe to events from the Windows SideShow platform.
YFGadget.AllDevicesRemoved += new System.EventHandler(OnAllDevicesRemoved);
YFGadget.ContentMissing += new System.EventHandler<Microsoft.SideShow.ContentMissingEventArgs>(OnContentMissing);
YFGadget.ContentNavigate += new System.EventHandler<Microsoft.SideShow.SimpleContentFormat.ContentNavigateEventArgs>(OnContentNavigate);
YFGadget.ContextMenuSelect += new System.EventHandler<Microsoft.SideShow.SimpleContentFormat.ContextMenuSelectEventArgs>(OnContextMenuSelect);
YFGadget.DeviceAdded += new System.EventHandler<Microsoft.SideShow.DeviceCapabilityEventArgs>(OnDeviceAdded);
YFGadget.DeviceRemoved += new System.EventHandler<Microsoft.SideShow.DeviceCapabilityEventArgs>(OnDeviceRemoved);
YFGadget.GadgetEnter += new System.EventHandler(OnGadgetEnter);
YFGadget.GadgetExit += new System.EventHandler(OnGadgetExit);
YFGadget.MenuSelect += new System.EventHandler<Microsoft.SideShow.SimpleContentFormat.MenuSelectEventArgs>(OnMenuSelect);
#endregion
4、傳送圖檔、菜單等
//枚舉目前路徑下的所有圖檔
string[] strPath = Directory.GetFiles(SharePath);
List<string> strImgPath = new List<string>();
foreach (string path in strPath)
{
if (path.Length > 3)
{
switch (path.Substring(path.Length - 3).ToLower())
{
case "jpg":
case "bmp":
case "gif":
strImgPath.Add(path);
break;
}
}
}
List<ScfElement> item = new List<ScfElement>();
for (int i = 0; i < strImgPath.Count; i++)
{
FileInfo fi = new FileInfo(strImgPath[i]);
Bitmap bmp = new Bitmap(fi.FullName);
PageNo = i + 1;
PicNo = 10000 + i + 1;
bmp = new Bitmap(bmp, 240, (int)(240 * ((float)bmp.Height / bmp.Width)));
YFGadget.AddContent(PicNo, ImageContentTransforms.ReduceColorDepth, bmp); // | ImageContentTransforms.KeepAspectRatio| ImageContentTransforms.KeepAspectRatio
ScfElement content = Scf.Content(
PageNo,
fi.Name,
200,
Scf.Img(PicNo, ScfAlign.Center, ScfImageFit.Native, fi.Name),
Scf.Txt(ScfAlign.Center, false, Color.Black, "", "<< " + PageNo.ToString() + "/" + strImgPath.Count.ToString() + " >>"),
Scf.Btn(DeviceButton.Left, "", PageNo - 1 == 0 ? strImgPath.Count : PageNo - 1),
Scf.Btn(DeviceButton.Right, "", PageNo + 1 > strImgPath.Count ? 1 : PageNo + 1),
Scf.Btn(DeviceButton.Back, "", 100)
);
item.Add(Scf.Item(PageNo, fi.Name));
YFGadget.AddContent(content);
bmp.Dispose();
}
YFGadget.AddContent(Scf.Menu(
100,
"Main Menu",
ScfSelectAction.Target,
item.ToArray()
));
YFGadget.AddContent(Scf.Menu(
200,
"Right Menu",
ScfSelectAction.Target,
Scf.Item(100, "主菜單")
));
由于SDK提供了相關SCF操作函數,是以我們就沒有必要寫原始的XML格式的檔案了。
OK,由于網上已有一些詳細介紹Gadget編寫的文章,是以我這裡也就不啰嗦了。如有必要,可以給我留言,我們可以進一步交流Gadget編寫技巧。