Windows API - part 1

Tags:    c++
Skrevet af Bruger #7461 @ 23.10.2006
Jeg vil i denne artikel fortælle om Windows api'et som bruges til at lave Windows programmer med. Så kan du noget grundlæggende c/c++ programmering og har du lyst til at lave ”rigtige” programmer i stedet for konsol programmer, så er denne artikel noget for dig. Jeg vil prøve at forklare alt ting så godt jeg kan, skulle der være noget du ikke forstår er du meget velkommen til at spørge.

Hvad er windows api'et

Windows api’et er udviklet af Microsoft og gør det muligt at lave windows programmer, api’et er lavet så du ved hjælp af c/c++ kan kode dine egne windows programmer. I api’et er der en masse funktioner du kan kalde som kan udføre forskellige ting, såsom tilføje knapper til dit vindue, vise grafik og meget mere. Windows api’et kaldes også win32 api.

Lad os komme i gang med at lære noget om det at lave windows programmer. Det første vi vil lave er et meget simpelt program som faktisk blot er et popup vindue. For at lave windows programmer skal du have en compiler der understøtter win api’et, det gør det fleste c/c++ compiler i dag. Nå men lad os komme i gang.

Eksempel 1
Fold kodeboks ind/udKode 


Okay dette er koden der laver en simpel popup, lad os gå koden igennem fra en ende af for at forstå den.

#include ”windows.h” Det er i denne fil alle windows apiet’s funktioner er defineret, så vi skal include denne fil for at få mulighed for at bruge api’et.

Int WINAPI WinMain (HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpCmd, int nShow)
Dette er vores main funktion ligesom int main(int argc, char ** argv) er det i et konsol program. Man behøves ikke at koncentrer sig så meget om hvad de forskellige ting i denne main funktion betyder, men her kommer det alligevel.

hInst er handleren til vores program som er læst ind i hukomelsen. hPrev bruges ikke i win32 programmer og vi skal derfor ikke tænke på den. lpCmd indeholder komando lines argumenter, hvis der er nogen. nShow bruges til at beskrive på hvilken måde vi vil vise vores program, så den kommer vi til senere når vi skal til at lave et vindue.

MessageBox(NULL, "Velkommen til windows api'et", "Windows api", NULL);
MessageBox() er en forud defineret funktion i Windows api’et og bruges til at lave en popup med.
Funktionen er defineret sådan her
int MessageBox(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType);

hWnd er handleren til vores vindue hvor vi vil lave popup’en, den er sat til NULL her da vi ikke har lavet noget vindue endnu. lpText er teksten der skal stå i popup’en. lpCaption er overskriften på popup’en. uType bruges til af beskrive hvordan popup’en skal se ud, det her man bestemmer hvilke knapper man vil have og sådan noget, nedenfor ses en samling af typer man kan bruge. Man kan sammen sætte flere ved at bruge | eks. MB_OK | MB_ICONSTOP.

Fold kodeboks ind/udKode 


Det var en masse forklaring, jeg håber du forstod det meste af det. Du har nu prøvet at lave dit første Windows program. Det vil være en god ide hvis du prøver at lege lidt med det inden du går videre så du har forstået det hele. Du kan lege lidt med at udskifte teksten, tilføje forskellige knapper og ikoner.

Nu vil vi gå videre og lære hvordan vi laver et rigtigt vindue, det er meget svært at komme i gang med da det kræver mange liners kode bare for at lave et vindue. Jeg vil først vise jer hele koden til at lave et vindue og vil derefter beskrive koden. Jeg har også lavet nogle kommentarer i koden du kan læse mens du læser koden igennem, så du har lettere ved at forstå koden. Det vil nok være en god ide at læse koden igennem et par gange så du bedre forstår hvad det er vi gør.

Fold kodeboks ind/udKode 


Det var en masse kode på en gang, men der kræves så meget kode for at lave et vindue. Jeg håber du forstod lidt af koden, og hvad det var vi gjorde. Vi skal nu kigge lidt på koden så vi er helt med på hvad det er der sker.

LRESULT CALLBACK MainWndProc (HWND hwnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
Er vores “tilbage kalds funktion” det er er alle informationer om hvad der sker I programmet og hvad folk gør I programmet bliver sendt til. Det er i denne funktion vi skal have det meste af vores kode, når vi skal til at lave noget i vores vindue. Hwnd er handleren til vinduet, nMsg indeholder beskederne som bliver sendt til programmet, wParam og lParam kan indeholde forskellige information alt efter hvilken besked der bliver sendt.

Fold kodeboks ind/udKode 


Det næste der kommer er en switch som bruges til at ”skifte” mellem de forskellige beskeder. Der er forskellige cases. WM_CREATE bliver sendt når vores vindue er blevet oprettet, så her kan vi gøre alle de ting vi vil have gjord når vores vindue er oprettet. WM_DESTROY bliver sendt når programmet bliver lukket, så det er her man gør de ting der skal ske når programmet skal lukkes ned.

int WINAPI WinMain (HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpCmd, int nShow)

Nu kommer vores main funktion igen som er beskrevet i første eksempel.
Fold kodeboks ind/udKode 


Det næste vi gør er at vi lave en vindues class som skal bruges til at indeholde information om hvordan vi vil have vores vindue til at se ud. Kommentarerne i koden fortæller hvad de forskellige ting er.

Fold kodeboks ind/udKode 


Det der sker her er at vi laver vores vindue, med funktion CreateWindow(). Læg mærke til at vi bruger vores vindues class som vi lige har lavet. Det er også her vi bestemmer hvad vinduet skal hedde, og hvordan det skal se ud ved hjælp af styles. Stylen WS_OVERLAPPEDWINDOW laver et et normalt vindue med en luk, minimer og maksimer knap. Der ud over bestemmer vi hvor vores vindue skal være på skærmen og hvor stort det skal være. Positionen og størrelsen på vinduet er angivet i pixel, og bliver angivet ud fra et koordinat system som har 0,0 i toppen af højre hjørne.


Det sidste vi gør af at fortælle den skal vise vinduet og opdatere det.

Fold kodeboks ind/udKode 


Det allersidste vi har i vores program er en while funktion som modtager alle meddelser som bliver sendt til programmet, ”oversætter” dem og sender dem videre til vores tilbagekalds funktion.

Tillykke du har nu lært at lave et windoes program, hvis du har fået koden til at virke skulle du gerne have et vindue uden noget i :)

Hvis koden ikke virker så check at du har skrevet alt rigtigt, du kunne måske prøve at kopiere hele koden over og se om det virker. Gør det ikke er det måske fordi din kompiler ikke ved at at du laver et windows program, hvis din kompiler spørger dig om hvilken slags projekt du vil lave skal du vælge et win 32 projekt.

Jeg håber du har lært noget af denne artikel, jeg ved godt at vi ikke fik lært noget om hvad man kan gøre når man har lavet vinduet, men da det er meget besværligt at komme i gang med har jeg valgt bare at beskrive hvordan man laver vinudet. Jeg vil i næste artikel beskrive noget om hvordan man kan komme i gang med at lave nogle ting. Jeg håber du nød at læse artiklen og lærte noget har du nogle spørgsmål er du meget velkommen til at stille dem som en kommentar og jeg skal gøre mit bedste for at svare.

Så har jeg ikke så meget andet at sige end vi ses i artikel nummer 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 (31)

User
Bruger #295 @ 28.10.06 12:11
Glæder mig til næste nummer. :lol:
User
Bruger #3353 @ 30.10.06 15:27
god artikel men får fejl når jeg compiler:

C:\\DOCUME~1\\sope08\\LOKALE~1\\Temp\\ccyqaaaa.o(.text+0xe8) In function `WinMain':
[Linker error] undefined reference to `GetStockObject@4'
C:\\DOCUME~1\\sope08\\LOKALE~1\\Temp\\ccyqaaaa.o(.text+0xe8) ld returned 1 exit status

kan ikke rigtig finde ud af hvad det er der er galt.? bruger dev-c++ med den originale compiler og har kopieret koden.
User
Bruger #7461 @ 30.10.06 17:21
Hey Jørn
Jeg arbejder på den men får ikke lavet så meget fordi jeg har lidt travlt for tiden, men jeg lover den kommer engang inden nytår :)

Hey Smurf :)
Det er fordi når du laver et ny projekt skal du vælge at du vil lave en windows application og ikke en Console application. Hvis du gør det skulle det virke.

Mvh.
Søren
User
Bruger #8985 @ 30.10.06 18:02
Jeg kiggede hurtigt på siste side, gad ikke lige kigge på dem alle, men jeg har endelig fået en brændende lyst for at gå i gang med at programmere C++!
User
Bruger #8985 @ 30.10.06 19:00
Hold kæft jeg er dum, så skriver jeg til den forkerte artikel... Men det er bare dit held du så fik et 5-tal af mig :D
User
Bruger #8502 @ 08.11.06 20:53
Generelt en god artikel.. men;

"hPrev bruges ikke i win32 programmer og vi skal derfor ikke tænke på den." - Lidt overfladisk skrevet, da du dog har inkluderet det i koden?

Kan nogen fortælle mig hvorfor, at jeg bilder mig selv ind, at have læst, at koordinaterne IKKE er angivet efter pixels, men efter skiftstørrelse osv.? - Hvilket passer?

"et koordinat system som har 0,0 i toppen af højre hjørne." - Ikke venstre (som ville være mest logisk)?

Jeg vil nu mene, at lidt indrykning i koden, samt kommentarer i selve koden, efter koden (ikke over eller under) ville give et bedre overblik over kodeeksemplerne.

Tak.
User
Bruger #8502 @ 08.11.06 21:00
Pixel-spørgsmålet fandt jeg selv svar på.
Jeg havde læst en sektion om dialogs og dialog-units. - Fik blandet det hele grundigt sammen :)
User
Bruger #8985 @ 15.11.06 22:55
Kender jeg alt for godt, Steffen :)
User
Bruger #6559 @ 22.11.06 10:38
God artikel, giver en lyst til hoppe stille videre fra Consol :D
User
Bruger #11126 @ 09.01.07 16:45
hvorhenne på computeren finder man filen win32 api??? :D
User
Bruger #8985 @ 23.01.07 17:00
Jeg synes du mangler at forklare en masse ting. Hvorfor skal nogle funktioner være af typen LRESULT, og hvor skal de kunne bruges som CALLBACK? Og hvad med MB_ICONEXCLAMATIN - den mangler du?

/* Vi nulstiller classen */
memset (&wndclass, 0, sizeof(WNDCLASSEX));

Jeg vil gerne vide hvorfor.

/* Vi registre classen så vi kan bruge den til at lave et vindue med */
RegisterClassEx (&wndclass);

Hvorfor _SKAL_ et vindue registreres?

Og jeg kunne blive ved ;)
User
Bruger #8985 @ 23.01.07 17:02
Jeg mente:
og hvorfor skal de kunne bruges som CALLBACK?

...og...

Jeg mente: MB_ICONEXCLAMATION
User
Bruger #10926 @ 14.02.07 10:49
AWESOME!!! denne kode virker og er god til C++ nybegynder (Som mig) 5 POINT TIL DIG :D
User
Bruger #10926 @ 14.02.07 10:49
AWESOME!!! denne kode virker og er god til C++ nybegynder (Som mig) 5 POINT TIL DIG :D
User
Bruger #7461 @ 25.03.07 01:02
Haha jeg ved ikke om den kommentar var tiltænkt mig, men jeg synes nu den er meget sjovt. Jeg synes det er meget fedt Lorita er blevet intresseret i mig, ved at kigge i min profil(hun kan nok ikke læse den, da den er dansk) og jeg har ikke rigtigt nogle billeder af mig der :P Det er nu lidt sjovt med lidt spam engang imellem ;)

Anyways thanks Lorita :)
User
Bruger #8985 @ 17.04.07 13:24
Din Lorita er dig vist utro, jeg har set hende andre steder på sitet med samme kommentar ;)
User
Bruger #11811 @ 11.05.07 13:52
Super artikel, lige hvad jeg manglede.

Er der evt. en der har kildekoden til et program der indeholde diverse funktioner så jeg har noget jeg kan leget med indtil næste artikel kommer? :)
User
Bruger #11861 @ 23.05.07 20:31
UINT ikke UNIT ...
Tak for fire herlige timers debugging :(

Men bortset fra min lille fejl, var artiklen meget tæt på perfekt!
User
Bruger #8985 @ 12.06.07 18:41
Simon Larsen > Hvad tænker du præcis på? For jeg kan muligvis lave noget til dig.
User
Bruger #11328 @ 11.08.07 15:15
Til alle jer der synes koden ser uoverskuelig ud:
Lær den udenad i bidder!!!
det har jeg gjordt og jeg kan nu!
det tog mig kun 2 timer... (Kun og kun.. :P)

anyways 5 herfra for en fantastisk artikel (hvornår kommer 2'eren???)
User
Bruger #10895 @ 30.09.07 18:14
Godt lavet :D
User
Bruger #13276 @ 11.02.08 21:52
er det bare mig eller er der aldrig kommet en nr. 2? please :D
User
Bruger #13669 @ 04.05.08 11:46
for en fejl her:

wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH);

bruger den compiler der kommer med codeblocks, tror den heder noget med gnu.

den skriver:
undefined reference to ´_GetStockObject@4'

har prøvet at slette linien, så fungere det bortset fra at windows vist ikke er så glad for gennemsigtige bagrunde.
User
Bruger #13669 @ 04.05.08 16:24
eller heder den mingw... ved ikk

sry for dobbelt post
User
Bruger #13669 @ 04.05.08 21:06
kørte det i dev c++, der virkede det...
User
Bruger #13964 @ 03.07.08 13:48
Hej. Jeg har lige et spørgsmål hvor jeg er gået i stå.

uType bruges til af beskrive hvordan popup’en skal se ud, det her man bestemmer hvilke knapper man vil have og sådan noget, nedenfor ses en samling af typer man kan bruge. Man kan sammen sætte flere ved at bruge | eks. MB_OK | MB_ICONSTOP.

Min kode ser sådan her ud indtil nu:
#include "windows.h"

int WINAPI WinMain (HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpCmd, int nShow)
{
MessageBox(NULL, "Velkommen til windows api'et", "Windows api", NULL);
int MessageBox(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType);
}

Hvor skal jeg sætte MB_OKCANCEL eller nogen af de andre koder henne? Jeg har prøvet mig frem ved at slette uType, ved at sætte MB_OKCANCEL efter uType osv. osv. men jeg kan ikke finde ud af hvor jeg skal sætte det. Nogen der kan hjælpe mig? :)
Jeg er nybegynder så håber I kan bære over med mig stupidhed :)

- Cosinus.
User
Bruger #7461 @ 04.07.08 13:55
Hej Cosinus

De skal indsættes på uType's plads. Der hvor jeg i eksemplet har skrevet NULL. Sådan her:
MessageBox(NULL, "Velkommen til windows api'et", "Windows api", MB_OKCANCEL);
Og hvis du ønsker at sætte flere ind så skal der en | imellem dem, sådan her:
MessageBox(NULL, "Velkommen til windows api'et", "Windows api", MB_OKCANCEL | MB_ICONSTOP);

Så den rigtige kode ser sådan her ud:

#include "windows.h"

int WINAPI WinMain (HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpCmd, int nShow)
{
MessageBox(NULL, "Velkommen til windows api'et", "Windows api", MB_OKCANCEL);
}

- Sieg
User
Bruger #14212 @ 30.09.08 19:38
Når jeg compiler din kode i visual c++ får jeg fejlen:
Fold kodeboks ind/udKode 

Hvordan kan det være? :S
User
Bruger #8985 @ 11.01.09 03:11
Ej nej nej, og han skriver ikke engang, hvor man kan downloade API'et, hvis det ikke følger med ens compiler. Jesus.

Du skal linke med gdi32.lib for at benytte GetStockObject
User
Bruger #15542 @ 21.01.10 14:07
Super god artikel! Det vigtigste er forklaret, og koden er forståelig!
God forklaring over det hele. Godt at du har tilføjet kommentarer i koden.
øv dig i at lave indryk.

Jeg glæder mig meget til, at du kommer med 2. del af den her artikel!



svar til Christian:
visual c++ er et edit- og compilerprogram, der er udviklet af windows, og har en masse forskellige funktioner, der tjekker koden på forhånd. Desværre har denne compiler også et indbygget register over hvordan tingene skal stå, uafhængigt af compilerens forståen af c++sproget! Så selvom du vælger at du vil lave en win32-applikation, er der mange ting, som dette program ikke forstår.

tag i stedet at downloade CodeBlocks! opret nyt projekt og vælg at lave et "win32 GUI projekt". Compileren i CodeBlocks er meget hurtigere og editoren er nøjagtig lige så go'!
hent den her: http://www.codeblocks.org/downloads


User
Bruger #8985 @ 10.09.11 23:23
Steffen: det skyldes altså at han befinder sig på et UNICODE-system. Smid alle dine strenge i TEXT-makroen, så bliver problemet løst. Altså

MessageBox(hwnd, TEXT("besked"), TEXT("overskrift"), MB_OK);
Du skal være logget ind for at skrive en kommentar.
t