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++:
-
Ladda ner den här zip-filen:
VS2012CPPWinForms.zip
-
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.
-
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:
Bild 3: Visual Studio-fönstret
När Visual Studio 2012 startat ser det ut så här:
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:
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.)
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.
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.
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".
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.
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.
"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.)
Bild 13: Starta programmet
Sen startar vi programmet genom att klicka
Debug -> Start Debugging,
alternativt genom att trycka på F5.
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!)
"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