7
Tags:
c++
Skrevet af
Bruger #714
@ 30.03.2003
I denne artikel skal vi se på hvordan man kan bruge c til at lave andet end små consol applikationer, nemlig til hvordan man kan lave vinduer, knapper osv. Altås en kort lille, og sikkert ikke fuldendt, gennemgang af WIN32 API'et. Denne artikel kræver noget kendskab til c++, som du kan læse i nogle af de andre artikler her på udvikleren. Efter du har læst denne artikel, vil du være i stand til at: Lave din helt egen windows applikation med et vindue.
Lidt basis viden
Før vi går helt igang med kode, er det vigtigt at du forstår hvordan hele dit program skal bygges op. Ligesom når du laver consol programmer, så har dit program en "main" procedure, men når du laver windows applikationer ser den sådan her ud:
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
Og hvad betyder det så? Jo, det første "int", betyder at vi retunere en integer value til sidst. WINAPI definere calling conventionen, den behøves du ikke at tænke så meget over, bare du husker den. WinMain, er funktionens navn. hInstance er "handlenen" til vores program (.exe filen) i hukommelsen. hPrevInstance er altid NULL. lpCmdLine er kommando liniens argumenter som en streng, uden programmets filnavn. nCmdShow kommer vi til senere.
Den gode hello world
Som altid, skal der være et hello world eksempel. Det vi skal lave er et program, der viser en "box" og lukker ned igen.
Det ser sådan ud:
#include <windows.h> //Dette inkludere alle windows standard funktionerne og "const" variablerne
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{ //Vores main procedure
MessageBox(NULL, "Hello World", "Hej verden", MB_OK | MB_ICONINFORMATION);
//Viser en "box" hvor der står hello world,
//plus en titel hvor der står "hej verden" og en "OK" knap,
//plus et informations billede.
return 0;
//Afslut programmet
}
Forklaring
Det eneste jeg synes der er grund til at forklare er "MessageBox" funktionen. Den bliver du nød til at stifte bekendskab til, ellers så kommer du ikke langt, lad os se på hvordan Microsoft beskriver den:
int MessageBox(
HWND hWnd, // handle of owner window
LPCTSTR lpText, // address of text in message box
LPCTSTR lpCaption, // address of title of message box
UINT uType // style of message box
);
Og hvad betyder det så?
int MessageBox betyder at MessageBox retunere en integer værdi.
HWND hWnd, kræver lidt mere forklaring. HWND typen, skal læses som Handle Window. Dette er "handleren" til "boxens" ejer vindue, da vi ikke har oprettet et, så satte vi det til NULL.
LPCTSTR lpText, kræver igen lidt forklaring. T'et (har jeg læst mig frem til der hvor jeg lærte C++, ret mig hvis det er forkert), har ingen betydning, med mindre vi skal kode noget unicode, så hvis vi glemmer det, så har vi LPSTR tilbage.
LPCSTR, skal læses som "Long Pointer Const String", altså en lang peger streng der ikke kan ændre værdi. Du skal bare betragte det som en streng, der ikke kan ændre værdi. Dette er selve teksten der kommer i vores "box", og den satte vi så til "Hello World".
LPCTSTR lpCaption, er igen en "lang peger streng der ikke kan ændre værdi". Dette er titlen på vores vindue.
UINT uType, er et unsigned integer, vi bruger ikke integer values, men nogle const variabler som er defineret i windows.h, som vi så kan bruge til, at lave knapper med, og bestemme hvilket ikon der skal komme med op (Du behøves ikke at angive et ikon). Hvis man vil angive mere end en skal man adskille dem med | Her er en oversigt over knapper, taget direkte fra WIN32 dokumentationen.
MB_ABORTRETRYIGNORE The message box contains three push buttons: Abort, Retry, and Ignore.
MB_OK The message box contains one push button: OK. This is the default.
MB_OKCANCEL The message box contains two push buttons: OK and Cancel.
MB_RETRYCANCEL The message box contains two push buttons: Retry and Cancel.
MB_YESNO The message box contains two push buttons: Yes and No.
MB_YESNOCANCEL The message box contains three push buttons: Yes, No, and Cancel.
Og her er oversigten over ikonerne.
MB_ICONEXCLAMATION,
MB_ICONWARNING
An exclamation-point icon appears in the message box.
MB_ICONINFORMATION,
MB_ICONASTERISK
An icon consisting of a lowercase letter i in a circle appears in the message box.
MB_ICONQUESTION A question-mark icon appears in the message box.
MB_ICONSTOP,
MB_ICONERROR,
MB_ICONHAND
A stop-sign icon appears in the message box.
Du kan også angive hvilken knap der skal være standard knappen. Og mange andre ting. Hvad der er mere spændende, er hvad den retunere når der bliver klikket på den.
Vi kunne eks. forestille os, at vi havde lavet en tekst-editor og der lige var blevet trykket på krydset, og vi ville spørge brugere om han/hun vil gemme det han/hun har skrevet, vi kunne dermed bruge MessageBox() således:
int Svar = MessageBox(NULL, "Vil du gemme dit dokument inden du afslutter programmet?", "Vil du gemme?", MB_YESNOCANCEL | MB_ICONQUESTION);
switch(Svar){
case IDYES:
//Gem dokumentet
//Læg mærke til at her ingen "break;" er, da vi også skal lukke programmet ved "IDYES"
case IDNO:
//Luk programmet
break;
default:
//Gør ingenting
}
Resten af de forskellige ID'er burde give sig selv(IDCANCEL, IDABORT osv.)
Der er også en del andre vi kan angive med MessageBox, men dem vil jeg ikke fortælle mere om lige nu.
Det endelige eksempel
Nu skal vi til det sjove, men også det meget svære, vi skal have lavet et vindue.
Først, koden, så forklaringen. Vær forberedt på det værste.
#include <windows.h>
const char KlasseNavn[] = "WIN32 API"; //Klasse navnet
LRESULT CALLBACK WndProc(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam) //Denne procedure bliver kaldt hver gang der er en besked til vores vindue, eller dens vinduer, kig længere nede for forklaring
{
switch(Msg){
case WM_CLOSE: //Øver, vi er nødt til at lukke
DestroyWindow(hwnd); //Destruer vores vindue
break;
case WM_DESTROY: //Lad os poste den sidste besked
PostQuitMessage(0);
break;
default: // Ikke noget vi gider at rode med, send den videre til default message handleren
DefWindowProc(hwnd, Msg, wParam, lParam);
break;
}
}
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
MSG Msg; //En message variabel
WNDCLASSEX wc; //Vores vindue klasse
HWND hwnd; // Handleren til vinduet
wc.cbSize = sizeof(WNDCLASSEX); //Størrelsen på WNDCLASSEX i bytes
wc.style = 0; //Ingen ekstra styles
wc.lpfnWndProc = WndProc; //Vindue proceduren, den tager sig af alle beskeder
wc.cbClsExtra = 0; //Skal vi ikke bruge
wc.cbWndExtra = 0; //Skal vi ikke bruge
wc.hInstance = hInstance; //hIstance, kommer fra hInstance, variablen i WinMain.
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); //Load et ikon
wc.hCursor = LoadCursor(NULL, IDC_ARROW); //Load en cursor
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); //Vælg farve til vinduet
wc.lpszMenuName = NULL; //Ingen menu
wc.lpszClassName = KlasseNavn; //Vores klassenavn
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION); //Load et lille ikon
if(!RegisterClassEx(&wc)){ //Forsøger at registrere vores vindue klasse, ellers spytter vi en box i hovedet på brugeren, og stopper programmet
MessageBox(NULL, "Kunne ikke registrere vindue klassen", "Fejl", MB_OK | MB_ICONEXCLAMATION);
return 0; //Stopper programmet
}
//Så skal vi lave selve vinduet
hwnd = CreateWindowEx(WS_EX_CLIENTEDGE, //Laver en kant på vinduet
KlasseNavn, //Angiver vores klasse navn
"Hej verden, nu fra et vindue", //Titlen på vores vindue
WS_OVERLAPPEDWINDOW, //Angiver at det er et normalt vindue vi vil lave (dette er en sammentrækning af en masse styles)
CW_USEDEFAULT, //Vælg en standard x poisition til vinduet
CW_USEDEFAULT, //Vælg en standard y poisition til vinduet
300, //Bredden på vinduet
200, //Højden på vinduet
NULL, //Vi har ingen ejer af vinduet
NULL, //Ingen menu
hInstance, //Handleren til .exe filen
NULL); //Skal vi ikke bruge
if(hwnd == NULL){ //Vinduet kunne ikke oprettes, smid en fejl i hovedet på brugeren og luk ned
MessageBox(NULL, "Kunne ikke oprette vinduet", "Fejl", MB_OK | MB_ICONEXCLAMATION);
return 0; //Stopper programmet
}
//Hvis vi er nået så langt, har vi en vindue, og en vindue klasse, nu mangler vi bare at vise vores vindue, og sørge for at fange alle messages der bliver sendt til det.
ShowWindow(hwnd, nCmdShow); //Viser vores vindue, paramenteren nCmdShow, er måden det skal vises på, og vi viser det, ligesom det er blevet ønsket.
UpdateWindow(hwnd); //Opdaterer vores vindue
//Dette er lidt tricky, dette loop sørger for at vores vindue, modtager alle messages, der bliver sendt til den, d.v.s. at vi får atvide, når f.eks. at vores vindue bliver oprette. Når det resizes osv.
while(GetMessage(&Msg, hwnd, 0, 0) > 0){ //Der er en besked fortsæt
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return Msg.wParam; //Retunerer Msgs wParam
}
Det ser lidt uoverskueligt ud, og det kan det også være. I part 2, vil der komme en nærmere forklaring på koden. Men hvis du sidder med en hjælpefil over alle funktionerne så vil jeg råde dig til at kigge i den. Ellers, så kan jeg kun sige at vi ses i part 2.
Hvad synes du om denne artikel? Giv din mening til kende ved at stemme via pilene til venstre og/eller lægge en kommentar herunder.
Del også gerne artiklen med dine Facebook venner:
Kommentarer (18)
Hey kaare din artikel synes jeg ikke er så vild igen. Det ser ud som om du har mistet lysten til sidst og bare skyndt dig at blive færdig.
På en måde ja og nej, jeg ville egentlig bare være færdig til sidst. Men samtidig var jeg godt klar over at der skulle nærmere forklaring til, og som skrevet til sidst kommer den i næste part. Jeg er allerede gået igang med den kan jeg da røbe. Jeg dog ikke med at vise så meget kode i 2'eren, men mere forklaring, da det kræver lidt at sætte sig ind i den måde det hele kører i. Jeg håber at du vil skifte mening når 2'eren kommer :-).
1. Du skriver at man i denne tutorial, vil lave programmer i c++. Det er ikke sandt, Win32 API'en er C.
2. Undrer mig lidt over hvorfor dine eksempler ligner (i sær det sidste) så meget
http://www.winprog.org/tutorial.3. Jeg synes godt du kunne have gjort dette noget bedre, for mig (har trodsalt brugt Win32 API'en i et pænt stykke tid) virker det som at det er noget hastværk.
4. Du skifter imellem danske og engelske kommentarer, igen noget der får mig til at tænke på, du ikke har helt ren mel i posen (
http://www.winprog.org/tutorial) 5. Måske burde du indsende en rettelse til udvikleren.dk, det kan gøres via artikel systemet.
Simon -> Det er rigtigt at jeg har fået stort set alt min viden fra www.winprog.org/tutorial, det er der ingen grund til at ligge skjul på, dog vil jeg også sige at jeg faktisk selv er ny i det her, men jeg føler er jeg er ved at fatte bare lidt af hvad det går ud på, derfor synes jeg at der er andre end mig der skal have fornøjelsen af at kende til det. Meget muligt at der er mange andre der kunne gøre det bedre. Men indtil videre, er der jo ikke nogen der har gjort det. Så jeg tænkte at det måtte være nok. Men jeg skal nok lige kigge på det.
Dog skal det lige siges at jeg under INGEN omstændigheder har skrevet af fra www.winprog.org/tutorial, men hvis der var noget jeg var i tvivl om, var det mit opslagsværk hvis ikke jeg kunne finde det i hjælpefilen.
Hvornår kommer der en part 2? Eller gider du ikke lave en? For jeg mangler forklaring på det siste eksempel
CHadi -> Efter lang tids venten på at få godkendt 2'eren, blev den afvist. Så der går nok lidt (meget) tid inden jeg får taget mig sammen til at skrive 2'eren.
go artikel men ejg savner 2'eren! glæder mig til forklaringen på sidste kodeexempel!
Når jeg kompilerer det endelige eksempel med min visual c++ 6 compiler skriver den:
error C4716: 'WndProc' : must return a value
og da jeg ikke ved så meget om at skrive windows-programmer så ved jeg ikke helt hvad den mener... det irriterer mig - men ellers er det en rigtig god artikel :-) håber at der snart kommer en 2'er
Hej jeg håber at i den næste at du kommer ind på den sidste del. Også noget med at inkludere knapper osv det ville være dejligt
Men ellers kunne man jo nok lære lidt selvom den sidste del var lidt stinky :/
Jeg undskylder at den sidste del ikke er kommet endnu, og jeg tvivler også lidt på om jeg får den skrevet (sorry men tiden den fløj bare væk, har rigtig mange ting at tage mig til), men jeg kan da råde jer til at kigge på stedet hvor jeg selv lærte det, og ellers kan jeg da opfordre andre til at fortsætte min artikel serie hvis de føler at det er noget der er værd at fortsætte.
www.winprog.org/tutorial
Derudover det, vil jeg lige sige at jeg rent faktisk skrev part 2, men den blev afvist, skal se om jeg kan rode den frem og lægge den op og smide et link, men jeg har ikke tiden der skal til for at få den rettet, desværre.
God tutorial selvom ligesom du selv siger mere eller mindre en omfomuleret tutorial der oprindeligt var lavet af theForger
og så lige en kommentar til Simon selvom jeg godt ved hans kommentar er ret gammel:
1. Du skriver at man i denne tutorial, vil lave programmer i c++. Det er ikke sandt, Win32 API'en er C.
Ja det er rigtigt, men du kan med de fleste compilere sagtens bruge c++ med det uden nogle fejl!
Og så lige noget til Chadi han har selv sagt at han har brugt
http://www.winprog.org/tutorial som opslagsværk og efter min mening ligner den og hans hinanden bortset fra sproget og længden så gå derind hvis du kan forstå lidt engelsk og det regner jeg med ellers har du haft svært ved at lære at programmere
Total fed artikel!! Rated 5/5
Synes godt jeg kunne have brugt noget med nogle knapper og labels og hvad det ellers hedder, men det er jo trods alt kun en den 1. af noget som skulle have været
når jeg prøver at compile (noget så simpelt som) det første exemple får jeg min 2 errors. Hvorfor? Og jeg bruger MSVS.
Til alle der har probsm ed denne her: HUSK AAT OPRETTE ET WIN PROJEKT OG IKKE ET WIN CONSOLE PROJEKT.
Hvorfor, om jeg må spørge, skal det her sprog være så skide indviklet?!?!? Bare et lille vindue fylder op mod 100 linier!!!
Okay, var pænt noob den gang... Nu synes jeg det er legende let at lave vinduer, og din tutorial hjalp mig lige til at komme det ekstra skridt videre, jeg havde brug for!! Du får en 5'er..
Virklig go' artikel den har lært mig meget selvom jeg stadig er ny i c++
siger bar' TAK!
Du skal være
logget ind for at skrive en kommentar.