Metro Style App 開發: 使用 C/C++


Windows 8 新增了一個應用程式開發平台--Metro Style App,開發人員在開發了這類的 app 之後便可以送交至 Windows Store,一般消費者便可以從 Windows Store 上下載安裝這些通過審查上架成功的 app,這篇文章是幫助使用 C/C++ 程式語言的開發人員,整理如何上手 Metro Style App 的開發。

從這張圖可以看得出來,若是使用 C/C++ 作為程式開發語言,則是搭配 XAML 來作應用程式介面的設計:


Windows 8 應用程式開發架構圖

XAML 是一種 XML 格式的檔案,用來描述操作介面(User Interface),檔案內容大概像是這樣:

<Page
x:Class="Application1.BlankPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Application1"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">

<Grid Background="{StaticResource ApplicationPageBackgroundBrush}">
<Button x:Name="Button1" Content="Click" HorizontalAlignment="Left"
Margin="20,20,0,0" VerticalAlignment="Top" Width="75" />
</Grid>
</Page>

這樣便會在畫面上有一個按鈕的元件。

從 .NET 3.0 以後 XAML 就大量地被運用在應用程式開發上,若您過去開發過 WPF、Silverlight、或是 Windows Phone,都是以 XAML 來作介面的設計;然而,許多具有操作介面的應用程式都以類似 XML 的方式來作介面的定義,這樣是非常常見的。

C++/CX

由於所有的 Metro Style App 都是基於 WinRT ,以 C++ 寫成的 app 必須要能與 WinRT 溝通,於是 Microsoft 設計出了 C++/CX (唸作:C plus plus over component extensions,參考資料:MSDN, Visual C++ Blog, Wikipedia)讓開發人員得以使用 C++ 開發 Metro Style App,C++/CX 相容標準的 C++ (支援到部份 C++11 標準),並且從為了 .NET CLR 設計的 C++/CLI 中借了部份的程式語法而成;C++/CX 與 C++/CLI 雖然在語法上很類似,但是底層的實作完全不同,C++/CX 並不會使用 CLR 或是 garbage collector,而會直接產生原生的 x86, x64 或 ARM 的機器語言,這也是為了讓 Metro Style App 能自然地運行在這些不同的裝置上。

舉例來說,如果要使用 WinRT 所提供的 Vector 來進行操作,用 C++/CX 的寫法可能會像是這樣:

namespace PC = Platform::Collections;
PC::Vector<int>^ numbers = ref new PC::Vector<int>();
for (int i = 0; i < 10; ++i)
{
    numbers->Append(i);
}

^ 或是 ref 這些關鍵字都是從 C++/CLI 借來的語法,如果要使用這個 collection 的 iterator,則可以寫成這樣:

// iterator
namespace WFC = Windows::Foundation::Collections;
for (PC::VectorIterator<int> it = WFC::begin(numbers); 
    it != WFC::end(numbers); ++it )
{
    // do something...
}

到現在為止都還是使用 WinRT 所提供的元件來撰寫程式,但事實上還是可以利用 C++ 的 STL 來完成一些工作,比方說在這個 collection 中尋找某個數值

PC::VectorIterator<int> findIt = 
    std::find(WFC::begin(numbers), WFC::end(numbers), 5);

所以完全可以利用既有的 C++ 資產,關於 C++/CX 更詳細的語法可以參考 (上述)MSDN 上的說明。

開發 Metro Style App

用 C++/CX 搭配 XAML 來開發 Metro Style App 說穿了也沒什麼,就是一個 XAML 介面搭配一個 C++/CX 的程式檔案,當你透過 Visual Studio 11 Beta 建立一個 Visual C++ » Windows Metro Style 下的 Blank Application 專案後,


建立 C++ 的 Metro Style App 專案

專案中會有個預設的空白頁 — BlankPage.xaml,這個 XAML 檔案就會搭配一組 C++ 的標頭檔及原始碼檔案: BlankPage.xaml.h 以及 BlankPage.xaml.cpp,如果以上述的 XAML 為例,要定義畫面上按鈕的行為,比方說按下按鈕後顯示一個訊息對話盒,在 BlankPage.xaml.cpp 裡可以這樣寫:

void BlankPage::OnNavigatedTo(NavigationEventArgs^ e)
{
    using namespace Windows::UI::Xaml::Controls;
    auto btn = safe_cast<button^>(this->FindName("Button1"));
    btn->Click += ref new RoutedEventHandler(this, &BlankPage::OnClick);
} 
// 別忘了在 BlankPage.xaml.h 中宣告這個 method,可以放在 private: 
void BlankPage::OnClick(Platform::Object^ sender, 
    Windows::UI::Xaml::RoutedEventArgs^ e)
{
    using namespace Windows::UI::Popups;
    auto dlg = ref new MessageDialog("Button clicked"); 
    dlg->ShowAsync();
}

這裡我用了 C++11 標準中的 auto 來減少打的字,而在應用程式裡要做的事情大多可以都使用 WinRT 所提供的元件即可完成。

開發 WinRT Component

WinRT 是一個很特殊的開發框架,整個 WinRT 都是以 C++ 開發完成的,但若你是 Metro Style App 的開發者,不論你是使用 C++/CX、C#、VB.net 還是 JavaScript 都有對應的 API 介面可以呼叫,這是 WinRT 使用了 Language Projection 的技術(註:常見的說法是 Language Binding,但在 WinRT 裡以 Language Projection 稱呼),而 WinRT 也允許 app 開發人員得以使用 C++/CX 或是 C#/VB.net 來開發 WinRT Component,詳細的說明可以參考 MSDN 上的文件

在 Visual Studio 11 Beta 中,你可以在 Visual C++ > Windows Metro Style 下找到 WinRT Component DLL 的專案,只要以這個專案範本就可以將開發好的 WinRT Component 產生出可以讓其它 Metro Style App 專案引用參考的 .dll 以及 .winmd 檔案。

比方說建立了一個 HelloComponent 的專案,然後在 WinRTComponent class 中新增一個簡單的 method,回傳一個 hello 的字串:

(WinRTComponent.h)
#pragma once

namespace HelloComponent
{
    public ref class WinRTComponent sealed
    {
    public:
        WinRTComponent();
        Platform::String^ SayHello();
    };
}

(WinRTComponent.cpp)
// WinRTComponent.cpp
#include "pch.h"
#include "WinRTComponent.h"

using namespace HelloComponent;
using namespace Platform;

WinRTComponent::WinRTComponent()
{
}

String^ WinRTComponent::SayHello()
{
    return ref new String(L"hello");
}

如此便可以建置出 HelloComponent.dll 以及 HelloComponent.winmd 檔案,如此一來,在其它的 Metro Style App 專案,不論是使用什麼程式語言進行開發,都可以將這個 dll 及 winmd 加入專案的參考(References),所以若是使用 C# 的專案,要呼叫這個 SayHello 函式就可以直接寫成:

var com = new HelloComponent.WinRTComponent();
var helloStr = com.SayHello();

若是 JavaScript,則是:

var com = new HelloComponent.WinRTComponent();
var helloStr = com.sayHello(); // 沒有打錯,會轉成 camel case

是不是覺得 WinRT 很神奇了呢 🙂

總結

使用 C++/CX 開發 Metro Style App,乍看之下似乎較 C#, JavaScript 要來得麻煩,不過由於它相容標準 C++ 的緣故,若有既有的 C++ 程式碼,要在 Metro Style App 上再利用都容易許多(當然,需要一些轉換成本,至少不是全部重來),而且還可以用來開發 WinRT Component,能夠將有效能瓶頸,或是不想輕易放在 JavaScript 檔案中的敏感資料都以 WinRT Component 來處理;另外就是,根據這篇文章的說法:

Developers can use our tools to create native C/C++ code for maximal performance and flexibility, in addition to the C#, XAML, VB, and HTML5 based tools, to target apps for WOA, so long as their code targets the WinRT API set. Additionally, developers with existing code, whether in C, C++, C#, Visual Basic, or JavaScript, are free to incorporate that code into their apps, so long as it targets the WinRT API set for Windows services. The Windows Store can carry, distribute, and service both the ARM and x86/64 implementations of apps (should there be native code in the app requiring two distributions).

有機會以 C/C++ 開發程式並且搭配 Microsoft 所提供的開發工具,在 x86/ARM 上各自最佳化效能(作成 WinRT Component),所以如果你是精通 C++ 程式語言的開發人員,不妨來試試以 C++ 開發 Metro Style App 吧!

Comments (0)

Skip to main content