Application Metro Windows 8 Hello world en C++

Read this post in English 

Note : le code C# est également disponible, voir à la fin de l’article.

C++/CX ou bien C++ et WRL ?

C’est facile comme tout de créer sa première application Metro pour Windows 8 en C++/CX.

Il est théoriquement possible de créer une application C++ Metro pour Windows 8 de deux façons, comme mentionné dans un précédent billet:

  • En utilisant C++/CX, un langage C++ avec des extensions spécifiques, notamment les pointeurs chapeau. Ce n’est pas du C++ standard.
  • Ou bien en utilisant une librairie de templates WRL (successeur d’ATL), et du C++ standard.

Mais en réalité, utiliser WRL est tout simplement trop compliqué. Il ne s’agit pas que de créer des interfaces COM à la main, mais aussi d’utiliser des delegates et autres joyeusetés qui se révèlent très fastidieuses à mettre en oeuvre en C++ pur avec WRL. Alors qu’en C++/CX, c’est beaucoup, beaucoup plus simple. Voilà, ce n’était que mon avis sur WRL.

Créer le projet C++

Donc, pour créer notre appli Metro Hello world en C++, il faut bien sûr disposer d’une pré-version de Windows 8 installée sur une machine touch si possible, et de lancer Visual Studio Express.

En cliquant tapant sur le menu File/New/project, on choisit un projet C++/Metro de type Application :

New-CPP-Project-Metro-Windows8-hello-world
Créer un nouveau projet C++ Metro pour WinRT (cliquer pour agrandir)

 

En cliquant sur OK, un squelette de projet est généré, et le fichier MainPage.xaml est ouvert:

xaml-metro-start
Un squelette de projet C++ Metro (cliquer pour agrandir)

Ceux qui ont déjà fait du WPF ne seront pas dépaysé. On dirait un projet WPF/C#, sauf qu’il y a des fichiers .cpp à la place des fichiers .cs !

Pour ceux qui viennent de Win32, éventuellement des MFC, ça dépayse.

Créer quelques contrôles

MainPage.xaml est – comme son nom l’indique – la description en langage Xaml de la fenêtre principale de l’application. C’est un UserControl.

Pour ceux qui connaissent les ressources Win32 (les fichiers.rc) Xaml est un peu l’équivalent amélioré d’un langage de ressources (oui, les string tables, les dialogbox, les menus, eh bien maintenant on met tout ça dans des fichiers Xaml).

Visual Studio affiche le fichier Xaml sous forme de code, en même temps que le rendu final de la fenêtre. Pour l’instant la fenêtre est vide, il n’y a rien.

Trève de théorie, ajoutons trois contrôles dans notre fenêtre principale : un label, un champ Edit, et un bouton OK. Pour cela  il suffit d’insérer le texte ci-dessous dans le fichier MainPage.xaml, à l’intérieur du tag <Grid> </Grid> :

<StackPanel Orientation="Horizontal">
    <TextBlock Text="Entrez 'hello, world':" Height="20" Margin="10"/>
    <TextBox Height="20" Margin="20" Width="200" x:Name="IDText"/>
    <Button Content="OK" Width="100" Height="20" Click="OnOK"/>
</StackPanel>

Le champ Edit (TextBox) a un identificateur IDText qu’on utilisera dans le code pour récupérer son contenu.
Le bouton OK est déjà associé à un gestionnaire d’évenement OnOK que l’on définira bientôt.

Et le tout est encapsulé dans un contrôle de type StackPanel, ce qui a pour effet d’aligner les trois contrôles sur une ligne.

 

Ajouter du code C++

Un fichier Xaml est souvent associé à deux fichiers : un fichier .cpp et in fichier .h. Les fichiers Mainpage.xaml.cpp et Mainpage.xaml.h sont liés au fichier MainPage.xaml. Ainsi, le code C++ des contrôles de MainPage trouvera naturellement sa place dans ces deux fichiers.

Dans l’explorateur de solution, en cliquant sur le petit triangle devant MainPage.xaml, on affiche les fichiers C++ associés :

CPP-Metro-solution-explorer

Ajoutons la méthode OnOK du gestionnaire d’évenement Click du bouton.

Dans le fichier MainPage.xaml.h :

private:
void OnOK(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);

Dans le fichier MainPage.xaml.cpp :

void MainPage::OnOK(Platform::Object^ sender,
                    Windows::UI::Xaml::RoutedEventArgs^ e)
{
    String^ strInput = IDText->Text;
    String^ strMessage;
    if ( !wcsicmp( strInput->Data(), L"hello, world") )
        strMessage = L"Bien joué";
    else
        strMessage = L"Essayez encore";
    auto boxOK = ref new Windows::UI::Popups::MessageDialog(strMessage);
    boxOK->ShowAsync()->Start();
}

Le code est assez explicite. On retrouve l’identificateur IDText qui référence le champ Edit. En fonction de son contenu, on affiche un message différent.

enter-hello-world

L’objet MessageDialog est l’équivalent Metro de la MessageBox bien connue :

metro-messagedialog

Paramétrer MessageDialog

On peut modifier la fenêtre MessageDialog, notamment ajouter des boutons.

Chaque bouton est représenté par un objet UICommand, qui associe un texte et un gestionnaire d’évenement. La méthode du gestionnaire d’évenement est appelée lorsque le bouton est cliqué.

UICommand^ btnOui = ref new UICommand(L"Oui",
        ref new UICommandInvokedHandler(this, &MainPage::OnOui));

La méthode MainPage::OnOui sera appelée lorsque l’utilisateur cliquera sur le bouton Oui de la fenêtre messageDialog. Voici le code de MainPage.xaml.cpp :

using namespace Windows::UI::Popups;

void MainPage::OnOK(Platform::Object^ sender,
                    Windows::UI::Xaml::RoutedEventArgs^ e)
{
    String^ strInput = MyText->Text;
    if ( !wcsicmp( strInput->Data(), L"hello, world") )
    {
        // MessageDialog simple
        MessageDialog^ boxOK = ref new MessageDialog(
                            ref new String(L"Bien joué !"));
        boxOK->ShowAsync()->Start();
    }
    else
    {
        // MessageDialog avec texte et titre
        MessageDialog^ boxAsk = ref new MessageDialog(
            "Phrase incorrecte. Voulez vous la solution ?",
            L"Erreur !");

        // Ajoute deux boutons “Oui” et “Non”
        UICommand^ btnOui = ref new UICommand(L"Oui",
            ref new UICommandInvokedHandler(this, &MainPage::OnOui));
        UICommand^ btnNon = ref new UICommand(L"Non",
            ref new UICommandInvokedHandler(this, &MainPage::OnNon));
        boxAsk->Commands->Append(btnOui);
        boxAsk->Commands->Append(btnNon);

        // Bouton par défaut = index dans Commands
        boxAsk->DefaultCommandIndex = 1;
        // Affiche MessageDialog et retourne immédiatement
        boxAsk->ShowAsync()->Start();
    }
}

void MainPage::OnOui(IUICommand^ command)
{
    // Donne la solution
    MyText->Text = L"hello, world";
}

void MainPage::OnNon(IUICommand^ command)
{
    MyText->Text = L"";
}



metro-messagedialog

Le code source C++/CX et C# du projet entier est disponible sur http://code.msdn.microsoft.com/windowsapps/MessageDialog-sample-243ce23e

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>