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


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 <vector>
#include <memory>

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<std::shared_ptr<ImplData>> 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<ImplData> 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<IList<string>, double> EnumerateZipFileAsync(StorageFile file)
{
return AsyncInfo.Run(async delegate(
System.Threading.CancellationToken cancellationToken, IProgress<double> progress)
{
IList<string> fileList = new List<string>();
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:

Comments (13)

  1. Ben Gracewood says:

    Did you guys not get the "No more Metro" memo?

  2. small_mountain says:

    @Ben – Ines' use of the term "Metro" is clearly an act of rebellion!

  3. aL says:

    The winRT stuff is great but what we really need is to be able to call winRT from desktop apps as well… not beeing able to make custom winRT libraries and not use winRT xaml for desktop apps is not only fragmenting the platform, its a serious inhibitor for winRT adoption.  it also widens the graphical gap between metro and desktop apps, causing people who where not to fond of metro to adopt it more slowly

    please enable this microsoft..

  4. Danijel says:

    What audio codecs/formats does WinRT support? Does it depend on the machine app is running on? Can I expect WinRT (Metro) apps to support most popular audio formats (mp3/wma/aac/FLAC…) on all Windows 8 devices (ARM and x86-64, desktop/laptop/tablet) by default?

  5. Metro is not an option for me therefore Windows 8 won't be installed on my PC because i find it unusable in every way. I hope MS changes their objective because WinRT (Metro in general) does bring 0 value to PC. Again Smart Phones, Tablets do not qualify as PC but PM -> Personal Mobile which is entirely different Eco System for which WinRT makes sense in many ways. The things are very simple, MS had good idea but execution was poor. It is so ridicilous that developers accept idea of WinRT on PC where it lacks, not even close to Win32.

    I hope MS changes their goal with Windows 9 because it will determine the fate of company itself. I am not pulling this out of hat but talking from 25 years of experience.

    Metro was failure with Zune

    Metro was failure with WP7

    Windows 8 will be failure because of Metro as well

    I am not sure where MS does their research and pull conclusions out of it, but they do it incredible wrong.

  6. I want to add few more things, Windows 8 will have hard time competing Windows 7 which is almost perfection. Windows 8 UI makes my eyes commit suicide after working in Windows 7 whose Aero UI is something beautiful. Windows 8 UI -> flat, boring, lifeless UI just so PC can be stripped down to the level of device which does not even qualify as PC namely called Windows 8 Phone so MS could win some mobile market share the one they lost against Apple and Android long ago. Rather sad….

    Not saying MS should not compete in that area but leave Windows alone and go with a new OS made just for Tablets, Phone and similar devices. Who says we need same interface for every device running Windows. WE DO NOT. We just need some common features and a perfect example of it is Microsoft Sky Drive App for Windows 7 Desktop. It does perfect. I am expecting Windows on my Desktop to act as real Windows and not some Flat Screen with big squares and enlarged icons which look without taste. When i am on phone i want to see interface which suits that device and Metro works there. Imagine bringing Desktop interface to Phone??? Crazy, i know…

  7. Rodrigo Mendoza says:

    Tengo el windows 8 hace ya un tiempo y no pasa naaa con el metro. Al principio novedoso pero después pesado en el manejo… vuelvan al botón de windows…. que es muy era bueno.

  8. MSDN Lite says:

    Aren't these posts just republishing content already on MSDN?

  9. P says:

    Would you please write down some more on available classes? I don't mean only UI components, but also Reflection. E.g. Could I use the DynamicMethod in a same way as I did on Windows Phone 7.5? Are there any major changes? If I recompile my WP7.5 app (without the UI) to WinRT should I expect any issues?

  10. Alan says:

    "You can now create a single Windows Runtime-exposed XAML library of custom controls that both C++ and C# app developers can consume." Do I understand correctly that it can't be consumed from a HTML/JS based app? What is the recommended approach (if any) to create a 3rd party control that can be consumed from all of the WinRT "platforms"?

  11. C says:

    @Alan, read the sentence again 🙂 It states "XAML library of controls…". XAML controls have no place in HTML5 Win8 apps. You can write non-UI components in C++ (or C# for that matter) that can be used across all supported runtimes/languages on Win8. You can't write shareable components in JavaScript.

  12. Alan says:

    @C: yes, I've read the sentence and that what the question is about. The point that the control was built in XAML is not more valid that if you'd say that a control built with C# can't be consumed in VB. The technology used to create a supposedly native component shouldn't be important to the way it is consumed.

  13. Joe White says:

    Hmm, it's a bit discouraging that nobody from MS has responded to any of the questions posted here. But I'll go ahead and post my questions anyway:

    1. Why do the classes need to be static? I've heard that mentioned before, but there's never been any explanation.

    2. If Windows 8 is supposed to be about "no compromises" and "unifying the input platform", then why do we need to write low-level C++ code to get game-controller input? Why isn't that part of the unified input?

    3. What about exceptions? If my component encounters an error condition, and I throw a carefully-chosen exception type, with a nice, descriptive, actionable exception message, would the code consuming my component (whether written in the same language as my component or a different language) actually get that meaningful exception? Or would it just get a generic "COM error", with absolutely no meaningful details, like what WinRT does whenever it gets an error?