Criando componentes do Tempo de Execução do Windows próprios para oferecer excelentes aplicativos estilo Metro

Blog do desenvolvedor de aplicativos do Windows 8

Ideias sobre a criação de aplicativos com o estilo Metro para o Windows 8, da equipe de engenharia do Windows 8

Criando componentes do Tempo de Execução do Windows próprios para oferecer excelentes aplicativos estilo Metro

  • Comments 0

No Windows 8, reimaginamos totalmente a plataforma, permitindo que você escolha a linguagem de programação e as tecnologias que já conhece para criar aplicativos voltados para o dispositivo e o fator forma. Com o Tempo de Execução do Windows, você pode até usar facilmente várias linguagens em um único aplicativo. Você pode criar um ótimo aplicativo estilo Metro com HTML e JavaScript, que pode interagir com o controlador do Xbox 360, criando o seu próprio componente do Tempo de Execução do Windows em C++. Você pode criar controles XAML reutilizáveis expostos pelos componentes do Tempo de Execução do Windows, que podem ser consumidos pelos aplicativos estilo Metro escritos tanto em C++ quanto em C#. Basicamente, permitimos que você crie aplicativos na plataforma do Windows 8 usando as linguagens que preferir sem comprometimentos.

Nesta postagem, falaremos sobre o que você precisa saber para criar os seus componentes do Tempo de Execução do Windows.

Noções básicas

O Tempo de Execução do Windows é o responsável pela possibilidade de escolha da linguagem. Ele é exposto de forma que você possa chamá-los de JavaScript, C++, C# e Visual Basic de maneira natural e familiar. Esse mesmo princípio também estará disponível quando você criar as suas próprias APIs.

Um componente do Tempo de Execução do Windows criado e incluído no seu aplicativo é normalmente chamado de Componente do Tempo de Execução do Windows de terceiro. Ele difere dos componentes primários que já fazem parte da plataforma do Windows 8. Você pode escrever esses componentes do Tempo de Execução do Windows de terceiro em C++, C# ou Visual Basic. Você pode chamar para as APIs expostas por eles de qualquer lugar, incluindo outros componentes do Tempo de Execução do Windows incluídos no seu aplicativo. Você também pode chamar para as APIs expostas via componentes do Tempo de Execução do Windows usando qualquer linguagem.

Os componentes do Tempo de Execução do Windows que você escrever para o seu aplicativo poderão usar APIs do Tempo de Execução do Windows, Win32, COM, .NET APIs ou bibliotecas de terceiros contanto que eles tenham suporte para o desenvolvimento de aplicativos estilo Metro. Observe que os componentes do Tempo de Execução do Windows criados por você são diferentes do que você tradicionalmente conhece como C++ DLLs ou assemblies .NET que expõem APIs. A criação de uma biblioteca de classes em .Net ou DLL anônimo em C++ não é o mesmo que criar um componente do Tempo de Execução do Windows. Os componentes do Tempo de Execução do Windows são declarados em arquivos .wnmd que expõem metadados do Tempo de Execução do Windows e permitem que linguagens como JavaScript consumam naturalmente as APIs do Tempo de Execução do Windows (por exemplo, suporte de pascalCasedNames para APIs expostas para JavaScript). Os metadados do Tempo de Execução do Windows também permitem que o Visual Studio forneça ótimas funcionalidades de ferramentas, como o suporte ao IntelliSense.

Por que criar os seus próprios componentes do Tempo de Execução do Windows

A criação de componentes do Tempo de Execução do Windows pode ajudá-lo a criar arquitetura para a reutilização e a interoperabilidade de linguagens. Vejamos alguns cenários de aplicativos que demonstram como você pode usar componentes do Tempo de Execução do Windows de terceiro para criar experiências melhores.

Você pode integrar o seu aplicativo estilo Metro ao controlador do Xbox 360 para Windows
Figura 1: Controlador do Xbox 360

Usando APIs COM e Win32 no seu aplicativo estilo Metro

A plataforma fornecida pelo Internet Explorer 10 permite que você crie ótimas experiências com aplicativos estilo Metro usando HTML, CSS e JavaScript. E se você tiver criado um jogo usando canvas HTML5 e deseja integrá-lo com o controlador do Xbox 360 para Windows? A API XInput, que permite que os aplicativos recebam entrada do controlador, expõe as APIs do Win32 que não estão disponíveis diretamente para JavaScript.

Esse é um ótimo exemplo de solução de problema com a criação de um componente do Tempo de Execução do Windows e oferece a você a capacidade de usar as APIs XInput no seu aplicativo estilo Metro baseado em HTML. A amostra de projeto de controlador com XInput e JavaScript demonstra exatamente isso. O aplicativo do exemplo contém um componente do Tempo de Execução do Windows com controlador de jogo escrito em C++, que encapsula a funcionalidade exposta pelas APIs XInput. O aplicativo baseado em HTML do projeto do controlador usa o componente do Tempo de Execução do Windows em C++ de controlador de jogo para permitir a manipulação com o controlador do Xbox 360.

Esse cenário, que seria impossível usando somente HTML e JavaScript, é um exemplo perfeito de como somente a criação de um componente do Tempo de Execução do Windows de terceiros permite um cenário complexo.

Operações de uso intensivo do computador

Os aplicativos criados para áreas como ciência, engenharia e cartografia/geografa normalmente têm operações que usam o computador de forma intensiva. Essas operações intensivas normalmente exigem um processamento paralelo potente e são ideais para C++, para atingir um desempenho ótimo. Em Developing Bing Maps Trip Optimizer, a Metro style app in JavaScript and C++ (Desenvolvendo o otimizador de viagens com o Bing Maps, um aplicativo estilo Metro em JavaScript e C++) , vemos outro cenário em que a criação de um componente do Tempo de Execução do Windows em C++ nos permite criar a melhor experiência no nosso aplicativo.

Você pode se perguntar por que alguém calcularia uma roteiro de viagem nos dados locais quando é possível executar essa tarefa de uso intensivo do computador na nuvem, nos servidores do Bing. O Bing Maps expõe as APIs JavaScript para fazer isso, mas, às vezes, um aplicativo deve ser executado offline. E também desejamos que o usuário arraste e altere o roteiro em tempo real com o toque. Podendo executar essas operações de uso intensivo localmente, criamos uma experiência ainda melhor.

Ao escrever a nossa operação de uso intensivo do computador em C++ usando a biblioteca de tarefas paralela, podemos utilizar a potência do cliente para criar uma ótima experiência para os usuários. O Tempo de Execução do Windows se encaixa perfeitamente nesse cenário, permitindo que criemos a nossa interface do usuário do cliente avançada em HTML e JavaScript com o controle AJAX do Bing Maps, executando, ao mesmo tempo, todas as nossas operações intensivas de roteiro usando o código C++ que faz cálculos rápidos usando a paralelização.

Bibliotecas

A comunidade está repleta de ótimas bibliotecas que foram reunidas e compartilhadas pelos desenvolvedores para serem usadas por todos. Antes, talvez tenha sido um desafio reutilizar algumas dessas bibliotecas quando elas não correspondiam à linguagem de programação em que o seu aplicativo havia sido implementado. Por exemplo, você criava um ótimo aplicativo .NET, mas não podia usar uma biblioteca escrita em C++ sem passar por dificuldades de interoperabilidade, como o PInvoke.

O Tempo de Execução do Windows serve de ponte entre as linguagens no Windows 8, tornando possível a uma única biblioteca com o componente do Tempo de Execução do Windows e uma única base de código atingir um conjunto maior de desenvolvedores independentemente da linguagem do componente ou da linguagem de programação primária do seu aplicativo.

Agora você pode criar uma única biblioteca em XAML de controles personalizados, exposta pelo Tempo de Execução do Windows, que os desenvolvedores de aplicativos em C++ e C# possam consumir. E você pode usar várias bibliotecas de armazenamento de dados do Tempo de Execução do Windows compartilhadas pelos desenvolvedores nos seus aplicativos estilo Metro baseados em XAML ou HTML. Todos esses cenários são possíveis sem a chatice de precisar escrever códigos de interoperabilidade.

Acreditamos que o Tempo de Execução do Windows será uma enorme vantagem para as bibliotecas criadas e compartilhadas amplamente pelos desenvolvedores para a comunidade de desenvolvedores de aplicativos estilo Metro. Vejamos agora dois exemplos concretos que mostram o básico da criação de um componente do Tempo de Execução do Windows de terceiro em C++/CX e C#.

Cenário 1: Aperfeiçoando o seu aplicativo com áudio nativo

Vamos supor que estamos criando um aplicativo sintetizador de software usando XAML baseada em lógica de aplicativo escrita em C#. Para adicionar suporte de filtro ao nosso aplicativo de música, gostaríamos de usar o XAudio para controlar diretamente o buffer de áudio.

Adicionando o componente do Tempo de Execução do Windows à nossa solução

Usando o Visual Studio, adicionamos um novo projeto do componente do Tempo de Execução do Windows em C++ à nossa solução existente. Esse componente do Tempo de Execução do Windows encapsula a funcionalidade de processamento da música:

Usando o Visual Studio para adicionar um novo componente do Tempo de Execução do Windows ao nosso aplicativo de música
Figura 2: Adicionando um novo componente do Tempo de Execução do Windows em C++

O Visual Studio criou um projeto em C++ no qual poderemos expor APIs cuja implementação será incluída em uma DLL e os metadados do Tempo de Execução do Windows, em um arquivo winmd. Os dois são disponibilizados para o nosso projeto C#.

Definindo a classe exposta para o nosso projeto C# em XAML

Usamos C++/CX para criar as APIs que serão expostas para o nosso projeto C#, mas você também pode usar a WRL (Biblioteca de Modelos C++ do Tempo de Execução do Windows). Começamos pela definição de uma classe básica para encapsular a funcionalidade XAudio:

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;
};
}

Você observará primeiro o uso das palavras-chave public, ref e sealed na declaração de classe. Para que seja criada a instância de uma classe de outra linguagem como JavaScript ou C# em um aplicativo estilo Metro, a classe deve ser declarada como public ref class sealed.

A funcionalidade pública (métodos, propriedades...) da classe se limita a tipos internos da C++ ou tipos do Tempo de Execução do Windows. Esses são os únicos tipos que têm permissão para ultrapassar o limite da linguagem em componentes do Tempo de Execução do Windows. Dito isso, você pode usar a biblioteca da C++ regular (isto é: coleções da biblioteca de modelos padrão) para os membros de dados privados da sua classe, como mostrado nesse trecho de código. Esses membros de dados privados não têm de seguir as regras associadas à ultrapassagem do limite da linguagem. O compilador do Visual Studio emite mensagens de erro e oferece diretrizes caso você use construtores sem suporte.

A implementação da classe exposta no nosso componente do Tempo de Execução do Windows

Agora que definimos a interface básica da nossa classe, vejamos alguns dos métodos implementados:

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);
}

Neste trecho de código, estamos apenas usando as APIs XAudio2 COM disponíveis para o desenvolvimento de aplicativos estilo Metro para conectar o nosso mecanismo de áudio, reproduzir som e retomar o mecanismo. Além disso, podemos usar construtores C++ e outros tipos além dos tipos do Tempo de Execução do Windows para implementar a funcionalidade necessária.

Adicionando e consumindo o componente do Tempo de Execução do Windows

Depois de definirmos e implementarmos a nossa classe básica, usamos o Visual Studio para adicionar o componente do Tempo de Execução do Windows XAudioWrapper ao projeto em C++ do nosso projeto em C#:

Usando o Visual Studio para adicionar uma referência ao componente do Tempo de Execução do Windows XAudioWrapper ao nosso aplicativo de música

Figura 3: Adicionando o componente do Tempo de Execução do Windows XAudioWrapper ao nosso aplicativo de música

Como resultado, a classe que expomos do nosso projeto em C++ é disponibilizada para o nosso projeto C#:

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);
}
}
}

Como mostrado no trecho de código, podemos interagir com o nosso wrapper do C# simplesmente como se ele fosse um componente .NET comum. Fazemos referência a seu namespace, criamos uma instância do componente e iniciamos a invocação dos vários métodos que ele expuser. Tudo isso sem precisar de nenhum DllImports para chamar ao código nativo!

Cenário 2: Usando APIs internas para abrir um arquivo zip do seu aplicativo

Vamos supor que estejamos criando um aplicativo visualizador de arquivos usando HTML e desejamos adicionar funcionalidade para permitir que os usuários desse aplicativo selecione arquivos zip. Desejamos usar as APIs que já são internas do Windows e expostas na plataforma .Net para manipular arquivos zip.

Adicionando o componente do Tempo de Execução do Windows à nossa solução

Essa é a mesma etapa que descrevemos para o nosso aplicativo de música, mas agora selecionamos o componente do Tempo de Execução do Windows em C# para encapsular a funcionalidade de processamento do zip:

Usando o Visual Studio para adicionar um novo componente do Tempo de Execução do Windows em C# ao nosso aplicativo visualizador de arquivos
Figura 4: Adicionando um novo componente do Tempo de Execução do Windows em C# 

O Visual Studio criou um projeto em C# no qual poderemos expor APIs cuja implementação e metadados do Tempos de Execução do Windows serão incluídos em um arquivo .winmd e disponibilizados para o nosso projeto Web.

A implementação da classe exposta no nosso componente do Tempo de Execução do Windows

Usamos C# para criar as APIs que serão expostas para o nosso projeto Web, mas você também pode usar o Visual Basic. Começamos pela definição de uma classe em C# simples para encapsular a funcionalidade do zip:

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;
});
}
}

Essa classe é public e sealed. Assim como na criação de componentes do Tempo de Execução do Windows em C++, isso é necessário para que outras linguagens criem uma instância da classe. O método estático exposto na classe usa uma mistura de tipos do Tempo de Execução do Windows (como o StorageFile) e os tipos .NET (como IList) na assinatura do método. A regra é usar o Tempo de Execução do Windows para definir os tipos de retorno, parâmetros e campos públicos que serão expostos para outras linguagens. Dito isso, você pode usar determinados tipos básicos do .NET (isto é: DateTimeOffset e Uri) e primitivos (isto é: IList).

Você também observará que o método acima aproveita a infraestrutura do Tempo de Execução do Windows para suporte assíncrono e de andamento, que você pode (e deve) usar ao definir os seus componentes do Tempo de Execução do Windows. Na implementação do componente do Tempo de Execução do Windows ou qualquer funcionalidade privada na classe, você não é limitado a usar somente APIs e tipos do Tempo de Execução do Windows, você tem a liberdade de usar qualquer superfície de API .NET exposta para o desenvolvimento de aplicativos Metro, como mostrado nas APIs ZipArchive de trecho de código.

Adicionando e consumindo o componente do Tempo de Execução do Windows

Agora que implementamos o wrapper da ferramenta de zip, usamos o Visual Studio para adicionar uma referência ao nosso projeto em C# do nosso projeto em JavaScript:

Usando o Visual Studio para adicionar uma referência ao componente do Tempo de Execução do Windows ZipUtil ao nosso aplicativo visualizador de arquivos
Figura 5: Adicionando o componente do Tempo de Execução do Windows ZipUtil ao nosso aplicativo visualizador de arquivos

Como resultado, a classe que expusemos do nosso projeto em C# é disponibilizada para o nosso projeto Web:

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";
}
});
};

Como você pode ver, podemos interagir com o nosso wrapper da ferramenta de zip do JavaScript exatamente como se ele fosse um objeto JavaScript comum. Podemos chamar para o método estático exposto no nosso componente do Tempo de Execução do Windows usando construtores de linguagem assíncrona de JavaScript, como o .then().

Diretrizes gerais

Nem toda API que você escrever para o seu aplicativo estilo Metro deve ser exposta como um componente do Tempo de Execução do Windows de terceiro. Em geral, usamos tipos de Tempo de Execução do Windows quando você se comunica entre linguagens de programação e usa tipos de construtores criados na linguagem que você estiver usando para a funcionalidade que não esteja publicamente exposta por meio de um componente do Tempo de Execução do Windows. Além disso, há vários recursos que são específicos de linguagem e regras relacionadas à ultrapassagem do limite da linguagem que você precisa levar em consideração ao criar o seu componente do Tempo de Execução do Windows. Isso inclui representantes e eventos, operações assíncronas, sobrecarga de método, manipulação de tipos de dados específicos, como coleções, manipulação de exceção e dicas de depuração. Você pode se aprofundar nesses tópicos, visitando a seção sobre a criação de componentes do Tempo de Execução do Windows para a sua linguagem de desenvolvimento.

Resumo

Com os componentes do Tempo de Execução do Windows, você agora pode misturar linguagens de programação e tecnologias de API para criar os aplicativos que desejar. O Windows 8 concilia tudo. Ele não abre mão de nada nem durante o desenvolvimento, permitindo que você misture e concilie as linguagens de programação que melhor se encaixem no seu cenário. Esperamos que, dessa forma, você gaste menos tempo sendo obrigado a aprender uma linguagem de programação totalmente nova e tenha mais tempo para pensar nas inovações.

Feliz criação de aplicativos!

-- Ines Khelifi, gerente de programas, Windows

Referências

Nesta postagem, nós vimos apenas superficialmente o que é possível fazer na criação de componentes do Tempo de Execução do Windows. Veja aqui outros recursos que o ajudarão a se aprofundar mais no assunto para o desenvolvimento de aplicativos:

  • Loading...
Leave a Comment
  • Please add 4 and 3 and type the answer here:
  • Post