[C++] WIN32/API, Venster maken.
1. Wat gaan we doen
2. Het Venster
3. Het menu
3. De tekst en de knoppen
4. Nawoord
1. Wat gaan we doen
We gaan in deze tutorial eens buiten dat lelijke MS-DOS werken, we gaan namenlijk eerst een venster maken zoals al die "echte programma's" ook hebben, dit doen we met API programmeren, ook wel WIN32. In het venster gaan we een tekst en een knop waarmee we NotePad gaan openen plaatsen, ook maken we een menu bovenin vanwaar wij hetzelfde kunnen doen!
N.B. : Minste verstand van Compilen etc wel vereist, dus graag eerst even de andere tutorials over C++ lezen!
Uiteindelijke resultaat zal worden:
top
2. Het venster
We gaan eerst natuurlijk een leuk venstertje maken om het straks allemaal in te zetten, staat commentaar bij, voor de oplettende lezer, dit is inderdaad gewoon een vertaalde versie van wat
Dev-Cpp je geeft als je kiest voor Window..
(ik gebruik ook steeds Dev-Cpp)
#include <windows.h> // windows.h includen, het bestand dat dit mogelijk maakt, de <> eromheen geven aan dat het gewoon ergens in je WINDOWS map staat..
/* WindowProcedure maken, weet niet precies waarvoor dat dient eigenlijk:P */
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);
/* Naam voor de windowclass */
char szClassName[ ] = "tutorial";
int WINAPI WinMain (HINSTANCE hThisInstance,
HINSTANCE hPrevInstance,
LPSTR lpszArgument,
int nFunsterStil)
{
HWND hwnd; /* hier komt ons window in */
MSG messages; /* hier komen berichten van het programma in */
WNDCLASSEX wincl; /* data structuur voor de class */
/* Structuur van de window */
wincl.hInstance = hThisInstance;
wincl.lpszClassName = szClassName;
wincl.lpfnWndProc = WindowProcedure; /* This function is called by windows */
wincl.style = CS_DBLCLKS; /* Catch double-clicks */
wincl.cbSize = sizeof (WNDCLASSEX);
/* Normaal icoontje en cursor gebruiken... */
wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
wincl.lpszMenuName = NULL; /* Geen menu */
wincl.cbClsExtra = 0; /* Geen bytes na de window class */
wincl.cbWndExtra = 0; /* structuur voor de window instance */
/* Achtergrond maken we gewoon de windows achtergrondkleur van */
wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;
/* Registreer de windowclas, als dit al niet gaat word het programma afgesloten */
if (!RegisterClassEx (&wincl))
return 0;
/* We leven nog, class bestaat, nu maar het programma zelf opbouwen */
hwnd = CreateWindowEx (
0, /* Opties... gewoon 0 */
szClassName, /* naam van onze window class */
"Tutorial", /* Komt bovenaan te staan (titel) */
WS_OVERLAPPEDWINDOW, /* normaal window */
CW_USEDEFAULT, /* Windows bepaalt waar we de window plaatsen */
CW_USEDEFAULT, /* zie hierboven */
544, /* breedte v/h programma */
375, /* hoogte natuurlijk ook */
HWND_DESKTOP, /* ons programma is een kindje van Desktop (als je bv. een 2e window maakt kan je die aan deze koppelen) */
NULL, /* Geen menu nog steeds */
hThisInstance, /* Programma instance */
NULL /* geen data voor window maken */
);
/* en nu, gaan we het laten zien! */
ShowWindow (hwnd, nFunsterStil);
/* loopje om de berichten op te vangen */
while (GetMessage (&messages, NULL, 0, 0))
{
/* zorg dat het echte berichten worden */
TranslateMessage(&messages);
/* en verzend het bericht naar WindowProcedure() */
DispatchMessage(&messages);
}
return messages.wParam;
}
/* hier zochten we net naar */
LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message) /* verzorg de berichten */
{
case WM_DESTROY:
PostQuitMessage (0); /* verzend WM_QUIT als bericht */
break;
default: /* onbelangrijke berichten, doen we lekker niets mee:P */
return DefWindowProc (hwnd, message, wParam, lParam);
}
return 0;
}
|
top
3. Het menu
hier gaan we met 2 meer bestanden werken, niet schrikken, overzichtelijke bestanden, ook bestanden waar je heel snel veel van begrijpt.
Allereerst gaan we weer in ons vorige bestandje werken, we voegen hier de volgende regels toe:
na #include plaatsen we een enter en zetten we #include "menu.h" , dit zorgt ervoor dat we straks met een menu zoals er bij notepad staat (Nieuw, Open etc)
na onze HWND hwnd regeltjes zetten we HMENU menu neer, onze handle voor het menu
en vervolgens na de regel ShowWindow(~ : menu = LoadMenu(hThisInstance, MAKEINTRESOURCE(ID_MENU));
SetMenu(hwnd, menu);
ons menu is geladen, maar als we nu compilen krijgen we een dikke error, want menu.h bestaat niet...
Dus we gaan verder, we voegen eerst het bestand menu.h toe aan ons project (als je met Dev-Cpp werkt, hoeft verder niet hoor..)
hierin zetten we de volgende code:
#define ID_MENU 501
#define IDM_OPENNOTEPAD 201
#define IDM_SLUIT 202
#define IDM_ABOUT 203
|
eerst definen we ID_MENU, met een cijfer erachter, als je eigenwijs was en zonder menu.h toch even wou gaan compilen had je ergens tussen de errors ID_MENU gezien, hier is die dus.
Elke IDM_{naam} met nummer is een menuitem, gaan we zo mee werken in het volgende bestand, dit noemen we "rscr.rc", (zonder de aanhalingstekens), dit hoeven we nergens te includen!
Inhoud van dat bestand:
#include
#include "menu.h"
501 MENU
BEGIN
POPUP "&Programma"
BEGIN
MENUITEM "&Open kladblok", IDM_OPENNOTEPAD
MENUITEM SEPARATOR
MENUITEM "&Sluit programma", IDM_SLUIT
END
POPUP "&Overig"
BEGIN
MENUITEM "&Over", IDM_ABOUT
END
END
|
hier includen we weer het menu en windows.h, en dat nummer 501 wat we toenstraks aan ID_MENU gaven, komt hier weer terug. We zetten dat neer met MENU erachter (want we zeiden ID_MENU) en BEGIN als teken dat ons menu gaat beginnen.
Met POPUP "&Programma" gaven we ons eerste dropdown menu de titel Programma, niet op de & letten, die gaat automatisch weg.
met MENUITEM "naam", IDM_naam zorgen we dat er een item met de IDM_ naam die we ook al hadden gedefineerd.
met MENUITEM SEPARATOR krijgen we een soort >hr< lijn in ons menu.
END zorgt ervoor dat onze POPUP of het hele menu weer afloopt.
als we dit gaan compileren, hebben we een programmatje met menu, er gebeurt niets als we ergens klikken, maar het ziet er leuk uit.
Nu willen we natuurlijk dat er wel iets gebeurt als we ergens op klikken, let's do that!
We hadden al berichten afgehandeld, dachten we, maar wat gebeurt er nou als jij op Programma->Sluit drukt?
Er word zo'n bericht verzonden met de naam van ons menuitem, dus als we die te pakken krijgen,en dan de actie uitvoeren die erbijhoort, zijn we klaar, toch?
Klinkt simpel, is het eigenlijk ook, C++ lijkt ook wel op PHP... zie de volgende code maar..(zet neer na case: WM_DESTROY~break;)
case WM_COMMAND:
switch( wParam)
{
case IDM_SLUIT:
DestroyWindow( hwnd );
return 0;
break;
case IDM_OPENNOTEPAD:
ShellExecute ( NULL, "Open", "C:\WINDOWS\notepad.exe", 0, "C:\WINDOWS\notepad.exe", SW_SHOWDEFAULT );
return 0;
break;
case IDM_ABOUT:
MessageBox(NULL,"Tutorial over WIN32 Programmeren!
Versie: Tutorial","About",1);
return 0;
break;
}
break;
|
als er een WM_COMMAND is gegeven (wat we dus doen door op een menuitem te klikken) wordt er als we op sluit hebben gedrukt het programma gesloten,
als we kladblok wouden openen, word dat geopend (let op de \, met escape je hier ook!)
en als we About opvragen komt er een alert met als titel About en dan is de 3e parameter inderdaad de inhoud ervan:P
Dus hiermee zijn we ook klaar, op naar het volgende onderdeel!
top
4. De tekst en de knop
Nu gaan we een tekst in ons programma neerzetten, dit gaat niet met de functie cout zoals we die nog zo makkelijk in DOS konden gebruiken...
We maken hiervoor WEER een nieuw venster, maar deze komt binnen ons programma en is anders dan wat we al hadden, niet eerst tig dingen defineren, komt ie aan!
We zetten onder waar we ons menu laadden (SetMenu) dit neer:
CreateWindow("Static", //vensterklasse naam, dit MOET Static zijn, werkt anders niet (ervaring!)
"Dit is een tutorial, hij is heel leerzaam voor elke programmeur!
PS: PHP is een scripttaal, C++ een Programmeertaal, in PHP script je, in C++ Programmeer je!", //tekst
WS_CHILD|WS_VISIBLE, //stijl
0, //positie X (in pixels)
0, //positie Y (in pixels)
500, //breedte in pixels
400, //hoogte in pixels
hwnd, //handle van hoofdvenster
0,
hThisInstance, //handle van instantie
0
);
|
en we hebben tekst!
Nu willen we ook een mooie knop waarmee we ook maar KladBlok kunnen openen, hiervoor moeten we eerst maar weer iets bij de berichten veranderen, anders gebeurt er weer niets als we op de knop drukken!
We maken van WM_COMMAND: ~, het volgende:
case WM_COMMAND:
if ( HIWORD ( wParam ) == BN_CLICKED &&
HWND ( lParam ) == ChildButton )
{
ShellExecute ( NULL, "Open", "C:\WINDOWS\notepad.exe", 0, "C:\WINDOWS\notepad.exe", SW_SHOWDEFAULT );
return 0;
}
else {
switch( wParam )
{
case IDM_SLUIT:
DestroyWindow( hwnd );
return 0;
break;
case IDM_OPENNOTEPAD:
ShellExecute ( NULL, "Open", "C:\WINDOWS\notepad.exe", 0, "C:\WINDOWS\notepad.exe", SW_SHOWDEFAULT );
return 0;
break;
case IDM_ABOUT:
MessageBox(NULL,"Tutorial over WIN32 Programmeren!
Versie: Tutorial","About",1);
return 0;
break;
}
break;
case WM_CREATE:
{
ChildButton = CreateWindowEx ( 0,
"Button",
"Notepad",
WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON,
0,
120,
100,
30,
hwnd,
NULL,
GetModuleHandle ( NULL ),
NULL );
return 0;
}
|
Zoals je ziet voegen we NOG een WM toe, dit is de WM_CREATE, het bericht dat verzonden word bij het laden van het programmma, hierbij zetten we onze button.
Verder moeten we nog om niet een error te creeren boven switch(message) het volgend zetten:
static HWND ChildButton = NULL;
top
5. Nawoord
Dit was het dan, de tutorial, hoop dat jullie er wat van hebben geleerd, kijk nog eens rustig naar de code. Probeer ook voor jezelf te kijken wat er gebeurt als je dit veranderd, of wat als je dat doet...
Verder mag je punten geven, no problemo, maar als je laag of juist hoog geeft zeg even waarom.
Timo
|