Click here to Skip to main content
Click here to Skip to main content

Show dialogs in Microsoft XP Media Center UI from an external application

, 8 Apr 2005 CPOL
Rate this:
Please Sign up or sign in to vote.
This article explains how to show dialogs in Microsoft's Windows XP Media Center UI from an external application.

Sample Image

Introduction

Windows XP Media Center Edition offers the best Windows experience in any room in your home, whether you’re looking for a family computer or to enhance your home theater. Enjoy integrated home entertainment experiences including photos, music, TV, and more. Connect with devices around the home, and on the go that extends your entertainment (see Microsoft's Media Center website for details).

If you want to integrate your application into this new user experience, you might want to expand your existing application to show a notification to the user who is probably just watching TV on the PC. This article describes a simple way to show a notification with an image to the user.

Background

Microsoft did not add a direct way to show notifications in the Media Center UI from an external application, but they made another way possible: you can add "Background Add-ins" to the Media Center which will run all the time the Media Center UI is running, and use it to receive messages from the "outer world". This article shows how to use these background add-ins to open a simple way to show a message to the user.

Michael Creasy describes how to develop these background add-ins. In his blog (see here) you can find a basic sample of a background add-in.

To communicate to this running Media Center add-in, I use a simple WM_COPYDATA to send the texts to show and other information to the add-in. There are several ways of communication between two different applications, but this way is the easiest one to use if your program parts are developed in different programming languages.

To give an overview of all the components and the flow, I have prepared this flowchart:

Using the code

The sample consists of two separate parts:

  1. A simple Visual Basic 6 program that demonstrates how to send some information to the Media Center add-in with WM_COPYDATA.

    The reason I chose VB 6 here is that this article has its roots in TapiRex, a shareware program I develop that shows CallerID on incoming calls, which also uses this technique to display a CallerID and some other information in the Media Center UI (see www.cbuenger.com for details).

  2. A background add-in for Media Center 2005 that is automatically loaded by the Media Center when it starts and which is listening to incoming WM_COPYDATA messages displays the containing texts with the Media Center API functions.

    This part has to be compiled with the .NET Framework 1.0, because Microsoft's Media Center only accepts add-ins to be in .NET 1.0. The source code contains a simple batch file that demonstrates how to compile the add-in without the Visual Studio IDE.

Let's get into the details: The "trick" in the background add-in is to derive this whole add-in not only from the base classes Microsoft proposes for add-ins (IAddInModule, IAddInEntryPoint, IDisposable) but also from System.Windows.Forms.NativeWindow. This gives us a window handle to hook on and listen for any Windows messages sent to this window and filter for WM_COPYDATA:

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

But just creating a window handle is only half way: this window has to be found by our MessageSender. So we just give this invisible window a very unique window title:

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 = "<? .: mceDialog.MessageServer :. ?>";
    this.CreateHandle(Params);
}

This ensures that we will find this window in our MessageSender using FindWindow:

'Get TargetWindow handle
hwndTarget = FindWindow(vbNullString, "<? .: mceDialog.MessageServer :. ?>")
If (hwndTarget = 0) Then
  ' MCE addin-window not found
  Exit Function
End If

The MessageSender in VB 6 has one important function, to send the message to the add-in using SendMessage:

Dim uCopyData As COPYDATASTRUCT
Dim sData As String
Dim strDelim As String
strDelim = "¦"

' build string to send
' single parameters are seperated 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

For simplicity, the data for the add-in is just separated by "¦". Doing this, we can split up the data when it is received by the add-in:

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 = "";

    ...
}

Now we have the data right where we wanted it: in the process of Media Center GUI. Because this add-in has a reference to Microsoft.MediaCenter, we have access to the Media Center API from our add-in. But there is no direct way to show a MCE style MessageBox from just some point in the add-in... The MessageBox-function has a similar function in Media Center API which is HostControl.Dialog (see MSDN for details). So we need a handle to a HostControl. A reference to a HostControl is passed in to the add-in in the function void IAddInEntryPoint.Launch(AddInHost host). This function is called when Media Center launches the add-in on start. So all we have to do is save this reference to host for later usage to show the 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);
}

Points of Interest

One very important thing to know is that a background add-in will be unloaded by Media Center when the execution leaves the IAddInEntryPoint.Launch function. So if you want an add-in to stay in memory (for example, to wait for specific messages like this one), you have to "hold" the execution in the Launch function and only give it back to the Media Center process if you want to be unloaded:

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();
    }
}

The call to DoEvents is just there to let the thread handle the WndProc function to get a chance to filter incoming messages.

More

This example only shows a one-way "communication" from an external application to a background add-in. If you want to let your application know which button in the dialog box was clicked by the user, you have to establish a connection back from the add-in to your application. This could be done the same way (with WM_COPYDATA) or in any other way you like.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Christoph Buenger
CEO Scavix Software Ltd. & Co. KG
Germany Germany
Scavix Software offers high quality software development and consulting. That's what customers like Intel, AMD, eBay and Sage Software trusted in the last 6 years. Be it on the desktop, in the web browser, on a mobile phone, on a tablet or on the TV: we can make your software visions come true.
Are you our next customer? Don't hesitate to contact us.
 
Imprint/Impressum: http://www.scavix.com/imprint/
Follow on   Twitter   Google+   LinkedIn

Comments and Discussions

 
GeneralSimilar Problem like Addin PinmemberMichael.F24-Jul-06 21:56 
GeneralRe: Similar Problem like Addin Pinmemberbenrjunk10-Jun-07 8:23 
I am experiencing the exact same problem. I'm a novice, so I was able to make changes to the VB6 messagesender for my own mods but I don't understand how to make the changes that Michael Creasy is suggesting on his blog to the addin itself. Could someone please help.
 
Thanks,
 
Ben
GeneralAdd-in getting unloaded after 10min PinmemberAddin15-Dec-05 13:25 
GeneralRe: Add-in getting unloaded after 10min PinmemberChristoph Buenger15-Dec-05 13:31 
GeneralRe: Add-in getting unloaded after 10min PinmemberAddin20-Dec-05 7:03 
GeneralRe: Add-in getting unloaded after 10min PinmemberChristoph Buenger20-Dec-05 9:51 
GeneralRe: Add-in getting unloaded after 10min PinmemberAddin4-Jan-06 13:19 
GeneralRe: Add-in getting unloaded after 10min PinmemberChristoph Buenger6-Jan-06 11:36 
GeneralRe: Add-in getting unloaded after 10min Pinmembergregoryfoster19-Dec-07 9:02 
GeneralRe: Add-in getting unloaded after 10min Pinmemberalfaevans20-Jan-08 9:38 
GeneralRe: Add-in getting unloaded after 10min Pinmemberbmnot22-Jan-10 14:14 
GeneralFailed to find the window created in Background Addin PinmemberAddin29-Nov-05 7:53 
GeneralRe: Failed to find the window created in Background Addin Pinmembercyycfol14-Aug-06 20:53 
GeneralRe: Failed to find the window created in Background Addin Pinmemberyuchih17-Sep-06 16:46 
GeneralRe: Failed to find the window created in Background Addin Pinmemberyuchih17-Sep-06 22:34 
GeneralGood PinsussAnonymous8-Apr-05 4:09 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web02 | 2.8.141015.1 | Last Updated 8 Apr 2005
Article Copyright 2005 by Christoph Buenger
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid