Handling the Resolution Difference of a Windows Media Center Extender Session in Hosted HTML

The screen resolution of the Windows Media Center Extender session will probably be different than that of the host computer, so you should scale your HTML pages accordingly. The easiest way to do this is by handling the MediaCenter.onScaleEvent in your application.

The onScaleEvent fires when a page loads and when the display is resized. By setting the zoom property of the page's body equal to the data provided by this event, you can automatically resize the page whenever the resolution changes. The following example shows how to resize a page in a handler for onScaleEvent:

function onScaleEvent(vScale)
{
    try
    {
        body.style.zoom=vScale;
    }
    catch(e)
    {
        // Ignore the error.
    }
}

When working with Online Media, designers and developers can use the following guidelines when creating and scaling their application user interface (UI):

  • Start with the sample code above, which uses the following:

    JScript: body.style.zoom=vScale
    HTML: <body id="body">
    

    This references an object in HTML, which is referred to by its ID attribute. When using this sample code, you will need to sync the JScript with the body element ID, for example:

    JScript: document.all.id_body.style.zoom=vScale
    HTML: <body id="id_body">
    
  • Rather than developing a new solution, it is recommended you use this solution for scaling the UI, which requires at most 11 lines of JScript and an ID attribute on the body element of HTML.

    • DHTML allows you to place objects and elements with absolute positioning rather than scaling the entire page.
    • Certain Windows Media Center objects are scaled independently of the onScaleEvent and cannot be controlled programmatically.
    • It is difficult to anticipate every situation for scaling pages for multiple aspect ratios.
  • Design your pages specifically for the widescreen aspect ratio, which is being adopted more and more.

How scaling works

The vScale argument, which is passed when Windows Media Center calls the onScaleEvent function in the developer's JScript, is always the smaller of the following calculations:

document.body.clientWidth / 1024
document.body.clientHeight / 768

When document.all.[body id].style.zoom is applied with the onScaleEvent function, the following values are always returned when Windows Media Center is running in a windowed mode or in native full-screen resolutions of exactly 4:3 and 16:9 aspect ratios:

  • For standard aspect ratio of 4:3:

    document.body.clientWidth = 1024
    document.body.clientHeight = 768
    
  • For widescreen aspect ratio of 16:9:

    document.body.clientWidth = 1366
    document.body.clientHeight = 768
    

When in full-screen mode, the following values are returned when not running in Windows Media Center's native full-screen resolutions of 4:3 or 16:9 aspect ratios:

  • For standard aspect ratios (those similar to 4:3—for example, 1280 x 1024):

    document.body.clientWidth = 1024
    

    [Calculated Value] document.body.clientHeight = [Actual document.body.clientHeight] * 1024 / [Actual document.body.clientWidth]

  • For widescreen aspect ratios (those similar to 16:9—for example, 1280 x 800):

    document.body.clientHeight = 768
    

    [Calculated Value] document.body.clientWidth = [Actual document.body.clientWidth] * 768 / [Actual document.body.clientHeight]

This complexity reinforces the recommendation to use the existing scaling solutions rather than developing your own.

The following code examples show how scaling works:

Default.htm

<html>
    <head>
        <LINK href="Main.css" type="text/css" rel="STYLESHEET"></LINK>
        <script src="BasicFunctions.js" type="text/javascript"></script>
        <script src="Scrolling.js" type="text/javascript"></script>
        <script src="MoveFocus.js" type="text/javascript"></script>
        <script language="jscript">

        function window_onload()
        {
            // BasicFunctions.js
            setBGColor("#666666");
        }

        function onScaleEvent(vScale)
        {
            try
            {
                var varWidth;
                var varHeight;
                var varScaleHorizontal;
                var varScaleVertical;

                // Uncomment this line to see the results of scaling applied to the page.
                // Note the page won't scale properly in Windows Media Center, but you will see the calculated values.
                //document.all.id_body.style.zoom=vScale;

                document.all.CurrentScale.innerText = "CurrentScale = " + vScale;

                varWidth = document.body.clientWidth;
                varHeight = document.body.clientHeight;

                document.all.ClientWidth.innerText = "ClientWidth = " + varWidth;
                document.all.ClientHeight.innerText = "ClientHeight = " + varHeight;

                varScaleHorizontal = varWidth / 1024;
                varScaleVertical = varHeight / 768;

                document.all.HorizontalScale.innerText = "HorizontalScale = " + varScaleHorizontal;
                document.all.VerticalScale.innerText = "VerticalScale = " + varScaleVertical;

            }
            catch(e)
            {
                // ignore error
            }

        }

        </script>
    </head>
    <body id="id_body" class="text" scroll="no" MCFocusStart="asdasd" onload="window_onload()" onkeydown="onRemoteEvent(window.event.keyCode)">
        <p>Windows Media Center Software Development Kit (SDK)</p>
        <p>Copyright Microsoft Corporation</p>
        <p>Sample Code: OnScaleEvent</p>
        <p id="CurrentScale"></p>
        <p id="ClientWidth"></p>
        <p id="ClientHeight"></p>
        <p id="HorizontalScale"></p>
        <p id="VerticalScale"></p>
        <!-- SharedViewPort SPAN Placeholder -->
        <span id="SVP" class="SVP_Span" MCFocusable="true"></span>
        <!-- SharedViewPort SPAN Placeholder -->
    </body>
</html>

BasicFunctions.js

   /////////////////////////////////////////////////////////////
   // Identify the page as enabled for Windows Media Center. This avoids a warning dialog to the user.
   function IsMCEEnabled()
   {
    return true
   }

/////////////////////////////////////////////////////////////////
// Scaling elements for page resize.
//function onScaleEvent(vScale)
//{
//    try
//    {
//        body.style.zoom=vScale;
//        // When the page gets resized, reset positions and sizes of focusable elements.
//        setArray()
//    }
//    catch(e)
//    {
//        // ignore error
//    }
//}

var nFullScreen = 0
function backFromFullScreen()
{
    if (nFullScreen == 0)
    {
        nFullScreen = 1
        return false
    }
    else return true
}


/////////////////////////////////////////////////////////////////
// Determine which remote control button the user selected
// and take appropriate action.
function onRemoteEvent(keyChar)
{
    /* Call optional "doOnFocus" function if needed; you can locate this function on the HTML page, and use it to tie some
   custom functionality to a remote control button press. If you want to stop onRemoteEvent from moving focus after that,
   return true in the doOnFocus function to indicate that the remote control button press is already being handled in some other way. */
    try
    {
        if (doOnFocus(keyChar) == true)
        {
            return true;
        }
    }
    catch(e)
    {
        // If the doOnFocus function is not present on the page, ignore the error.
    }
    try
    {
    // This switch tests to see which button on the remote is pressed.
        switch (keyChar)
        {
        case 38:  // Up button selected.
            changeFocus("up");
            break;

        case 40:  // Down button selected.
            changeFocus("down");
            break;

        case 37:  // Left button selected.
            changeFocus("left");
            break;

        case 39:  // Right button selected.
            changeFocus("right");
            break;

        case 13:  // Enter button selected; execute link to content/page.
            doSelect();
            return true;
            break;

        case 8:  // Keyboard BACKSPACE selected.
            return false;
            break;

        case 166:            // Remote control Back button selected; Windows Media Center will already perform a Back.
            return false;    // Navigation when this is pressed, but this case can be used to add additional
            break;           //functionality to the Back button.

        case 33:    // Page up (plus) selected; page-up scrolling menu.
            pageUpDown("up");
            return true;
            break;

        case 34:    // Page down (minus) selected; page-down scrolling menu.
            pageUpDown("down");
            return true;
            break;

        default:
            return false;
            // Ignore all other clicks.
        }
    }
    catch(ex)
    {
        // Ignore error.
    }
    return true
}


///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Set the background color for shared view port and Windows Media Center toolbars that appear when you move the mouse.
function setBGColor(Color)
{
    try
    {
        window.external.MediaCenter.BGColor = Color
    }
    catch(e)
    {
        // Not using Windows Media Center, or attribute not set.
    }
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////
/* For Windows XP Media Center Edition 2003, test the onload event to see whether the variables are reset; if they are not, this
means that the user is returning from some Windows Media Center view, such as full-screen video mode or My TV.
If this is the case, you want to ignore your page's onload event. In Windows XP Media Center Edition 2005 and later,
the page does not raise an onload event when this happens, so this function will not be necessary. */

var backFromMediaCenter = false
function continueOnloadFunctions()
{
    if (backFromMediaCenter == false) // Meaning the variable has been reset to its default state.
    {
        // Set variable to true and return.
        backFromMediaCenter = true
        return
    }
    /* Otherwise, page variables have not been reset, so you do not want to continue to call
    your page initilizing functions. Return false. */
    return false
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// This function tests to see whether you need to open a view port for media playback.
function needViewport()
{
    // If the shared or custom view port is already visible, return false.
    if (window.external.MediaCenter.SharedViewPort.Visible == true || window.external.MediaCenter.CustomViewPort.Visible == true)
    {
        return false
    }
    // If there is no media playing, return false.
    if(window.external.MediaCenter.Experience.PlayState == -1) return false
    // Otherwise return true.
    return true
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// This function detects what version of Windows Media Center the user is running. It will return a year as string, such as "2005".
function showMCEVersion()
{
    try
    {
        var nMajVer = window.external.MediaCenter.MajorVersion
    }
    catch (e)
    {
        return null
    }
    if (nMajVer < 7) return "2004"
    if (nmajVer = 7) return "2005"
    // In case the above fails, return null.
    return null
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// This function detects whether the user is in a remote session on a Windows Media Center Extender device.
function IsMCExtender()
{
    try
    {
        // If this is not a Windows Media Center PC session ...
        if (window.external.MediaCenter.Capabilities.IsConsole == false)
        {
            /* ...then it is either a Windows Media Center Extender session or a Remote Desktop session.
            To tell which type of session it is, check whether video is allowed. If video is allowed... */
            if (window.external.MediaCenter.Capabilities.IsVideoAllowed == true)
            {
                // ... then it is an Extender session, so return true.
                return true.
            }
            // Windows Media Center does not allow video in a traditional Remote Desktop session. So if video is not allowed ...
            else
            {
                /* IsConsole and IsVideoAllowed are both false false, so user is accessing through a traditional Remote
                Desktop session, rather than from an Extender device. That means that the user probably has access to a keyboard
                and mouse, but they cannot play video. If your application features video playback, you may want to
                adjust your functionality for this user accordingly.
                Returning false simply indicates that this is not an Extender session.  */
                return false
            }
        }
        else
        {
            // If not, this is a Windows Media Center session on the Windows Media Center PC, so return false.
            return false
        }
    }
    catch(e)
    {
        /* If the above causes errors, the user is probably accessing from a browser outside of Windows Media Center.
        Return false to indicate that it is not an Extender session. */
        return false
    }
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Function for reloading page
    function reloadPage()
    {
        /* This function refreshes the page, and calls the onScaleEvent function
        to manage resizing of the elements on the page. */
        window.location.reload()
        // Determine the width of the page.
        var newWidth = body.getBoundingClientRect().right
        // Determine how much the page needs to be resized, by comparing page width to 1024.
        var sizeAmount = (newWidth/1024)
        // Call the onScaleEvent function.
        onScaleEvent(sizeAmount)
    }

See Also