Posts
76
Comments
208
Trackbacks
0
October 2009 Entries
Silverlight for Windows Embedded tutorial (step 2)

In our first tutorial
http://geekswithblogs.net/WindowsEmbeddedCookbook/archive/2009/10/01/silverlight-for-embedded-tutorial.aspx
we learnt how to load a XAML-based user interface inside your own application and intercept the events that it generates.
In this second tutorial we will learn how to use storyboards to create animations inside our user interface and how we can control them from code.
We can reopen our silverlight2 application project in Expression Blend 2 SP1 and add a new element to our UI: a TextBlock.

We can place it just under our button.

Then we can create a new storyboard, using the "+" button that we can find just under the "Objects and Timeline" toolbox header.

We should assign a name to our new Storyboard, as we did with the button control.

Now we can move our storyboard time cursor to the 1 second mark and change our page to the end point of our animation.

We can rotate our TextBlock, for example.

Expression Blend create for us the animation and transformation objects required to perform the desired visual effect.
We want to have our TextBlock performing a full rotation, so we can edit the parameters of the rotation transform and set the angle to 360 degrees.

By right clicking on the tranform item we can also set the number of iteration that this animation performs. We set it to infinite to have a continous rotation of our poor TextBlock.

Now we save the changes we did to our project in Expression Blend and go back to Platform Builder to change our code.
First of all we have to get a pointer to our Storyboard. We can retrieve it using the FindName method of our visual root, like we did to retrieve a pointer to the button object in the first step of this tutorial.

    IXRStoryboardPtr sboard;

    if (FAILED(retcode=root->FindName(TEXT("SpinText"), &sboard)))
        return -1;


We will need to use the storyboard and button object inside your event handler class, so we need to change it to store those two smart pointers:

class BtnEventHandler
{
protected:

    IXRButtonBasePtr    btn;
    IXRStoryboardPtr     sboard;

public:

    BtnEventHandler(IXRButtonBasePtr& button, IXRStoryboardPtr& storyboard) : btn(button),sboard(storyboard)
    {    
    }

   
We also need to change its declaration inside the WinMain function:

    BtnEventHandler handler(btn,sboard);


Now we can edit our OnClick event handler to use our button to start and stop spinning animation.
First of all we should know if the animation is running. To do that we can retrieve the state of our storyboard object:

        HRESULT        retcode;
        XRClockState ckstate;

        if (FAILED(retcode=sboard->GetCurrentState(&ckstate)))
            return retcode;


if ckstate is XRClockState_Stopped, our animation is stopped, so we will need to start it, using the Begin method of our Storyboard object.
If the animation is running we should stop it using the Stop method.
At the same time we want to change the text on the button object to reflect the action it performs. The IXRButton object (COM interface) derives from the IXRContentControl object that defines methods to access a control "content".
What is "content" for a Silverlight for Windows Embedded object? It's an instance of the XRValue class. This class can contain different kinds of data: strings, numbers, coordinates etc. It's current content type is defined by the vType field and may be one of the VALUE_TYPE enumeration values:
VTYPE_NONE = 0,
VTYPE_FLOAT = 1,
VTYPE_INT = 2,
VTYPE_BOOL = 3,
VTYPE_UINT = 4,
VTYPE_COLOR = 5,
VTYPE_READONLY_STRING = 6,
VTYPE_BSTR = 7
VTYPE_POINT = 8,
VTYPE_RECT = 9,
VTYPE_THICKNESS = 10,
VTYPE_SIZE = 11,
VTYPE_GRIDLENGTH = 12,
VTYPE_CORNER_RADIUS = 13,
VTYPE_OBJECT = 14
Depending on the type you set, you can use one of the fields of the object (defined as an unnamed union) to set the actual value of your XRValue objects.
If you worked on COM (Component Object Model) applications in the past (or you are working on this kind of technology right now, of course!) the XRValue object will remind you the VARIANT object that is used in COM to define "generic" data.
To change the content of our button we need to declare an XRValue object of type "read only string":

        XRValue btnvalue;

        btnvalue.vType=VTYPE_READONLY_STRING; 


We can assign its value trough the pReadOnlyStringVal field and set it to "Spin!" or "Stop!" depending on our animation current state.
The full code of our event handler will be:

    HRESULT OnClick(IXRDependencyObject* source,XRMouseButtonEventArgs* args)
    {
        HRESULT        retcode;
        XRClockState ckstate;

        if (FAILED(retcode=sboard->GetCurrentState(&ckstate)))
            return retcode;

        XRValue btnvalue;

        btnvalue.vType=VTYPE_READONLY_STRING; 

        if (ckstate==XRClockState_Stopped)
        {
            btnvalue.pReadOnlyStringVal=L"Stop!";
            if (FAILED(retcode=sboard->Begin()))
                return retcode;
        }
        else
        {
            btnvalue.pReadOnlyStringVal=L"Spin!";
            if (FAILED(retcode=sboard->Stop()))
                return retcode;
        }

        if (FAILED(retcode=btn->SetContent(&btnvalue)))
            return retcode;

        return S_OK;
    }

   
A little more complicated than the event handler of our previous tutorial step, but not so much. And in this function we used two very useful features of Silverligh for Embedded: animations and control content access.
You can download the full source code here:
http://cid-9b7b0aefe3514dc5.skydrive.live.com/self.aspx/.Public/SilverlightSample2.zip
Please use the comments to let me know if you find this kind of tutorial useful, to report mistakes and to suggest the arguments that you would like to see discussed in the next steps.

Posted On Sunday, October 11, 2009 3:49 AM | Comments (13)
Interfaccia uomo macchina
Sevilla (Spain) - The alcazar
If you want to discover something more about Windows Embedded CE 6.0 R3 and you live close to Padua, Milan or Bologna (or you want to travel to those cities, of course!), you can register for those Arrow, Microsoft and Freescale sponsored events:
http://www.silverstar-celdis.it/index.php?id=834&tx_ttnewstt_news=253&tx_ttnewsbackPid=831&cHash=6a2c437777
If you read my blog and come to those events, let me know that!
Posted On Monday, October 5, 2009 2:47 AM | Comments (0)
Silverlight for Windows Embedded tutorial

Windows Embedded CE 6.0 R3 has been released yesterday, you can download it from here:
http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=bc247d88-ddb6-4d4a-a595-8eee3556fe46
One of the most exciting new features of R3 is Silverlight for Windows Embedded.
With this technology the UI of an application can be described using XAML, an XML-based language, and can be designed using visual tools like Expression Blend.
This will allow UI designers to work on embedded devices using the same tools they use on the desktop and it will let embedded developers concentrate on the core application features and not on the design of the UI.
I hope that this will lead to visually pleasing but also more user friendly interfaces on any kind of embedded device. Using visual tools for UI design should also improve development time and allow minor fixes to the UI without code modifications. This will improve device development times and reduce maintenance costs.
This simple tutorial will show how you can design a very basic UI in Expression Blend 2, load it inside an application and interact with it.
The first step you need to perform is include the components needed to support Silverlight for Windows Embedded inside your OS Image and rebuild it.
Jochen Dieckfoß provided a good description of that process on his blog here:
http://discovertheexperience.blogspot.com/2009/09/windows-embedded-ce-60-r3-using.html
Now that you have an OS image supporting Silverlight for Windows Embedded you can start to design your UI.
Start Expression Blend and create a new Silverlight application.

You'll have to use Expression Blend 2 SP1 (thanks Shai for the useful advice!) because this is the release that support Silverlight 2, the version that is currently supported on embedded devices.
This will create a Visual Studio solution (that we don't need for this tutorial).
As you can see the wizard allows you to choose a language between C# and Visual Basic. Silverlight for Windows Embedded supports only C++ programming and it's currently not integrated with Expression Blend, so you'll not use the source code generated by this tool.
Remember to disable Visual Studio integration inside Expression Blend or it will generate C# or VB.NET code for event handlers etc.

After you created a new project, Expression Blend will present you with an empty XAML document (named page.xaml by default).

We can draw a simple button inside it picking it from the rich collection of controls provided by Silverlight.

Using the properties window we can assign a name to our new button.

The properties toolbox allows you to customize many aspects of your button: it's colors, it's rotation (yes you can have a vertical button or a button turned at 45 degrees!), it's opacity etc.
We will experiment with all these features in the next tutorials, for now we will keep the button as is and save our XAML.
If you open the XAML file using a text editor or view it using the XAML view inside Expression Blend you'll see that it's quite simple:

<UserControl xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"    
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Class="SimpleApp.Page" 
Width="640" Height="480">
    <Grid x:Name="LayoutRoot" Background="White">
        <Button Height="87" Margin="189,106,209,0" VerticalAlignment="Top" Content="Button" 
x:Name="MyButton"/>
    </Grid>
</UserControl>


We have a top level container (UserControl) that uses a Grid layout (objects are organized in rows and columns) and contains our button.
The button has attributes for placement inside its own grid cell (the only one we have), alignment, content (the text "Button") and its name ("MyButton").
Now we can start Platform Builder and add a new subproject to our OS Design.
You may develop your Silverlight for Windows Embedded application also using Visual Studio 2005 or 2008 Smart Device application if you generate an SDK from your R3 OS design and install it on your development PC, but for this tutorial we will keep things simple...
Move to the solution tab, right click on the subprojects node and select "add new...".
Create a Win32 application.

And choose the simple Win32 application template.

This will create an application containing only WinMain, it's enough to start experimenting with our first Silverlight for Embedded UI.
The first thing we should do is add the Silverlight for Windows Embedded includes to our source code:

#include "pwinuser.h"
#include "xamlruntime.h"
#include "xrdelegate.h"
#include "xrptr.h"


We will add the XAML that we generate with expression blend to our application resources. In this way we will not need to distibute the XAML file with it. On the other side changes to the XAML will require a rebuild of the application, you may choose the best method to integrate XAML and C++ source code in your application.
To include resources inside your executable file you need to add a resource script (rc file) to your subproject.
Right click on the subproject in solution view, select "add\new item" and then select resource file from the dialog box and assign a name to it (usually you have only one resource file per application so using the application name for that file sounds like a good idea).

Now that you have your resource file you can add the XAML data to it by creating a new resource.
Go to the "resource view" tab, right click on your resource file and select "add resource..."

Now you can import your XAML file data inside your executable. It will be stored inside it (at the end of the file) as binary data.

Type "XAML" as resource type.

For the tutorial you can leave the default ID (IDR_XAML1) for that resource, but it's a good idea to give meaningful names to your XAML components in a real project.

To use our resource IDs we need to include "resource.h" inside our .cpp file:

#include "resource.h"


Then, inside our application main function (WinMain) we can start to interact with the XAML runtime.
First of all we need to initialize it:

    if (!XamlRuntimeInitialize())
        return -1;


If XamlRuntimeInitialize succeeded, the Silverlight for Windows Embedded runtime is loaded inside your application and it's ready to handle the UI.
Each Silverlight for Windows Embedded application has a singleton "Application" object that allows us to access global application properties and features.
To access it we should use the GetXRApplicationInstance API.

    HRESULT retcode;

    IXRApplicationPtr app;
    
    if (FAILED(retcode=GetXRApplicationInstance(&app)))
        return -1;



Someone will notice that we are using HRESULTs and classes that use the "I" prefix and the "Ptr" suffix and understand that this new technlogy is based on COM (Component Object Model) that may sound like an ancient tool in those .NET and managed code days but it's still the foundation of many technlogies on both CE and desktop Windows releases. All Silverlight for Windows Embedded objects are implemented as COM objects that export specific interfaces (COM interfaces have names beginning with "I"). Since using interfaces directly requires handling of their reference count and this may lead to memory leaks or premature object deletions, COM programmers prefer to use "smart pointers" that are wrappers around the interfaces and manage reference counting internally, destroying the COM object when the smart pointer object goes out of scope inside your C++ application (function return if it's allocated on the stack, object destruction if it's declared as a class member etc.). Smart point classes add the "Ptr" suffix to the interface name.
After this 30 seconds introduction to COM, we can return to our application.
The first thing we have to do with our application object is tell it where it can find its resources (XAML, images etc.).
We included them inside the executable using the resource file and so we can pass our HINSTANCE handle to it:

    if (FAILED(retcode=app->AddResourceModule(hInstance)))
        return -1;


Now that we have initialized our application object we can create our main window and let Silverlight for Windows Embedded manage its contents:

    XRWindowCreateParams wp;

    ZeroMemory(&wp, sizeof(XRWindowCreateParams));

    wp.Style       = WS_OVERLAPPED;
    wp.pTitle      = L"S4E Test";
    wp.Left        = 0;
    wp.Top         = 0;

    XRXamlSource xamlsrc;

    xamlsrc.SetResource(hInstance,TEXT("XAML"),MAKEINTRESOURCE(IDR_XAML1));

    IXRVisualHostPtr vhost;

    if (FAILED(retcode=app->CreateHostFromXaml(&xamlsrc, &wp, &vhost)))
        return -1;


The VisualHost object "hosts" the runtime and allows us to access its contents and load our XAML from resources (using the XRXamlSource object).
Now our XA
The object inside our Silverlight for Windows Embedded application are organized in a objects tree. To access the object inside it we need a pointer to its root:

    IXRFrameworkElementPtr root;

    if (FAILED(retcode=vhost->GetRootElement(&root)))
        return -1;


From the root object we can access our button using the name we assigned to it inside Expression Blend:

    IXRButtonBasePtr btn;
    
    if (FAILED(retcode=root->FindName(TEXT("MyButton"), &btn)))
        return -1;


To receive a notification when the user clicks our button we need to provide a delegate. A delegate is a pointer to a member of an istance of a C++ class that should have a specific prototype.
We can declare a simple C++ class inside our .cpp source and implement our button click event delegate inside it:

class BtnEventHandler
{
public:

    HRESULT OnClick(IXRDependencyObject* source,XRMouseButtonEventArgs* args)
    {
        MessageBox(NULL,TEXT("Click!"),TEXT("Silverlight for Windows Embedded test"),MB_OK);
        return S_OK;
    }
};


Our event handler will simply display a message box when the button is clicked.
As you can see the event handler takes two parameters. A pointer to the object that generates the event (our button) and a pointer to a structure that contains the event parameters.

To connect our event handler to the button we have to create a delegate object:

    BtnEventHandler handler;

    IXRDelegate<XRMouseButtonEventArgs>* clickdelegate;

    if (FAILED(retcode=CreateDelegate(&handler,&BtnEventHandler::OnClick,&clickdelegate)))
        return -1;

    if (FAILED(retcode=btn->AddClickEventHandler(clickdelegate)))
        return -1;


Our event handler has been connected to the button, now we can show our UI and wait that the user presses our wonderful button:

    UINT exitcode;

    if (FAILED(retcode=vhost->StartDialog(&exitcode)))
        return -1;


Our clickdelegate object is not a smart pointer, so we will have to release it explicitly:

    clickdelegate->Release();


Before we can build our subproject we need to add the include directories and the libraries needed to support Silverlight for Windows Embedded inside our application.
Open the subproject sources script by right clicking on the subproject and choosing "open".
Add includes:

INCLUDES=$(_OEMINCPATH)

and libraries:

TARGETLIBS= \
    $(_PROJECTROOT)\cesysgen\sdk\lib\$(_CPUINDPATH)\coredll.lib \
    $(_PROJECTROOT)\cesysgen\sdk\lib\$(_CPUINDPATH)\xamlruntime.lib \
    $(_PROJECTROOT)\cesysgen\sdk\lib\$(_CPUINDPATH)\uuid.lib \


(you should already have the TARGETLIBS directive inside your sources script)
Now you can run the application on your device and push that button!

You, like me, are too lazy to type sample code, you can download a zip containing our demo application here:
http://cid-9b7b0aefe3514dc5.skydrive.live.com/self.aspx/.Public/SilverlightSample.zip

You can find the next step here:
http://geekswithblogs.net/WindowsEmbeddedCookbook/archive/2009/10/11/silverlight-for-embedded-tutorial-step-2.aspx

Posted On Thursday, October 1, 2009 2:35 PM | Comments (87)
Toradex logo

Tag Cloud