Create a Silverlight for Windows Embedded Application (Windows Embedded CE 6.0)
1/6/2010
To create an application for a Windows Embedded CE powered device that is based on Silverlight, you create the XAML file that defines the UI and create a subproject. Then, use the Silverlight C++ API to initialize Silverlight, parse the XAML file into an object tree, and add event handlers to the parsed elements.
To learn more about the classes available for creating a UI, see Silverlight for Windows Embedded Classes and Differences Between Silverlight for the Web and Silverlight for Windows Embedded.
Then, you can add functionality for features to implement custom methods to call from inside event handlers, add window controls, implement custom hook procedures, or add new objects at run time in C++.
Prerequisites
- If you decide to use a source XAML file to define the visual scene, you have already created that XAML file by using Microsoft Silverlight 2 XAML, Microsoft Expression Blend 2, or by writing directly in a .xaml file. For more information, see this Microsoft Web site.
- You have decided which type of application to build based on Silverlight. You have also identified the SYSGEN variables and .h files that include the additional APIs to use in your application.
- An OS design, run-time image, and a connection from Platform Builder to your device. For more information, see Developing an OS Design.
Step 1 Add Silverlight to Your OS Design
In Platform Builder for Windows Embedded CE 6.0, in your OS design project, add Silverlight support by including SYSGEN_XAML_RUNTIME. For more information, see Adding an Item from the Catalog.
Step 2 Create a Subproject for Your Application
If you have chosen to define the UI in Silverlight 2 XAML instead of C++, copy the existing XAML file(s) to your subproject. For more information, see Subprojects.
Step 3 Create an Object that has Event Handlers
Create a custom object that includes method implementations for event handlers for all the interactive UI elements in your application, whether they are defined in the source XAML or will be created in C++.
You can create this object in <ProjectName>.cpp, before the WinMain routine.
The following example template code shows how to define this custom object:
class TestEventHandler
{
public:
HRESULT OnKeyDown( IXRDependencyObject* pSender, XRKeyEventArgs* pArgs )
{
//event handler implementation
}
};
Step 4 Prepare the Silverlight Visual Tree
To display the application UI and modify UI elements, you must first prepare Silverlight to run in an application by parsing a source XAML file to populate the visual tree with UI elements.
To complete the task, you will initialize the system, load the source XAML file, generate an object tree, and begin routing and processing messages for the application.
To prepare the Silverlight visual tree
In the C++ source code file, include the related header files. For example:
#include <XamlRuntime.h> #include <XRDelegate.h>
In the WinMain routine, initialize the system by calling XamlRuntimeInitialize. For example:
BOOL IsXRInitialized = FALSE; IsXRInitialized = XamlRuntimeInitialize(); if (! IsXRInitialized) { goto Error; }
Obtain a singleton application object by calling GetXRApplicationInstance. For example:
IXRApplication* pApplication = NULL; GetXRApplicationInstance(&pApplication);
(Optional) Add a resource module for Silverlight to use when it resolves image source Uniform Resource Identifiers (URIs) in the source XAML that it parses and loads into a visual tree. To do this, use one or both of the methods below.
Call IXRApplication::AddResourceModule and supply the handle to the current instance of the application (HINSTANCE) from the WinMain function signature.
pApplication->AddResourceModule(hInstance);
Create an IXRResourceManager object and then call IXRApplication::RegisterResourceManager. For example:
IXRResourceManager* pResource; pApplication->RegisterResourceManager(&pResource);
(Optional) If the source XAML includes an application.xaml file for resources, call IXRApplication::GetResourceDictionary and IXRApplication::LoadResourceDictionary to parse that XAML file.
IXRResourceDictionary* pResourceDictionary; XRXamlSource Source; Source.SetFile(RESOURCE_DIR L"Application.xaml""); pApplication->LoadResourceDictionary(&Source, &pResourceDictionary); pApplication->GetResourceDictionary(&pResourceDictionary);
Specify the XAML source by creating an XRXamlSource structure and populating it with information about the source of the XAML markup.
XRXamlSource SourceXaml; SourceXaml.SetFile(L"AppScene.xaml"); // Also set the XAML resource if you called AddResourceModule SourceXaml.SetResource(hInstance, L"XAML", MAKEINTRESOURCE(500));
(Optional) Set up the default window by creating an XRWindowCreateParams structure and populating it with window parameters.
XRWindowCreateParams WindowParameters; ZeroMemory(&WindowParameters, sizeof(WindowParameters)); WindowParameters.Style = WS_POPUP; WindowParameters.pTitle = L"Title Name"; WindowParameters.Left = 100; WindowParameters.Top = 100;
Parse the source XAML markup and generate the visual tree by calling IXRApplication::CreateHostFromXaml.
IXRVisualHost* pVisualHost = NULL; pApplication->CreateHostFromXaml(&SourceXaml, &WindowParameters, &pVisualHost);
(Optional) Obtain an IXRFrameworkElement pointer to the root of the visual tree so you can add UI objects created at run time to the visual tree. These objects can be integrated with the layout system by Silverlight and displayed in the graphical window.
IXRFrameworkElement* pRoot = NULL; pVisualHost->GetRootElement(&pRoot);
Display the host window for your application by using one of the options below.
For a modal dialog box, call IXRVisualHost::StartDialog.
pVisualHost->StartDialog(NULL);
For a modeless dialog box, call IXRVisualHost::ShowWindow and then call IXRApplication::StartProcessing.
pVisualHost->ShowWindow();
The following example code displays the host window for a modeless dialog box:
HWND hwnd = NULL; pVisualHost->GetContainerHWND(&hwnd); pVisualHost->ShowWindow(); UpdateWindow(hwnd);
Start processing messages for objects that were loaded into the visual tree by using the custom WndProc implemented by Silverlight.
UINT exitCode = 0; pApplication->StartProcessing(&exitCode);
After you complete this task, the application will be displayed on the screen and prepared for user interaction.
In the WinMain routine, after you parse the XAML into an object tree by calling IXRApplication::CreateHostFromXaml, insert code that adds the event handlers into each interactive UI object in the object tree.
To add an event handler to a UI object that is created in C++
Add XRDelegate.h and XRPtr.h to the #include list in the Silverlight application.
#include <XRDelegate.h> #include <XRPtr.h>
Initialize an object variable for a smart pointer and use the IXRApplication::CreateObject(IID,Object) method to convert it into an object and return a reference to the new object.
IXRRectanglePtr pRect; pApplication->CreateObject(&pRect);
Define the new object instance by using its methods.
pRect->SetRadiusX(50); pRect->SetRadiusY(50);
Create a delegate for your custom event handler and attach it to the object.
To do this, call the associated Add*EventHandler method, and call the CreateDelegate(class,class::method) inline function in the first argument of the method. Each class for an interactive UI object has one or more Add*EventHandler methods, such as IXRUIElement::AddMouseEnterEventHandler.
TestEventHandler* HandlerObject = NULL; pRect->AddMouseEnterEventHandler(CreateDelegate(&HandlerObject, &TestEventHandler::OnMouseEnter));
To add event handlers to parsed XAML elements, you can create a helper function that finds all the interactive objects parsed from XAML and attaches delegates to each object. Then, you can call this function after you parse the XAML in the WinMain routine.
To add event handlers to UI objects parsed from XAML
Retrieve the x:Name values of the XAML elements that you parsed in your Silverlight application.
You can do this by requesting a list of x:Name values from the UI designer, or you can scan the XAML files yourself and extract the value of x:Name from each interactive element to handle events for. The following example markup shows a XAML element that has an x:Name value of "Button7."
<Button x:Name="Button7" Content="Remove" Width="80" Height="30" />
Add XRDelegate.h and XRPtr.h to the #include list in Silverlight application.
#include <XRDelegate.h> #include <XRPtr.h>
Obtain an IXRFrameworkElement pointer to the root of the visual tree by using the IXRVisualHost object returned by IXRApplication::CreateHostFromXaml.
IXRFrameworkElement* pRoot = NULL; pVisualHost->GetRootElement(&pRoot);
Use IXRFrameworkElement::FindName to locate each interactive UI object by its x:Name value.
IXRButton* pButton; pRoot->FindName(L"Button7", &pButton);
Create a delegate for you custom event handler that you can attach to the UI object.
To do this, call the CreateDelegate(class,class::method) inline function in the first argument of the Add*EventHandler method. Each class for an interactive UI object has one or more Add*EventHandler methods, such as IXRButtonBase::AddClickEventHandler.
TestEventHandler* HandlerObject = NULL; pButton->AddClickEventHandler(CreateDelegate(&HandlerObject, &TestEventHandler::OnClick));
Step 5 Add Variables to Enable Accessing UI Objects in an Event Handler
(Optional) If you want to access the visual tree from an event handler, add a global variable to represent the visual host in the event object. Then, implement a method called SetHost that sets the global variable to the application's visual host, so the code inside each event handler can access other UI objects in the visual host.
For example:
class TestEventHandler
{
public:
IXRVisualHost* g_pHost;
HRESULT SetHost(IXRVisualHost* pHost)
{
HRESULT hr;
ASSERT(! g_pHost);
if(NULL == pHost)
{
hr = S_FALSE;
return hr;
}
g_pHost = pHost;
g_pHost->AddRef();
hr = S_OK;
return hr;
}
};
Call the new method SetHost after IXRApplication::CreateHostFromXaml.
TestEventHandler events;
events.SetHost(pVisualHost);
Step 6 Implement Your Application
Write code to add the desired functionality to your application.
If you want to change the visual scene at run time, you can use the Silverlight API to modify or add new UI objects to the object tree. Use IXRFrameworkElement::FindName to traverse the object tree and get pointers to objects that you would like to customize or add new objects to.
For example, you can change the visual scene by setting new values for brushes, images, coordinate position, animation storyboard collections, and so on.
Step 7 Write Shutdown Code
When the application exits, your code must release resources for the visual host and the application instance, and disable Silverlight. Call SAFE_DELETE on object instances, and call IUnknown::Release on the IXRFrameworkElement root element instance.
For example, the following example code frees resources for the IXRVisualHost (pVisualHost) object instance and the IXRApplication (pApplication) object instance, and exits the application:
Error:
if (pVisualHost)
{
pVisualHost->DestroyWindow();
pVisualHost->Release();
pVisualHost = NULL;
}
if (pApplication)
{
pApplication->Release();
pApplication = NULL;
}
if (pRoot)
{
pRoot->Release();
}
if (IsXRInitialized)
{
XamlRuntimeUninitialize();
}
return 0;
Step 8 Build the Application and Your OS Design
In Solution Explorer, expand Subprojects, right-click the subproject you created, and click Build (build).
The build progress is displayed in the Output tab of the Output window.**
For more information, see Subprojects.
(Optional) If you defined the UI in Silverlight 2 XAML, add the XAML file(s) to the subproject BIB file. In Solution Explorer, expand Subprojects, expand Parameter files, and then double-click <ProjectName>.bib. Create a FILES section and add entries for the XAML files. For more information, see FILES Section.
Rebuild the run-time image, and download it to the device through the connection that you have already configured.**
For more information, see How to Connect to a Target Device for Debugging.
Step 9 Run Your Application
Run the application on the run-time image by doing one of the following tasks:
- In Platform Builder, on the Target menu, click Run Programs, click <ProjectName>.exe, and click OK.
- In Platform Builder, on the Target menu, click Target Control. Then, at the command prompt, type
s <ProjectName>
.
For information about error messages, see Silverlight for Windows Embedded Error Messages