Populate On-Screen Content for a Silverlight for Windows Embedded Application (Windows Embedded CE 6.0)
1/6/2010
A visual host represents a Silverlight 2 visual tree in a Win32 window. All visual elements parsed from XAML are stored in a visual tree, and only one visual tree can belong to one visual host. By loading XAML markup into a visual tree that belongs to a visual host, you can populate the on-screen content for the UI of Silverlight–based application. Then, a Silverlight application can search, modify, and add to the XAML elements in the visual tree with C++ code. For more information about visual trees, see this Microsoft Web site.
To work with the visual tree, you must first obtain a handle to the visual host. You can obtain this handle when you create the visual host by calling IXRApplication::CreateHostFromXaml or IXRApplication::CreateHostFromElementTree.
Each visual host object contains an IXRFrameworkElement object that is a pointer to the root of its visual tree. You can obtain a pointer to the root by calling IXRVisualHost::GetRootElement. Then to find an element, call IXRFrameworkElement::FindName. To find an IXRDependencyObject-derived object that matches a UI element, create an XRPtr<Interface> smart pointer. Then, use the smart pointer as follows:
IXRButtonPtr pButton;
IXRFrameworkElementPtr pRootElement;
pVisualHost->GetRootElement(&pRootElement);
pRootElement->FindName(L"MyIXRButton", pButton);
Access the Host Window from the Visual Host
To access the host Win32 window, first call IXRVisualHost::GetContainerHWND to retrieve an HWND, then call Win32 functions that take an HWND as a parameter, such as UpdateWindow, IsChild, or SetParent. Having access to the host's window handle allows you to call any Win32 functions directly in Silverlight.
Handle Additional Window Messages in the Visual Host
The visual host provides event handling at run time for objects stored in the Silverlight visual tree. For example, when the host window receives a WM_PAINT message, the visual host draws UI elements on the screen.
When the window receives a user-input event such as a button click, the visual host must route it to the correct element in its visual tree. By default, windows messages such as WM_PAINT, WM_TIMER, WM_SETTINGCHANGE, WM_SIZE, WM_MOUSEMOVE, WM_SYSKEYUP, WM_CHAR, WM_INPUTLANGCHANGE, WM_KILLFOCUS, WM_MOVE, and WM_GESTURE are processed in WndProc.
To provide custom handling for these window messages or to handle other window messages that Silverlight does not handle by default, you can do one of the following:
- Implement a hook procedure for the window message by using the XR_HOOKPROC type and add the event-handling code directly in the HostHookProc window procedure.
- Create a subclass of the default WndProc for the host window. When the window message is received, you can provide message-handling code that calls IXRUIElement::HitTest to determine which Silverlight element that the message is for.
To create a hook procedure
Define a procedure that matches the signature provided in XR_HOOKPROC and give it a custom name.
In your procedure, create a message loop that handles WM_* messages.
In your application startup code, do the following:
- Create an XRWindowCreateParams structure, populate its values, and then pass the name of the hook procedure that you implemented into the pHookProc member of XRWindowCreateParams.
- Pass XRWindowCreateParams into the call that creates the visual host, such as IXRApplication::CreateHostFromXaml or IXRApplication::CreateHostFromElementTree.
The following code shows an example hook procedure.
Important
For readability, the following code example does not contain security checking or error handling. Do not use the following code in a production environment.
BOOL CALLBACK CustomHookProc ( VOID* pv, HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam, LRESULT* pRetVal) { switch (Msg) { // Add cases such as WM_CREATE, WM_COMMAND, WM_PAINT if you do not // want to pass these messages along for default processing. case WM_CAPTURECHANGED: // implement custom message-handling code return TRUE; case WM_MOUSEWHEEL: // implement custom message-handling code return TRUE; } return FALSE; }