在Windows Media Center中实现通知功能

在家庭的任何房间中,无论是作为家庭电脑还是增强家庭影院体验,Windows Media Center都能提供最佳的Windows体验。它集成了包括照片、音乐、电视等在内的家庭娱乐体验。通过连接家中和外出的设备,可以扩展娱乐体验。如果希望将应用程序集成到这种新的用户体验中,可能希望扩展现有的应用程序,以便在用户可能正在PC上观看电视时向用户显示通知。本文描述了一种向用户显示带有图像的通知的简单方法。

微软并没有在Media Center UI中直接添加从外部应用程序显示通知的方式,但他们提供了另一种可能的方式:可以向Media Center添加“背景插件”,这些插件将在Media Center UI运行时一直运行,并使用它来接收“外部世界”的消息。本文展示了如何使用这些背景插件向用户显示消息。

Michael Creasy在他的博客中描述了如何开发这些背景插件。可以在那里找到一个背景插件的基本示例。为了与正在运行的Media Center插件进行通信,使用了简单的WM_COPYDATA来发送要显示的文本和其他信息到插件。虽然有几种方式可以在两个不同的应用程序之间进行通信,但如果程序的部分是用不同的编程语言开发的,这种方式是最简单的。

组件和流程概览

为了概述所有组件和流程,准备了这个流程图:

使用代码

示例由两个独立的部分组成:

  • 一个简单的Visual Basic 6程序,展示了如何使用WM_COPYDATA向Media Center插件发送一些信息。
  • 一个Media Center 2005的背景插件,当Media Center启动时自动加载,并监听传入的WM_COPYDATA消息,使用Media Center API函数显示包含的文本。

在背景插件中的“技巧”是不仅仅从微软建议的基类派生这个插件(IAddInModule、IAddInEntryPoint、IDisposable),还从System.Windows.Forms.NativeWindow派生。这为提供了一个窗口句柄来挂钩并监听发送到这个窗口的任何Windows消息,并过滤WM_COPYDATA:

protected override void WndProc(ref Message m) { if (m.Msg == WM_COPYDATA) { ... } base.WndProc(ref m); }

但是仅仅创建一个窗口句柄只是一半的工作:这个窗口必须被消息发送者找到。所以给这个不可见的窗口一个非常独特的窗口标题:

public mceDialogAddIn() { // Creating Window based on globally known name, and create handle so we can start listening to Window Messages. CreateParams Params = new CreateParams(); Params.Caption = ""; this.CreateHandle(Params); }

这确保了可以使用FindWindow在MessageSender中找到这个窗口:

' Get TargetWindow handle hwndTarget = FindWindow(vbNullString, "") If (hwndTarget = 0) Then ' MCE addin-window not found Exit Function End If

VB 6中的消息发送者有一个重要功能,使用SendMessage将消息发送到插件:

Dim uCopyData As COPYDATASTRUCT Dim sData As String Dim strDelim As String strDelim = "|" ' build string to send ' single parameters are separated by "|" ' the parameters: ' [0] = caption ' [1] = text to show ' [2] = image to display ' [3] = hide dialog automatically after these seconds sData = strCaption & strDelim & strText & strDelim & _ strImage & strDelim & intAutoHide & strDelim ' Fill up the structure With uCopyData .cbData = LenB(sData) .lpData = StrPtr(sData) End With Call SendMessage(hwndTarget, WM_COPYDATA, 0, uCopyData) ' hwndTarget is the window handle of the invisble ' Media Center addin window

为了简单起见,插件的数据只是用“|”分隔。这样做,可以在插件接收到数据时将其分割:

if (m.Msg == WM_COPYDATA) { // arguments are delimited by "|". // the argument in order: // [0] = caption // [1] = text to show // [2] = image to display // [3] = hide dialog automatically after these seconds COPYDATASTRUCT st = (COPYDATASTRUCT) Marshal.PtrToStructure(m.LParam, typeof(COPYDATASTRUCT)); string strData = Marshal.PtrToStringUni(st.lpData); string strDelim = "|"; string[] args = strData.Split(strDelim.ToCharArray()); int intTimeOut = Int32.Parse(args[3]); string strImage = args[2].Replace("\\", "\\\\"); if (!File.Exists(strImage)) // if image does not exist, // do not pass to Dialog or it will not show up strImage = ""; ... }

现在已经得到了想要的数据:在Media Center GUI的过程中。因为这个插件有对Microsoft.MediaCenter的引用,可以通过插件访问Media Center API。但是没有直接的方法从插件的某个点显示MCE风格的MessageBox... MessageBox函数在Media Center API中有一个类似的函数,即HostControl.Dialog(详见MSDN)。所以需要一个HostControl的句柄。一个HostControl的引用在函数void IAddInEntryPoint.Launch(AddInHost host)中传递到插件中。这个函数在Media Center启动插件时被调用。所以所要做的就是保存这个host的引用,以便以后使用它来显示Dialog:

void IAddInEntryPoint.Launch(AddInHost host) { mhcControl = host.HostControl; ... } protected override void WndProc(ref Message m) { if (m.Msg == WM_COPYDATA) { ... Object[] oButtons = new Object[1]; oButtons[0] = 1; // just an OK button mhcControl.Dialog(args[1], args[0], oButtons, intTimeOut, false, strImage, null); // mhcControl is our saved reference to a HostControl } base.WndProc(ref m); }

要点

一个非常重要的一点是,当执行离开IAddInEntryPoint.Launch函数时,背景插件将被Media Center卸载。所以如果希望插件保留在内存中(例如,等待像这样的特定消息),必须在Launch函数中“持有”执行,并且只有在想要被卸载时才将其返回给Media Center进程:

void IAddInEntryPoint.Launch(AddInHost host) { ... while (true) { // Yield processing till we sample for inactivity // if we let the execution exit "Launch", // the addin will be unloaded // and is then unable to get messages... Thread.Sleep(100); System.Windows.Forms.Application.DoEvents(); } }
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485