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

Inte klart än! Än så länge har jag bara bytt ut texten "2005" mot "2010", så en del av det som står stämmer bara ungefär, men vilket år som helst kommer det en beskrivning som stämmer bättre med hur det fungerar i Visual Studio 2010.

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 2010.) 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: Starta Visual Studio

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

Visual Studio i Start-menyn

Bild 2: Visual Studio-fönstret

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

Visual Studio-fönstret

Bild 3: 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 4: 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.

Nytt projekt-fönstret

Bild 5: Projektet i Visual Studio-fönstret

Nu kan vi börja jobba med vårt nya projekt. Notera designverktyget ("designern") till vänster, som vi kan använda för att bygga det grafiska användargränssnittet för programmet.

Visual Studio-fönstret med designverktyget

Bild 6: 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.

Verktygslådan

Bild 7: 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 8: 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 9: 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" 10: 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(43, 52);
    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(102, 118);
    this->button2->Name = L"button2";
    this->button2->Size = System::Drawing::Size(135, 71);
    this->button2->TabIndex = 1;
    this->button2->Text = L"button2";
    this->button2->UseVisualStyleBackColor = true;

Bild 11: 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 F6. (Snabbtangenterna kan bli lite olika i olika installationer, förmodligen beroende på vilka inställningar man har.)

Menyval i Visual Studio-fönstret

Bild 12: 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 13: 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" 14 och 15: 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). För att C++-program ska fungera i .NET-miljön, så har Microsoft gjort en del ä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" 16 och 17: 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 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), 12 april 2011