Visual Studio 2012: Skapa ett C++-program med grafik för .NET

Vi ska skapa ett enkelt C++-program som kan köras i .NET-miljön och som använder fönster och grafik.

Om man ska skriva ett portabelt C++-program, alltså ett som också kan kan kompileras och sen köras på en dator med till exempel Mac OS X eller Linux, så måste man hålla sig till in- och utmatning av text. (Man kan läsa här om hur man skapar ett sånt C++-program i Visual Studio 2012.) De grafiska gränssnitten, och hur man arbetar med fönster och knappar och liknande, är helt olika på de olika systemen, och på Windows använder man numera helst .NET.

"Bild" 1: Först måste man komplettera Visual Studio 2012

Tidigare kunde man skapa fönsterprogram med C++ "out of the box" i Visual Studio, men inte i Visual Studio 2012. Microsoft skriver: "C++/CLI is a great solution for interop, but we do not recommend creating brand new UI applications using C++/CLI."

Men från http://www.t-hart.org/vs2012/ hämtar vi en lösning, så att även Visual Studio 2012 kan skapa nya fönsterprojekt med C++:

  1. Ladda ner den här zip-filen: VS2012CPPWinForms.zip
  2. Installera genom att kopiera de filer som finns i zip-filen till katalogen
    C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\vcprojects\vcNET
    (eller var du nu har installerat Visual Studio).
    Detta kommer att skriva över filen vcNET.vsdir, så spara först en kopia av den filen, ifall du behöver avinstallera de här tilläggen.
  3. Starta Visual Studio 2012. Nu kan man skapa fönsterprojekt med C++ enligt nedan.

Bild 2: Starta Visual Studio

Visual Studio 2012 finns som ett menyval i Start-menyn:

Visual Studio i Start-menyn

Bild 3: Visual Studio-fönstret

När Visual Studio 2012 startat ser det ut så här:

Visual Studio-fönstret

Bild 4: Skapa ett nytt projekt

Det som en del andra kanske skulle kalla för ett "program" eller en "mjukvara", kallar Visual Studio för "projekt". Vi skapar ett nytt projekt genom att klicka FILE -> New -> Project:

Menyval i Visual Studio-fönstret

Bild 5: Nytt projekt-fönstret

Nu får vi välja vilken sorts projekt vi ska skapa. Vi ska skapa ett projekt med språket Visual C++. Det ska vara av typen CLR, som betyder Common Language Runtime, och som är det körbara format som används i .NET. Bland mallarna ("templates" på engelska) väljer vi Windows Forms Application, alltså ett vanligt Windows-program med fönster. (Det var den typen av projekt som vi behövde lägga till i början.)

Nytt projekt-fönstret

Bild 6: Projektet i Visual Studio-fönstret

Nu kan vi börja jobba med vårt nya projekt. Notera designverktyget ("designern") till höger, som vi kan använda för att bygga det grafiska användargränssnittet för programmet. I designverktyget ser vi hur vårt fönsterprogram kommer att se ut när vi kör det.

Visual Studio-fönstret med designverktyget

Bild 7: Ta fram verktygslådan

Om verktygslådan med diverse olika knappar och inmatningsfält inte syns, kan man få fram den genom att klicka View -> Toolbox. Man kan ta loss verktygslådefönstret från Visual Studios huvudfönster och lägga det för sig på skärmen.

Verktygslådan

Bild 8: Dra en knapp till designverktyget

Ta tag i en knapp ("Button") i verktygslådan och dra den till designverktyget. Knappen får namnet "button1".

Designverktyget med en knapp

Bild 9: Dra ännu en knapp till designverktyget

Dra ännu en knapp från verktygslådan till designverktyget. När knappen finns på designverktyget kan man flytta den med musen, eller ändra storleken på den genom att ta tag i ett hörn.

Designverktyget med två knappar

Bild 10: Designern kan generera kod

Designern kan generera C#-kod utifrån den design vi byggt upp grafiskt. Man kan få fram koden genom att klicka View -> Code.

Kod-vy i Visual Studio-fönstret

"Bild" 11: Den genererade koden

Här är ett utdrag ur den kod som designverktyget genererat. (Filen heter Form1.h.) I koden ser man till exempel att den andra knappen är större än den första.

Ändringar som görs i koden, till exempel om man ändrar storleken på en knapp, återspeglas sen i vad designverktyget visar grafiskt. Man kan växla mellan designverktyget och kodfönstret genom att klicka på flikarna.

    // 
    // button1
    // 
    this->button1->Location = System::Drawing::Point(39, 29);
    this->button1->Name = L"button1";
    this->button1->Size = System::Drawing::Size(75, 23);
    this->button1->TabIndex = 0;
    this->button1->Text = L"button1";
    this->button1->UseVisualStyleBackColor = true;
    // 
    // button2
    // 
    this->button2->Location = System::Drawing::Point(117, 93);
    this->button2->Name = L"button2";
    this->button2->Size = System::Drawing::Size(128, 59);
    this->button2->TabIndex = 1;
    this->button2->Text = L"button2";
    this->button2->UseVisualStyleBackColor = true;

Bild 12: Bygg ihop programmet så det går att köra

Programmet finns än så länge bara i form av källkod (även om den kan visas både som text och grafiskt), och den kan inte köras av datorn. Därför måste programmet kompileras och länkas, eller "byggas". Det gör vi genom att klicka Build -> Build Solution, alternativt genom att trycka på snabbtangenten F7. (Snabbtangenterna kan bli lite olika i olika installationer, förmodligen beroende på vilka inställningar man har.)

Menyval i Visual Studio-fönstret

Bild 13: Starta programmet

Sen startar vi programmet genom att klicka Debug -> Start Debugging, alternativt genom att trycka på F5.

Menyval i Visual Studio-fönstret

Bild 14: Programmet körs

Programmet startar, och det fönster som vi byggde ihop i designverktyget dyker upp som ett vanligt Windows-programfönster. Man kan trycka på knapparna, men än så länge händer inget, för vi har inte skrivit någon programkod som kan köras vid knapptryckningarna. (Den måste vi skriva för hand, utan hjälp av designverktyget!)

Programmet körs

"Bild" 15 och 16: Ohanterade data

Microsofts .NET-miljö, som det här programmet kommer att köras i, har en del finesser, till exempel automatisk skräpsamling (på engelska garbage collection). Det finns också ett stort bibliotek med färdiga klasser. För att C++-program ska fungera i .NET-miljön, har Microsoft gjort en hel massa ändringar i själva språket C++ när man programmerar för .NET.

Till exempel finns det två sorters klasser, för hanterade och för ohanterade data.

Klasser som är ohanterade data (på engelska unmanaged data) definieras och fungerar som vanligt i C++:

class Hund {
    int antal_hussar;
    double vikt;
};

Man skapar objekt av klassen Hund som vanligt med new, och sen måste man städa bort dem med delete:

    Hund* h1 = new Hund();
    Hund* h2 = NULL;
    // ...
    delete h1;

"Bild" 17 och 18: Hanterade data

Klasser som är hanterade data (på engelska managed data) definieras och fungerar annorlunda än i vanlig C++:

ref class Katt {
    int antal_svansar;
    double toppfart;
};

Notera att det står ref class och inte bara class. Sen skapar man objekt av klassen Katt med gcnew i stället för new, och de tas bort automatiskt, så delete behövs inte.

    Katt^ k1 = gcnew Katt();
    Katt^ k2 = nullptr;
    // ...

Notera också att man inte använder * för att ange en pekare till ett objekt av en hanterad klass, utan ^, och att det inte heter NULL utan nullptr.


Thomas Padron-McCarthy (thomas.padron-mccarthy@oru.se), 18 januari 2013