Mar
15
2011

Integrating Microsoft’s Silverlight Into Qt Applications

Developers who have had occasion to develop applications using the Qt framework love it for its convenience and ease of use, and the power hidden under the technology’s hood. We also love Qt, and we wanted to expand our favorite framework with a feature for working with modern vector graphics – for example, we wanted to integrate Adobe Flash and Microsoft Silverlight clips into applications.

After all, Flash and Silverlight make it possible to create jaw-dropping design clips, interfaces, and last but not least, games. And all of this is accessible through a web browser – but would not be out of place in desktop applications either. So meet our Qtitan Multimedia component, made for combining the most popular technologies: Qt and the Flash and Silverlight multimedia platforms. Here we will discuss how to integrate Silverlight clips into an ordinary application written in Qt using the Qtitan Multimedia component.

Microsoft Silverlight
It so happens usually that popular technologies acquire their popularity, and with it, competitors. Adobe Flash has a competitor in Microsoft’s Silverlight graphics system. Flash and Silverlight have their similarities and their differences, but the goal of these two technologies is the same: to create and play vector animations and interactive applications (including games), and integrate video clips into webpages. One might think that Microsoft has missed the bus for displacing Flash, having announced Silverlight 1.0 in 2006 when Flash was already out of reach. But Microsoft being Microsoft, the company has more than enough resources to win this multimedia face-off. Which has proven to be the case: Microsoft has now released the fourth version of Silverlight already and certainly has no plans to stop. So to those asking such questions as “Is it worth spending time and effort to learn something new?” we recommend forgetting these questions, and to jump on the bandwagon and start learning Silverlight.
As far as technology on the client side, Silverlight comes in the form of a browser plugin similar to the Flash plugin. Similarly, when you visit a page with a Silverlight clip, your browser will request to download the plugin from Microsoft’s website, after which you can enjoy the latest design creations written on bleeding-edge technology. The plugin includes a full version of the .Net CLR. This means that all the benefits of .Net are available to Silverlight applications.
Silverlight is available for Windows XP, Windows Vista, Mac OS X, and the following web browsers: Internet Explorer (version 6 and higher), Mozilla Firefox, Safari, Chrome and Opera. For Linux there is the Moonlight project, implemented using Mono (an open-source implementation of .Net for Linux). For developers, Microsoft has made Visual Studio 2008 and the Silverlight Tools package available. Visual Studio 2008 should have the first service pack installed, or else Silverlight Tools will simply refuse to be installed.
Qtitan Multimedia Component For Qt
Qtitan is our component, whose unique merit is that it allows integrating Flash and Silverlight into ordinary applications written in Qt. After installing Qtitan Multimedia, a QWidget child will be made available to you, which is where the clips will be located. This widget is entitled Qtitan::Silverlight. Technically, the display of clips is accomplished thanks to the use of NPAPI plugins, and as such the class container is capable of displaying Netscape-compatible plugins. From a practical point of view, these details are not particularly important. In practice, for programmers this will be standard work with a QWidget child. In doing so we do not receive some abstract black box – effectively “we served up a clip and we’re good now” – but rather, a Qt application that can actively interact with a Silverlight clip.
There are two options for interaction:

We can call on the pluginScriptValue() function in the Qtitan::Silverlight widget and get an instance of QScriptValue. After getting QScriptValue, we can communicate with the clip just as a web browser can through JavaScript.
The opposite is also possible: instead of a Qt application calling on the clip, a Silverlight clip can actually call an application function. Just register this function by calling on the registrScriptableFunction(…) method in the Qtitan::Silverlight widget. When subsequently developing the Silverlight clip, we can call this function like an ordinary JavaScript function.

Qtitan Multimedia integrates with the Qt Designer form designer, which allows simplifying the addition of new objects and accelerating the development process.

Usage example

Now we will demonstrate how to integrate a Silverlight clip into a Qt application. For our example we will create an interactive banner in Silverlight and get it to work with a Qt application. We will pass our name from the application to Silverlight, where it will be used. In the clip we will offer the user the chance to vote for their favorite technology and pass the results of voting to the application.
We will require the following to do so:

Microsoft Visual Studio 2008 SP1 with the Silverlight Tools package installed. The free version, Visual Studio Express, may also be used.
The latest version of Qt, 4.6.3, or earlier versions. A free open-source version can be used, which is available in debug and release builds.
Qtitan Multimedia. You can use a demo version, which is downloadable at http://www.devmachines.com/downloads/free-demo-version.html

Recommended installation order:

Install Microsoft Visual Studio 2008 SP1.
Install Silverlight Tools.
Install and build Qt using Visual Studio’s nmake compiler.
Download and install Qtitan. It is advisable to install the demo in a folder whose name does not contain spaces, e.g., c:qtitan and not Program Files.

Of course, if you already have VS 2008 SP1 and a build of Qt compiled for it, then you need only to install Silverlight Tools and Qtitan.

Creating a Silverlight clip
Launch Microsoft Visual Web Developer 2008. Create a new project by going to the File menu: File->New Project… In the New Project dialog, select Visual C# -> Silverlight in the Project types list.
http://www.devmachines.com/images/article_silverlight/index_001.png
During the next step we will be asked whether we want to create a test ASP.NET application where the clip will be embedded. We will answer yes. Visual Studio will create a local web server on localhost, and place on it a page with the embedded clip so that we can immediately see all of the changes that we make. So the solution has two projects, the clip itself and the test application.
http://www.devmachines.com/images/article_silverlight/index_002.png
For the central portion of the project we have a window split into two parts: the appearance of our clip and its XAML code. Creating a Silverlight clip consists of editing the XAML code, which is similar to XML.
Let’s edit the XAML code. We will make the page background a gradient, from yellow to red. To do this, inside of the <Grid> tag we’ll insert the following code:

<Grid x:Name=”LayoutRoot”>
<Grid.Background>
<LinearGradientBrush>
<LinearGradientBrush.GradientStops>
<GradientStop Offset=”0″ Color=”Yellow” />
<GradientStop Offset=”1″ Color=”Red”/>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Grid.Background>
</Grid>

Then we will delete the Background=”White” property which sets the page background to white. Now our page will have a gradient fill, from yellow to red, in the background. We will also set the standard banner size of 468 by 60 in the UserControl tag.
Now we will insert a text box displaying the user’s name, which the user will enter in the Qt application. On the right we will place a pair of radio buttons so that users can vote for their favorite technology.
http://www.devmachines.com/images/article_silverlight/index_003.png
The goal of our banner is simple: to greet the user and allow them to vote for their favorite technology. The choice of technology will be sent to the Qt application. Below is the complete XAML code for our banner.

<UserControl x:Class=”Banner.Page”
xmlns=”<a href=”http://schemas.microsoft.com/winfx/2006/xaml/presentation”>http://schemas.microsoft.com/winfx/2006/xaml/presentation</a>”
xmlns:x=”<a href=”http://schemas.microsoft.com/winfx/2006/xaml”>http://schemas.microsoft.com/winfx/2006/xaml</a>”
Width=”468″ Height=”60″>
<Grid x:Name=”LayoutRoot”>
<Grid.Background>
<LinearGradientBrush>
<LinearGradientBrush.GradientStops>
<GradientStop Offset=”0″ Color=”Yellow” />
<GradientStop Offset=”1″ Color=”Red”/>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Grid.Background>
<Grid.RowDefinitions>
<RowDefinition Height = “25” />
<RowDefinition Height = “15” />
<RowDefinition Height = “20”/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width=”150″ />
<ColumnDefinition Width=”350″/>
</Grid.ColumnDefinitions>
<TextBlock Width=”100″
Height=”20″
Text=”Hello,”
Grid.Row=”1″ />
<TextBlock x:Name=”textName”
Width=”100″
Height=”30″
Text=”UserName”
Grid.Row=”2″ />
<TextBlock Text=”Please vote for your favorite technology”
Grid.Row=”0″
Grid.Column=”1″ />
<RadioButton x:Name=”radFlash”
Content=”Adobe Flash”
Grid.Row=”1″ Grid.Column=”1″ />
<RadioButton x:Name=”radSilverlight”
Content=”Microsoft Silverlight” Grid.Row=”2″ Grid.Column=”1″ />
</Grid>
</UserControl>

In this code we will add a grid, mark it up and insert controls. We then will compile the code by pressing the F5 key. When completed, this will create a file titled banner.xap, which is the Silverlight clip itself. Its size is less than 5 Kb. Later we will place the file in the resources for our Qt application.

Creating a Qt application
We will begin a new Banner project. Create a separate folder for the project and place the banner.pro file inside of it:

TEMPLATE = app
CONFIG += msvc2008
QTITANDIR = $$(QTITANDIR)
include($$QTITANDIR/src/shared/shared.pri)
DESTDIR = $$QTITANDIR/lib
DLLDESTDIR = $$QTITANDIR/bin

CONFIG(msvc2008):DESTDIR = $$member(DESTDIR, 0)_msvc2008
CONFIG(msvc2008):DLLDESTDIR = $$member(DLLDESTDIR, 0)_msvc2008

HEADERS = mainwindow.h
SOURCES = main.cpp
mainwindow.cpp
RESOURCES = banner.qrc

The project is based on a sample provided with Qtitan. You can find samples in the folder Qtitan/demos/media. In this case we are using the hellosilverlight sample as the basis for our project.
We then add our Silverlight clip, banner.xap, as an application resource.
To do this, in the project folder we will create a res folder and place the banner.xap file inside of it. In the project folder we will then create a file entitled banner.qrc:

<!DOCTYPE RCC><RCC version=”1.0″>
<qresource>
<file>res/banner.xap</file>
</qresource>
</RCC>

We then add the file main.cpp to the project folder:

#include <QApplication>
#include “mainwindow.h”

int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MainWindow window;
window.show();
return app.exec();
}

This is a standard main.cpp file which creates an instance of QApplication and calls the application’s main window, MainWindow.
Now we will write the files mainwindow.h and mainwindow.cpp.
In the file mainwindow.h we will include the file QtitanMM.h:

#include <QtitanMM.h>

And we will add a pointer to Qtitan::Silverlight to the protected portion of the MainWindow class. The header for the MainWindow class now looks like this (the file mainwindow.h):

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QLineEdit>
#include <QtitanMM.h>

class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = 0);
protected slots:
void clickButton();
void getUrl(NPluginStreamArgs& parameters);
protected:
Qtitan::Silverlight * silverlight_;
QLineEdit * edtName_;
};
#endif //MAINWINDOW_H

Beginning of class implementation (file mainwindow.cpp):
#include <QtGui>
#include “mainwindow.h”

MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
// Central widget
QWidget * widget = new QWidget(this);
QVBoxLayout * vLayout = new QVBoxLayout;
widget->setLayout(vLayout);
setCentralWidget(widget);

// Create a widget for the clip
silverlight_ = new Qtitan::Silverlight(widget);
// Set size
silverlight_->setMinimumSize(468, 60);
silverlight_->setSource(“banner.xap”);
// Set connection with clip
connect(silverlight_, SIGNAL(getUrl(NPluginStreamArgs&)),
this, SLOT(getUrl(NPluginStreamArgs&)));
// Active clip
silverlight_->setActive(true);
// Verify activation result
if (!silverlight_->isActive())
{
// Notify if clip is inactive
QMessageBox::about(this, tr(“Hello, Silverlight!”),
tr(“The <b>Microsoft Silverlight</b> is not installed at your PC.”));
}
// Additional controls
QLabel * lblName = new QLabel(“Name: “, this);
edtName_ = new QLineEdit(this);
QPushButton * btnName = new QPushButton(“Name”, this);
btnName->setMaximumWidth(120);

// Arrange objects
QHBoxLayout * hLayout = new QHBoxLayout;
hLayout->addWidget(lblName);
hLayout->addWidget(edtName_);
vLayout->addWidget(silverlight_);
vLayout->addLayout(hLayout);
vLayout->addWidget(btnName, 0, Qt::AlignRight);
vLayout->addStretch();
// Connect to button
connect(btnName, SIGNAL(clicked()), this, SLOT(clickButton()));
}

void MainWindow::getUrl(NPluginStreamArgs& parameters)
{
QFile* data = new QFile(“:/res/banner.xap”);
data->open(QIODevice::ReadOnly);
parameters.setIODevice(data);
}

Here we have created a project for our application: on top is a banner, and just below it is an input field for entering the user’s name, and the Name button, which when clicked will send our name to the banner.
Pay special attention to the line linking the Qtitan::Silverlight component together with the Silverlight clip directly. The link is made through the standard slot/signal mechanism:
connect(silverlight_, SIGNAL(getUrl(NPluginStreamArgs&)),
this, SLOT(getUrl(NPluginStreamArgs&)));

Using this link, the instance of Qtitan::Silverlight gains access to our clip’s resources. The getUrl(NPluginStreamArgs&) slot gets a link to the object to which it passes the clip data.
Now we can launch our application and view the result: we see that the clip has been successfully integrated into the application.
http://www.devmachines.com/images/article_silverlight/index_004.png
Now we will write a handler for the btnName button, so that when clicked, the entered text is passed to the Silverlight clip.
We will add a connect for the button to the MainWindow constructor:

connect(btnName, SIGNAL(clicked()), this, SLOT(clickButton()));

With the following handler code:

void MainWindow::clickButton()
{
// Get access to clip functions
QScriptValue silverlightObject = silverlight_->pluginScriptValue();
// Call Silverlight clip function and pass it as parameter
// text from editName_ input field
QScriptValue content = silverlightObject.property(“content”);
QScriptValue silverlightForm = content.property(“BannerForm”);
QScriptValue func = silverlightForm.property(“SetUserNameMethod”);
func.call(silverlightForm, QScriptValueList() << edtName_->text());
}

In effect, here we are calling on the JavaScript code:
silverlightObject.content.BannerForm.SetUserNameMethod(“text”);
We could in fact call on it immediately by using the evaluate() method from the QScriptEngine class. We should not forget to declare the clickButton() slot in the closed portion of the MainWindow class.

protected slots:
void clickButton();

For this code to work, the BannerForm object and SetUserNameMethod method should be registered in the Silverlight clip. We should return to the Silverlight project and open the Page.xaml.cs page.
http://www.devmachines.com/images/article_silverlight/index_005.png
We will edit the page code as follows. First, we will add a line for browser access
using System.Windows.Browser;
Second, before declaring the Page class we will add the line
[ScriptableType]

This is necessary so that the BannerForm object can be registered.
Registration itself is done in the Page class constructor.
HtmlPage.RegisterScriptableObject(“BannerForm”, this);
Additionally, the SetUserNameMethod method needs to be registered. The full code for the Page.xaml.cs page is given below.

using System.Windows.Browser;
namespace banner
{
[ScriptableType]
public partial class Page : UserControl
{
public Page()
{
InitializeComponent();
HtmlPage.RegisterScriptableObject(“BannerForm”, this);
}
[ScriptableMember]
public void SetUserNameMethod(string text)
{
textName.Text = text;
}
}
}

We then compile the project and copy the resulting file banner.xap to the resources for the Qt application. We rebuild the application and launch it. Now whenever the button is clicked, our name (entered in the editName_ input field) will be passed to the clip and displayed there.
http://www.devmachines.com/images/article_silverlight/index_006.png
Now we need to get the voting results from the Silverlight clips. We will again have to return to the project for the Silverlight clip and make changes to it. First, we will need to define the event handers for the radio button controls. We will define the handlers in the XAML code:

<RadioButton x:Name=”radFlash”
Content=”Adobe Flash”
Grid.Row=”1″ Grid.Column=”1″
Checked=”Flash_Click”/>
<RadioButton x:Name=”radSilverlight”
Content=”Microsoft Silverlight”
Grid.Row=”2″ Grid.Column=”1″
Checked=”Silverlight_Click”/>
We will write the code for them in the file Page.xaml.cs in the body of the Page class:

private void Flash_Click(object sender, RoutedEventArgs e)
{
HtmlPage.Window.Invoke(“ShowCustomMessage”, “I vote for Adobe Flash!”);
}
private void Sliverlight_Click(object sender, RoutedEventArgs e)
{
HtmlPage.Window.Invoke(“ShowCustomMessage”, “I vote for Microsoft Silverlight!”);
}

In other words, the clip calls on a ShowCustomMessage function, which to it looks like a regular JavaScript function. Actually, this function is defined in our Qt application and we will register it in the clip directly from the application.We compile the clip and add it to the application’s resources. We then open our Qt project and add a line for registering the ShowCustomMessage function to the constructor for the MainWindow class:
silverlight_->registrScriptableFunction(“ShowCustomMessage”, ShowCustomMessage);

And then we will define the ShowCustomMessage function itself:
QScriptValue MainWindow::ShowCustomMessage(QScriptContext* context, QScriptEngine *)
{
QMessageBox::information(qApp->activeWindow(), “Vote”, context->argument(0).toString());
return QScriptValue();
}
In the mainwindow.h header fil

Article Source: http://www.articlesnatch.com

About the Author:
Product manager at Developer Machines

About the Author:

Comments are closed.