Quantcast
Channel: Category Name
Viewing all articles
Browse latest Browse all 10804

Building your own Windows Runtime components to deliver great Metro style apps

$
0
0

For Windows 8, we completely reimagined the platform, allowing you to choose the programming language and technologies you already know to build apps tailored to the device and form factor. With the Windows Runtime, you can even easily use multiple languages within a single app. You can build a great Metro style app with HTML and JavaScript that can interact with the Xbox 360 controller through building your own Windows Runtime component in C++. You can build reusable XAML controls exposed via Windows Runtime components that are instantly consumable by Metro style apps written in both C++ and C#. Essentially, we have let you build apps on the Windows 8 platform using the languages of your choice with no comprises.

In this blog post, we talk about what you need to know to build your own Windows Runtime components.

The basics

The Windows Runtime is at the heart of empowering language choice. It exposes so that you can call them from JavaScript, C++, C# and Visual Basic in a way that’s natural and familiar. This same foundation is available to you when building your own APIs too.

A Windows Runtime component that you build and package in your app is typically referred to as a 3rd party Windows Runtime component. This differs from 1st party components that are already part of the Windows 8 platform. You can write these 3rd party Windows Runtime components in C++, C# or Visual Basic. You can call into the APIs they expose from anywhere, including other Windows Runtime components packaged into your app. You can also call into the APIs exposed via Windows Runtime components from any language.

The Windows Runtime components that you write for your app can use Windows Runtime APIs, Win32, COM, .NET APIs or 3rd party libraries as long as they are supported for Metro style app development. Note that the Windows Runtime components that you build are different from what you traditionally know as C++ DLLs or .NET assemblies that expose APIs. Creating a class library in .Net or a standalone DLL in C++ is not the same as building a Windows Runtime component. Windows Runtime components are declared in .wnmd files that expose Windows Runtime metadata and enable languages such as JavaScript to naturally consume Windows Runtime APIs (for example, pascalCasedNames support for APIs exposed to JavaScript). The Windows Runtime metadata also enables Visual Studio to provide great tooling capabilities such as IntelliSense support.

Why build your own Windows Runtime components

Creating Windows Runtime components can help you architect for reusability and language interoperability. Let’s take a look at some app scenarios that showcase how you can use 3rd party Windows Runtime components to build better experiences.

You can integrate your Metro style app with the Xbox 360 Controller for Windows
Figure1: Xbox 360 Controller

Using Win32 and COM APIs in your Metro style app

The platform provided by Internet Explorer 10 enables you to create great Metro style app experiences using HTML, CSS and JavaScript. But what if you have built a game using HTML5 canvas and want to integrate with the Xbox 360 controller for Windows? The XInput API, which allows apps to receive input from the controller, exposes Win32 APIs that are not available directly to JavaScript.

This is a great example of where creating a Windows Runtime component can solve this problem and give you the ability to use the XInput APIs in your HTML based Metro style app. The XInput and JavaScript controller sketch sample showcases exactly that. The sample app contains a game controller Windows Runtime component written in C++ which wraps the functionality exposed by the XInput APIs. The controller sketch HTML-based app uses the game controller C++ Windows Runtime component to enable the interaction with the Xbox 360 controller.

This scenario, impossible to accomplish using HTML and JavaScript alone, is a perfect example of where creating a 3rd party Windows Runtime component allows you to complete a complex scenario that you otherwise wouldn’t be able to.

Computationally Intensive Operations

Apps created for fields like science, engineering, and maps/geography often have computationally intensive operations. These intensive operations typically require powerful parallel processing and are well suited for C++ to achieve optimal performance. In Developing Bing Maps Trip Optimizer, a Metro style app in JavaScript and C++ , we see another scenario where creating a Windows Runtime component in C++ allows us to create the best experience in our app.

You wonder why anyone would want to calculate a trip route on local data at all when we could run this computationally intensive task in the cloud on Bing servers. Bing Maps exposes JavaScript APIs to do this, but sometimes an app must run offline. And we also want the user to drag and change the route in real time with touch. If we can run these intense operations locally, we create an even better experience.

By writing our compute-intensive operation in C++ using the parallel task library, we can harness the power of the client to create a great experience for users. Windows Runtime is a great fit for this scenario, allowing us to create our rich client User Interface (UI) in HTML and JavaScript with the Bing Maps AJAX control while running all of our intensive route operations using C++ code that calculates quickly using parallelization.

Libraries

The community is filled with great libraries that developers put together and shared for everyone to use. In the past, you may have found it challenging to reuse some of these libraries if they didn’t match the programming language your app was implemented in. For example, you built a great .NET app, but couldn’t use a library written in C++ without going through painful interop hoops like PInvoke.

Windows Runtime bridges the language gap in Windows 8, making it possible for a single Windows Runtime component library with a single code base to reach a broader set of developers irrespective of the component’s language or your app’s primary programming language.

You can now create a single Windows Runtime-exposed XAML library of custom controls that both C++ and C# app developers can consume. And you can use various data storage Windows Runtime libraries shared out by developers in your XAML or HTML based Metro style apps. All of these scenarios are possible without the burden of writing any interop code.

We think Windows Runtime will be a boon to the libraries that developers create and share broadly for the community of Metro style app developers. Let’s now take a look at two concrete examples showing the basics of building a 3rd party Windows Runtime component in C++/CX and C#.

Scenario 1: Enhancing your app with native audio

Say we are building a software synthesizer app using XAML backed by app logic written in C#. To add filter support to our music app, we would like to use XAudio to have direct control of audio buffers.

Adding the Windows Runtime component to our solution

Using Visual Studio, we add a new C++ Windows Runtime component project to our existing solution. This Windows Runtime component wraps the music processing functionality:

Using Visual Studio to add a new C++ Windows Runtime Component to our music app
Figure 2: Adding a new C++ Windows Runtime Component

Visual Studio created a C++ project for us to expose APIs for which the implementation will be packaged in a DLL and the Windows Runtime metadata in a winmd file. Both are made available to our C# project.

Defining the class exposed to our XAML C# project

We use C++/CX to build the APIs that will be exposed to our C# project, but you also can use the Windows Runtime C++ Template Library (WRL). We start by defining a fairly basic class to encapsulate the XAudio functionality:

XAudioWrapper.h

#pragma once

#include "mmreg.h"
#include
#include

namespace XAudioWrapper
{
public ref class XAudio2SoundPlayer sealed
{
public:
XAudio2SoundPlayer(uint32 sampleRate);
virtual ~XAudio2SoundPlayer();

void Initialize();

bool PlaySound(size_t index);
bool StopSound(size_t index);
bool IsSoundPlaying(size_t index);
size_t GetSoundCount();

void Suspend();
void Resume();

private:
interface IXAudio2* m_audioEngine;
interface IXAudio2MasteringVoice* m_masteringVoice;
std::vector> m_soundList;
};
}

You will first notice the usage of the public, ref and sealed keywords in the class declaration. For a class to be instantiated from another language such as JavaScript or C# in a Metro style app, the class must be declared as public ref class sealed.

The public functionality (methods, properties …) of the class are limited to C++ built-in types or Windows Runtime types. Those are the only types allowed for crossing the language boundary in Windows Runtime components. That being said, you can use the regular C++ library (i.e.: Standard Template Library collections) for the private data members of your class as shown in this code snippet. Those private data members don’t have to follow the rules associated with crossing the language boundary. The Visual Studio compiler emits error messages and provides guidance if you use unsupported constructs.

Implementing the class exposed in our Windows Runtime component

Now that we have defined the basic interface for our class, let’s take a look at some of the implemented methods:

XAudioWrapper.cpp

XAudio2SoundPlayer::XAudio2SoundPlayer(uint32 sampleRate) :
m_soundList()
{
// Create the XAudio2 engine
UINT32 flags = 0;

XAudio2Create(&m_audioEngine, flags);

// Create the mastering voice
m_audioEngine->CreateMasteringVoice(
&m_masteringVoice,
XAUDIO2_DEFAULT_CHANNELS,
sampleRate
);
}

void XAudio2SoundPlayer::Resume()
{
m_audioEngine->StartEngine();
}

bool XAudio2SoundPlayer::PlaySound(size_t index)
{
//
// Setup buffer
//
XAUDIO2_BUFFER playBuffer = { 0 };
std::shared_ptr soundData = m_soundList[index];
playBuffer.AudioBytes = soundData->playData->Length;
playBuffer.pAudioData = soundData->playData->Data;
playBuffer.Flags = XAUDIO2_END_OF_STREAM;

HRESULT hr = soundData->sourceVoice->Stop();
if (SUCCEEDED(hr))
{
hr = soundData->sourceVoice->FlushSourceBuffers();
}

//
// Submit the sound buffer and (re)start (ignore any 'stop' failures)
//
hr = soundData->sourceVoice->SubmitSourceBuffer(&playBuffer);
if (SUCCEEDED(hr))
{
hr = soundData->sourceVoice->Start(0, XAUDIO2_COMMIT_NOW);
}

return SUCCEEDED(hr);
}

In this code snippet, we are just using the XAudio2 COM APIs available for Metro style app development to wire up our audio engine, play sound and resume the engine. Additionally, we can use C++ constructs and types beyond just the Windows Runtime types to implement the necessary functionality.

Adding and consuming the Windows Runtime component

After we define and implement our basic class, we use Visual Studio to add the XAudioWrapper Windows Runtime component to our C++ project from our C# project:

Using Visual Studio to add a reference to the XAudioWrapper Windows Runtime Component in our music app

Figure 3: Adding the XAudioWrapper Windows Runtime Component to our music app

As a result, the class that we expose from our C++ project becomes available to our C# project:

MainPage.cs

using XAudioWrapper;

namespace BasicSoundApp
{
public sealed partial class MainPage : Page
{
XAudio2SoundPlayer _audioPlayer = new XAudio2SoundPlayer(48000);
public MainPage()
{
this.InitializeComponent();
}

protected override void OnNavigatedTo(NavigationEventArgs e)
{
_audioPlayer.Initialize();
}

private void Button_Click_1(object sender, RoutedEventArgs e)
{
_audioPlayer.PlaySound(0);
}
}
}

As shown in the code snippet, we can interact with our XAudio wrapper from C# just as if it were a regular .NET component. We reference its namespace, instantiate the component and start invoking the various methods it exposes. All of this without requiring any DllImports to call into the native code!

Scenario 2: Using built-in APIs to open a zip file from your app

Say we are also building a file viewer app using HTML and want to add functionality to allow users of this app to pick zip files. We want to use the APIs already built-into Windows and exposed in the .NET platform for handling zip files.

Adding the Windows Runtime component to our solution

This is the same step as we have described for our music app, but we now pick the C# Windows Runtime component to wrap the zip processing functionality:

Using Visual Studio to add a new C# Windows Runtime Component to our file viewer app
Figure 4: Adding a new C# Windows Runtime Component 

Visual Studio has created a C# project for us to expose the APIs for which both the implementation and Windows Runtime metadata are packaged in a .winmd file and made available to our web project.

Implementing the class exposed in our Windows Runtime component

We use C# to build the APIs that will be exposed to our web project, but you can also use Visual Basic. We start by defining a simple C# class to encapsulate the zip functionality:

ZipWrapper.cs

using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Threading.Tasks;
using Windows.Foundation;
using Windows.Storage;

public sealed class ZipWrapper
{
public static IAsyncOperationWithProgress, double> EnumerateZipFileAsync(StorageFile file)
{
return AsyncInfo.Run(async delegate(
System.Threading.CancellationToken cancellationToken, IProgress<double> progress)
{
IList fileList = new List();
progress.Report(0);

using (var stream = await file.OpenStreamForReadAsync())
{
using (var archive = new ZipArchive(stream))
{
for (int i = 0; i < archive.Entries.Count; i++)
{
// add code for processing/analysis on the file
// content here

// add to our list and report progress
fileList.Add(archive.Entries[i].FullName);
double progressUpdate = ((i + 1) / ((double)archive.Entries.Count)) * 100; // percentage
progress.Report(progressUpdate);
}
}
}

progress.Report(100.0);
return fileList;
});
}
}

This class is public and sealed. Similarly to building C++ Windows Runtime components, this is necessary for other languages to instantiate the class. The static method exposed in the class uses a mixture of Windows Runtime types (such as StorageFile) and as .NET types (such as IList) in the method signature. The rule of thumb is to use Windows Runtime types for defining the public fields, parameters and return types that will be exposed to the other languages. That being said, you can use certain .NET fundamental types (i.e.: DateTimeOffset and Uri) and primitives (i.e.: IList) as is.

You will also notice that the method above leverages the Windows Runtime infrastructure for async and progress support that you can (and should) use when defining your Windows Runtime components. As far as the implementation for the Windows Runtime component or any private functionality in the class, you are not limited to only using Windows Runtime types and APIs; you are free to use any of the .NET API surface exposed for Metro app development as shown in the code snippet ZipArchive APIs.

Adding and consuming the Windows Runtime component

Now that we have implemented our zip tool wrapper, we use Visual Studio to add a reference to our C# project from our JavaScript project:

Using Visual Studio to add a reference to the ZipUtil Windows Runtime component in our file viewer app
Figure 5: Adding the ZipUtil Windows Runtime component to our file viewer app

As a result, the class that we have exposed from our C# project becomes available to our web project:

program.js

function pickSinglePhoto() {

// Create the picker object for picking zip files
var openPicker = new Windows.Storage.Pickers.FileOpenPicker();
openPicker.viewMode = Windows.Storage.Pickers.PickerViewMode.thumbnail;
openPicker.suggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.picturesLibrary;
openPicker.fileTypeFilter.replaceAll([".zip"]);

// Open the picker for the user to pick a file
openPicker.pickSingleFileAsync().then(function (file) {
if (file) {
ZipUtil.ZipWrapper.enumerateZipFileAsync(file).then(
function (fileList) {
for (var i = 0; i < fileList.length; i++)
document.getElementById('output').innerHTML += " " + fileList[i];
},
function (prog) {
document.getElementById('zipProgress').value = prog;
}
);
} else {
document.getElementById('output').innerHTML = "an error occurred";
}
});
};

As you can see, we can interact with our zip tool wrapper from JavaScript just as if it were a regular JavaScript object. We can call into the static method exposed in our Windows Runtime component, and we can do so using JavaScript’s async language constructs such as .then().

General guidance

Not every API you write for your Metro style app should be exposed as a 3rd party Windows Runtime component. In general, use Windows Runtime types when you are communicating between programming languages and use types and constructs that are built into the language that you are using for functionality that is not publicly exposed via a Windows Runtime component. Additionally, there are various language-specific features and rules around crossing the language boundary that you need to take into consideration when building your Windows Runtime component. This includes delegates and events, asynchronous operations, method overloading, handling specific data types such as collections, exception handling and debugging tips. You can dive into those topics further by visiting the section on building Windows Runtime components for your development language.

In closing

With Windows Runtime components, you can now mix programming languages and API technologies to build the apps you envision. Windows 8 is about no compromises. There are even no compromises during development, allowing you to mix and match the programming languages that best fit your scenario. We hope this allows you to spend more time thinking about innovation and less time being forced to learn a completely new programming language.

Happy app building!

-- Ines Khelifi, Program Manager, Windows

References

In this post, we have merely scratched the surface of what’s possible with building Windows Runtime components. Here are additional resources to help you dive into this further for your app development:


Viewing all articles
Browse latest Browse all 10804

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>