Part 1

Code:
>Your First glimpse at a Win32 application:

CODE
#include <windows.h>

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
       MessageBox (NULL, "Hello World" , "Tutorial", 0);
       return 0;
}


Whoa! What is all that garbage. An explanation:

int WinMain is the windows equivalent of int main() in a console app. This is where the program starts when you compile your program.

WinMain() accepts the following parameters:

1. hInstance -Identifies the programs current instance.
2. hPrevInstance -Identifies the previous instance of the program. For a Win32 application, this parameter is always NULL.
3. lpCmdLine -Holds the command line arguments in a string. (Equivelant of argv[1] argv[2] in a console application)
4. nCmdShow -Value to be passed to the ShowWindow() API.

Notice the things like LPSTR in the parameter list. These are windows specific definitions. LPSTR is the same as char *. These things are

there to increase portability. You can use which ever one you prefer. Both char * and LPSTR will work.

MessageBox is a function that can be used to display a ...... MessageBox. tongue.gif
It accepts the following parameters:

1. hWnd -Identifies the owner  of the MessageBox that will be created. If this is set to NULL then the MessageBox will have no owner

window.
2. lpText -This is the text that you want to be displayed in the MessageBox.
3. lpCaption -This is caption text of your MessageBox
4. uType -This parameter allows you to customize your MessageBox. Eg: display a warning or information icon.

Ok, now that that is done let's get down to REAL GUI programming.

>Creating a Simple Window:

Here is the source to a simple window:

CODE
#include <windows.h>

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

static char sClassName[]  = "MyClass";
static HINSTANCE zhInstance = NULL;

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
       WNDCLASSEX WndClass;
       HWND hwnd;
       MSG Msg;

       zhInstance = hInstance;

       WndClass.cbSize        = sizeof(WNDCLASSEX);
       WndClass.style         = NULL;
       WndClass.lpfnWndProc   = WndProc;
       WndClass.cbClsExtra    = 0;
       WndClass.cbWndExtra    = 0;
       WndClass.hInstance     = zhInstance;
       WndClass.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
       WndClass.hCursor       = LoadCursor(NULL, IDC_ARROW);
       WndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
       WndClass.lpszMenuName  = NULL;
       WndClass.lpszClassName = sClassName;
       WndClass.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);

       if(!RegisterClassEx(&WndClass)) {
               MessageBox(0, "Error Registering Class!", "Error!", MB_ICONSTOP | MB_OK);
               return 0;
       }

       hwnd = CreateWindowEx(WS_EX_STATICEDGE, sClassName, "db Tutorial", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,

CW_USEDEFAULT,
                      320, 240, NULL, NULL, zhInstance, NULL);

       if(hwnd == NULL) {
               MessageBox(0, "Error Creating Window!", "Error!", MB_ICONSTOP | MB_OK);
               return 0;
       }

       ShowWindow(hwnd, nCmdShow);
       UpdateWindow(hwnd);

       while(GetMessage(&Msg, NULL, 0, 0)) {
               TranslateMessage(&Msg);
               DispatchMessage(&Msg);
       }

       return Msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) {
       switch(Message) {
               case WM_CLOSE:
                       DestroyWindow(hwnd);
                       break;
               case WM_DESTROY:
                       PostQuitMessage(0);
                       break;
               default:
                       return DefWindowProc(hwnd, Message, wParam, lParam);
       }
       return 0;
}


That does look confusing doesn't it? ;D. Well .... don't worry. You don't need to memorize all of this. Most people just create this once, then

save it as a seperate .cpp/.c file. Then, whenever they are creating a GUI application they just copy the code over to their application. This is

the skeleton of a GUI program.

Now lets get down to explaining all that stuff:

Windows programs unlike console applications are event driven. They remain idle until they recieve a message. Once they get a message,

they act on the message and then wait for the next message. When a windows application responds to a message it's called "Message

Handling".

As you can see I declared a prototype of my WndProc() function at the begining. It will be explained later.
Inside the WinMain() we see some strange new variables. Some of them include WndClass, hwnd and msg. Now, the msg struct contains

information from a threads message queue. The next thing we come to is when the hInstance is made global in the variable zhInstance. After

that we come to the defining of each of the WndClass settings:

1. cbSize -Holds the size of this structure in bytes, Always set this to the size of WndClassEx or WndClass.
2. style -The style of our window. For now just set it to NULL.
3. lpfnWndProc -This points to our Windows Callback Procedure ie: "WndProc".
4. cbClsExtra -The amount of extra data to be allocated for this class in memory. Set this to 0.
5. cbWndExtra -Amount of extra data to be allocated in memory per Window. Again, set this to 0
6. hInstance -The handle for the window instance.
7. hIcon -The icon that will be displayed when the users presses ALT+TAB. Don't worry too much about this at the moment.
8. hCursor -The cursor that will be used in our program. Again don't worry about this now.
9. hbrBackround -The brush that we will use to set the colour of our backround.
10. lpszMenuName -The name of the menu resource to use. We will not cover menu's in this tutorial, so set it to NULL.
11. lpszClassName -The name to identify the class with.
12. hIconSm -The small icon show in the top-left cornor of our program and in the taskbar.

Once we've filled in all that information, we need to "Register" our window class. So, we pass on our WndClass structure to RegisterClass or

RegisterClassEx.

Now, we need to actually create the window. We will use the CreateWindow() or CreateWindowEx() API to create our window. We store it in

hwnd which will later be passed onto ShowWindow(). CreateWindowEx() takes the following parameters:

dwExStyle -Tells it what style of window we want. We will use a plain static window.
lpClassName -Points to the classname we came up with earlier on.
lpWindowName -The titlebar text of our window.
dwStyle -The style of window we are creating.
x -The horizontal starting position of the window. Setting this to CW_USEDEFAULT will let windows pick a place.
y -The verticle starting position of our window. Again, Setting this to CW_USEDEFAULT will place the window randomly
nWidth -Width of our window.
nHeight -Height of our window.
hWndParent -The handle of the parent window. For now just set this to NULL since we don't have a parent.
hMenu -Identifies the menu for out window. Only applies if it's a child window.
hInstance -The hInstance of our window.
lpParam -Points to a value passed to the window through the CREATESTRUCT structure.

Now.... ShowWindow() sets our windows state. UpdateWindow() updates the client area of our window by sending a WM_PAINT message to

our window. The while() loop will set our program to loop until the WM_QUIT or WM_DESTROY message is recieved. TranslateMessage() will

translate virtual key messages into character messages. DispatchMessage() will dispatch a message to a windows procedure.

WH0000!!! I'm really tired now but wtf? tongue.gif
Let's get to the most important part of our program. Our CallBack Procedure. What this is, is a function with a beeeeg giant switch()

statement to switch of what each message should do. Our CallBack takes the following parameters:

hwnd -Identifies our window.
uMsg -Specified the message.
wParam -Specifies the aditional message information. The contents of this value depends on the value of the uMsg.
lParam -Specifies additonal message info. Again the contents of this value depends on uMsg.

Now, in our switch() statement we see a WM_CLOSE. This message tells us if our user clicked the 'X' button in our program or they hit

ALT+F4. By using WM_CLOSE we can prompt the user if he wants to save his current work or whatever.
Part 2
Code:
OK, now let's get started!

>Skeleton of a Win32 proggie:

CODE
#include <windows.h>

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

static char gszClassName[]  = "darkblue";
static HINSTANCE ghInstance = NULL;

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
       WNDCLASSEX WndClass;
       HWND hwnd;
       MSG Msg;

       ghInstance = hInstance;

       WndClass.cbSize        = sizeof(WNDCLASSEX);
       WndClass.style         = NULL;
       WndClass.lpfnWndProc   = WndProc;
       WndClass.cbClsExtra    = 0;
       WndClass.cbWndExtra    = 0;
       WndClass.hInstance     = ghInstance;
       WndClass.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
       WndClass.hCursor       = LoadCursor(NULL, IDC_ARROW);
       WndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
       WndClass.lpszMenuName  = NULL;
       WndClass.lpszClassName = gszClassName;
       WndClass.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);

       if(!RegisterClassEx(&WndClass)) {
               MessageBox(0, "Window Registration Failed!", "Error!", MB_ICONSTOP | MB_OK);
               return 0;
       }

       hwnd = CreateWindowEx(
               WS_EX_STATICEDGE,
               gszClassName,
               "darkblue owNz!",
               WS_OVERLAPPEDWINDOW,
               CW_USEDEFAULT, CW_USEDEFAULT,
               320, 240,
               NULL, NULL,
               ghInstance,
               NULL);

       if(hwnd == NULL) {
               MessageBox(0, "Window Creation Failed!", "Error!", MB_ICONSTOP | MB_OK);
               return 0;
       }

       ShowWindow(hwnd, nCmdShow);
       UpdateWindow(hwnd);

       while(GetMessage(&Msg, NULL, 0, 0)) {
               TranslateMessage(&Msg);
               DispatchMessage(&Msg);
       }
       return Msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) {
       switch(Message) {
               case WM_CLOSE:
                       DestroyWindow(hwnd);
                       break;
               case WM_DESTROY:
                       PostQuitMessage(0);
                       break;
               default:
                       return DefWindowProc(hwnd, Message, wParam, lParam);
       }
       return 0;
}


Right, now lets move onto TEXT!
So..... how do we write text to the screen? It isn't very easy nor hard.

CODE
#include <windows.h>

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

static char gszClassName[]  = "darkblue";
static HINSTANCE ghInstance = NULL;

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
       WNDCLASSEX WndClass;
       HWND hwnd;
       MSG Msg;

       ghInstance = hInstance;

       WndClass.cbSize        = sizeof(WNDCLASSEX);
       WndClass.style         = NULL;
       WndClass.lpfnWndProc   = WndProc;
       WndClass.cbClsExtra    = 0;
       WndClass.cbWndExtra    = 0;
       WndClass.hInstance     = ghInstance;
       WndClass.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
       WndClass.hCursor       = LoadCursor(NULL, IDC_ARROW);
       WndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
       WndClass.lpszMenuName  = NULL;
       WndClass.lpszClassName = gszClassName;
       WndClass.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);

       if(!RegisterClassEx(&WndClass)) {
               MessageBox(0, "Error Registering Window!", "Error!", MB_ICONSTOP | MB_OK);
               return 0;
       }

       hwnd = CreateWindowEx(
               WS_EX_STATICEDGE,
               gszClassName,
               "darkblue owNz!",
               WS_OVERLAPPEDWINDOW,
               CW_USEDEFAULT, CW_USEDEFAULT,
               320, 240,
               NULL, NULL,
               ghInstance,
               NULL);

       if(hwnd == NULL) {
               MessageBox(0, "Window Creation Failed!", "Error!", MB_ICONSTOP | MB_OK);
               return 0;
       }

       ShowWindow(hwnd, nCmdShow);
       UpdateWindow(hwnd);

       while(GetMessage(&Msg, NULL, 0, 0)) {
               TranslateMessage(&Msg);
               DispatchMessage(&Msg);
       }
       return Msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) {
       HDC hdc;
       PAINTSTRUCT ps;
       LPSTR szMessage = "darkblue 0wNz j00!";

       switch(Message) {
               case WM_PAINT:
                       hdc = BeginPaint(hwnd, &ps);
                       TextOut(hdc, 70, 50, szMessage, strlen(szMessage));
                       EndPaint(hwnd, &ps);
                       break;
               case WM_CLOSE:
                       DestroyWindow(hwnd);
                       break;
               case WM_DESTROY:
                       PostQuitMessage(0);
                       break;
               default:
                       return DefWindowProc(hwnd, Message, wParam, lParam);
       }
       return 0;
}


WHOA! wtf is all that new stuff. All this does is print "darkblue OwNz j00!" to the screen. Not very pretty tongue.gif
Now let's explain. At the top of the WinProc I added a few more variables. HDC identifies the display DC to used
for painting to the screen. PS is out paint structure. The PAINTSTRUCT structure contains information for an
application. This info can be used to paint to the client area of our windows. Message is a simple char array that
holds our message.

After that I added a new case statement. Remember what I said about how UpdateWindow() sends the message WM_PAINT,
well here is where we can use it. Firstly we have to tell the HDC to recieve painting information from BeginPaint().
Now, BeginPaint() takes the following parameters:

hwnd - This identifies the window to be painted to.
pPaint - A pointer to the PAINTSTRUCT structure that will recieve the painting info.

Once we've done that, we can use TextOut() to print to the screen. Now TextOut() takes the following parameters:

hdc - This identifies the device context.
nXStart - Specifies the x-coordinate of the reference point that Windows uses to align the string.
nYStart - Specifies the y-coordinate of the reference point that Windows uses to align the string.
lpString - This points to the string that we want to print.
cbStrng - This specifies the number of chars. in the string.

OK, now for EndPaint(). EndPaint() tells the program that we are done printing to the screen. It takes the following
parameters:

hwnd - This identifies the window that we painted to.
lpPaint - This points to the PAINTSTRUCT structure that we used that contains the painting info. retrieved
by BeginPain().

>Controls:
What are controls? Controls are like child windows such as buttons, checkboxes, edit boxes etc etc. For each new
control that we make we make a new window using CreateWindowEx(), but these are childs of the first main window
and are not new windows.

OK, i've put everything that i could think of together and this is what I came up with:

CODE
#include <windows.h>

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

static char gszClassName[]  = "db Tutorial";
static HINSTANCE ghInstance = NULL;

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
       WNDCLASSEX WndClass;
       HWND hwnd;
       MSG Msg;

       ghInstance = hInstance;

       WndClass.cbSize        = sizeof(WNDCLASSEX);
       WndClass.style         = NULL;
       WndClass.lpfnWndProc   = WndProc;
       WndClass.cbClsExtra    = 0;
       WndClass.cbWndExtra    = 0;
       WndClass.hInstance     = ghInstance;
       WndClass.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
       WndClass.hCursor       = LoadCursor(NULL, IDC_ARROW);
       WndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
       WndClass.lpszMenuName  = NULL;
       WndClass.lpszClassName = gszClassName;
       WndClass.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);

       if(!RegisterClassEx(&WndClass)) {
               MessageBox(0, "Error Registering Window!", "Error!", MB_ICONSTOP | MB_OK);
               return 0;
       }

       hwnd = CreateWindowEx(
               WS_EX_STATICEDGE,
               gszClassName,
               "darkblue 0wNz j00!",
               WS_OVERLAPPEDWINDOW,
               CW_USEDEFAULT, CW_USEDEFAULT,
               320, 240,
               NULL, NULL,
               ghInstance,
               NULL);

       if(hwnd == NULL) {
               MessageBox(0, "Window Creation Failed!", "Error!", MB_ICONSTOP | MB_OK);
               return 0;
       }

       ShowWindow(hwnd, nCmdShow);
       UpdateWindow(hwnd);

       while(GetMessage(&Msg, NULL, 0, 0)) {
               TranslateMessage(&Msg);
               DispatchMessage(&Msg);
       }
       return Msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) {
       HWND hButton, hCombo, hEdit, hList, hScroll, hStatic;

       switch(Message) {
               case WM_CREATE:
                       hButton = CreateWindowEx(
                                NULL,
                               "Button",
                               "Button Example",
                               WS_BORDER | WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
                               0, 0,
                               100, 30,
                               hwnd, NULL,
                               ghInstance,
                               NULL);
                       hCombo  = CreateWindowEx(
                               NULL,
                               "ComboBox",
                               "darkblue",
                               WS_BORDER | WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST,
                               0, 30,
                               100, 100,
                               hwnd, NULL,
                               ghInstance,
                               NULL);
                       hEdit   = CreateWindowEx(
                               NULL,
                               "Edit",
                               "edit box example",
                               WS_BORDER | WS_CHILD | WS_VISIBLE,
                               0, 60,
                               100, 30,
                               hwnd, NULL,
                               ghInstance,
                               NULL);
                       hList   = CreateWindowEx(
                               NULL,
                               "ListBox",
                               "db db db",
                               WS_BORDER | WS_CHILD | WS_VISIBLE,
                               100, 0,
                               100, 200,
                               hwnd, NULL,
                               ghInstance,
                               NULL);
                       hScroll = CreateWindowEx(
                               NULL,
                               "ScrollBar",
                               "",
                               WS_BORDER | WS_CHILD | WS_VISIBLE | SBS_VERT,
                               210, 0,
                               100, 200,
                               hwnd, NULL,
                               ghInstance,
                               NULL);
                       hStatic = CreateWindowEx(
                               NULL,
                               "Static",
                               "",
                               WS_BORDER | WS_CHILD | WS_VISIBLE | SS_BLACKRECT,
                               0, 90,
                               100, 30,
                               hwnd, NULL,
                               ghInstance,
                               NULL);
                       break;
               case WM_CLOSE:
                       DestroyWindow(hwnd);
                       break;
               case WM_DESTROY:
                       PostQuitMessage(0);
                       break;
               default:
                       return DefWindowProc(hwnd, Message, wParam, lParam);
       }
       return 0;
}


I have already explained the CreateWindowEx() API so this should be fairly simple. If you don't understand anything,
feel free to contact me OR look it up on google.

>Menus:
When programming there are usually a few ways of doing something, making a menu is no different tongue.gif. I am going
to go over 2 ways of making a menu. Both will do the same thing.

>>Method 1: Making a menu using Resources
From what I have done and seen, using resources to make a menu is one of the easiest things. Basically, the menu
is predefined in a resource file (a file with a .rc extention). The resource files are compiled by the resouce
compiler and linked to the program when the linker is run. This is the first program where I am also going to
throw in additional files besides the source files.

Our header file:

This is our header file. Here we are just defining all the ID's we are going to use so that we can just include
this in both the resource file and in the source file. (Save as tutorial.h)

CODE
#define ID_FILE_NEW           100
#define ID_FILE_OPEN          101
#define ID_FILE_SAVE          102
#define ID_FILE_EXIT          103
#define ID_DO_SOMETHING       104
#define ID_DO_SOMETHING_ELSE  105
#define ID_HELP_ABOUT         106


Our resource file:

This is going to be our resource file. Here we just define the layout of the menus and giving them message
ID's. These message ID's have to be defined in both the resource file and the source file. This is why we use a
header file to define them and then we just include the header file.

CODE
#include "tutorial.h"

ID_MENU MENU DISCARDABLE
BEGIN
       POPUP "&File"
       BEGIN
               MENUITEM "&New",             ID_FILE_NEW
               MENUITEM "&Open",            ID_FILE_OPEN
               MENUITEM "&Save",            ID_FILE_SAVE
               MENUITEM SEPARATOR
               MENUITEM "E&xit",            ID_FILE_EXIT
       END
       POPUP "&Do"
       BEGIN
               MENUITEM "&blaaaa",       ID_DO_SOMETHING
               MENUITEM "lalalalallal",  ID_DO_SOMETHING_ELSE
       END
       POPUP "&Help"
       BEGIN
               MENUITEM "&About db",           ID_HELP_ABOUT
       END
END


Main source file:

CODE
#include <windows.h>
#include "tutorial.h"

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

static char gszClassName[]  = "db";
static HINSTANCE ghInstance = NULL;

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
       WNDCLASSEX WndClass;
       HWND hwnd;
       MSG Msg;

       ghInstance = hInstance;

       WndClass.cbSize        = sizeof(WNDCLASSEX);
       WndClass.style         = NULL;
       WndClass.lpfnWndProc   = WndProc;
       WndClass.cbClsExtra    = 0;
       WndClass.cbWndExtra    = 0;
       WndClass.hInstance     = ghInstance;
       WndClass.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
       WndClass.hCursor       = LoadCursor(NULL, IDC_ARROW);
       WndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
       WndClass.lpszMenuName  = "ID_MENU";
       WndClass.lpszClassName = gszClassName;
       WndClass.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);

       if(!RegisterClassEx(&WndClass)) {
               MessageBox(0, "Window Registration Failed!", "Error!", MB_ICONSTOP | MB_OK);
               return 0;
       }

       hwnd = CreateWindowEx(
               WS_EX_STATICEDGE,
               gszClassName,
               "db's Menu Tutorial",
               WS_OVERLAPPEDWINDOW,
               CW_USEDEFAULT, CW_USEDEFAULT,
               320, 240,
               NULL, NULL,
               ghInstance,
               NULL);

       if(hwnd == NULL) {
               MessageBox(0, "Window Creation Failed!", "Error!", MB_ICONSTOP | MB_OK);
               return 0;
       }

       ShowWindow(hwnd, nCmdShow);
       UpdateWindow(hwnd);

       while(GetMessage(&Msg, NULL, 0, 0)) {
               TranslateMessage(&Msg);
               DispatchMessage(&Msg);
       }
       return Msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) {
       switch(Message) {
               case WM_CLOSE:
                       DestroyWindow(hwnd);
                       break;
               case WM_DESTROY:
                       PostQuitMessage(0);
                       break;
               case WM_COMMAND:
                       switch(LOWORD(wParam)) {
                               case ID_FILE_NEW:
                                       MessageBox(hwnd, "You Clicked New File", "Menu", 0);
                                       break;
                               case ID_FILE_OPEN:
                                       MessageBox(hwnd, "Blaaa ... Open File", "Menu", 0);
                                       break;
                               case ID_FILE_SAVE:
                                       MessageBox(hwnd, "Save Save Save", "Menu", 0);
                                       break;
                               case ID_FILE_EXIT:
                                       PostQuitMessage(0);
                               case ID_DO_SOMETHING:
                                       MessageBox(hwnd, "blaaaaaa!", "Menu", 0);
                                       break;
                               case ID_DO_SOMETHING_ELSE:
                                       MessageBox(hwnd, "lalalalllaa", "Menu", 0);
                                       break;
                               case ID_HELP_ABOUT:
                                       MessageBox(hwnd, "db 0wnZ j00!!", "About", 0);
                                       break;
                       }
                       break;
               default:
                       return DefWindowProc(hwnd, Message, wParam, lParam);
       }
       return 0;
}


You see we have changed the "WndClass.lpszMenuName" to what the name of our menu is. There we also added a
WM_COMMAND in our switch statement. This is the message that is posted when a person clicks on a menu item.
The ID of the item is sent with the message. We use LOWORD() to get the message from the lower word of the
32-bit. LOWORD() takes the following parameters:

dwValue - The value to get the lower word from.

>>Method 2: Making a menu on the spot
Using resource menus is great if you want a menu that won't change. But some programs require menu's that can
be changed on the spot! This might be used to add or delete items from the menu or to make some menu items grey.

Header file:

CODE
#define ID_FILE_NEW     100
#define ID_FILE_OPEN          101
#define ID_FILE_SAVE          102
#define ID_FILE_EXIT          103
#define ID_DO_SOMETHING       104
#define ID_DO_SOMETHING_ELSE  105
#define ID_HELP_ABOUT         106


Main source file:

CODE
#include <windows.h>
#include "tutorial.h"

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

static char gszClassName[]  = "db";
static HINSTANCE ghInstance = NULL;

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
       WNDCLASSEX WndClass;
       HWND hwnd;
       MSG Msg;
       ghInstance = hInstance;

       WndClass.cbSize        = sizeof(WNDCLASSEX);
       WndClass.style         = NULL;
       WndClass.lpfnWndProc   = WndProc;
       WndClass.cbClsExtra    = 0;
       WndClass.cbWndExtra    = 0;
       WndClass.hInstance     = ghInstance;
       WndClass.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
       WndClass.hCursor       = LoadCursor(NULL, IDC_ARROW);
       WndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
       WndClass.lpszMenuName  = NULL;
       WndClass.lpszClassName = gszClassName;
       WndClass.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);

       if(!RegisterClassEx(&WndClass)) {
               MessageBox(0, "Window Registration Failed!", "Error!", MB_ICONSTOP | MB_OK);
               return 0;
       }

       hwnd = CreateWindowEx(
               WS_EX_STATICEDGE,
               gszClassName,
               "db Menu Tutorial",
               WS_OVERLAPPEDWINDOW,
               CW_USEDEFAULT, CW_USEDEFAULT,
               320, 240,
               NULL, NULL,
               ghInstance,
               NULL);

       if(hwnd == NULL) {
               MessageBox(0, "Window Creation Failed!", "Error!", MB_ICONSTOP | MB_OK);
               return 0;
       }

       ShowWindow(hwnd, nCmdShow);
       UpdateWindow(hwnd);

       while(GetMessage(&Msg, NULL, 0, 0)) {
               TranslateMessage(&Msg);
               DispatchMessage(&Msg);
       }
       return Msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) {
       HMENU hMenu, hSubMenu;

       switch(Message) {
               case WM_CLOSE:
                       DestroyWindow(hwnd);
                       break;
               case WM_DESTROY:
                       PostQuitMessage(0);
                       break;
               case WM_CREATE:
                       hMenu = CreateMenu();

                       hSubMenu = CreatePopupMenu();
                       AppendMenu(hSubMenu, MF_STRING, ID_FILE_NEW, "&New");
                       AppendMenu(hSubMenu, MF_STRING, ID_FILE_OPEN, "&Open");
                       AppendMenu(hSubMenu, MF_STRING, ID_FILE_SAVE, "&Save");
                       AppendMenu(hSubMenu, MF_SEPARATOR, 0, 0);
                       AppendMenu(hSubMenu, MF_STRING, ID_FILE_EXIT, "E&xit");
                       AppendMenu(hMenu, MF_STRING | MF_POPUP, (UINT)hSubMenu, "&File");

                       hSubMenu = CreatePopupMenu();
                       AppendMenu(hSubMenu, MF_STRING, ID_DO_SOMETHING, "&blaaaa");
                       AppendMenu(hSubMenu, MF_STRING, ID_DO_SOMETHING_ELSE, "lalalalal");
                       AppendMenu(hMenu, MF_STRING | MF_POPUP, (UINT)hSubMenu, "&Do");

                       hSubMenu = CreatePopupMenu();
                       AppendMenu(hSubMenu, MF_STRING, ID_HELP_ABOUT, "&About db");
                       AppendMenu(hMenu, MF_STRING | MF_POPUP, (UINT)hSubMenu, "&Help");

                       SetMenu(hwnd, hMenu);
                       break;
               case WM_COMMAND:
                       switch(LOWORD(wParam)) {
                               case ID_FILE_NEW:
                                       MessageBox(hwnd, "A brand newwwww newww file", "Menu", 0);
                                       break;
                               case ID_FILE_OPEN:
                                       MessageBox(hwnd, "OoOpen a File!", "Menu", 0);
                                       break;
                               case ID_FILE_SAVE:
                                       MessageBox(hwnd, "Save Save save Save", "Menu", 0);
                                       break;
                               case ID_FILE_EXIT:
                                       PostQuitMessage(0);
                               case ID_DO_SOMETHING:
                                       MessageBox(hwnd, "blaaaaa!", "Menu", 0);
                                       break;
                               case ID_DO_SOMETHING_ELSE:
                                       MessageBox(hwnd, "lalalalalalal", "Menu", 0);
                                       break;
                               case ID_HELP_ABOUT:
                                       MessageBox(hwnd, "db definately 0wNz j00!!", "About", 0);
                                       break;
                       }
                       break;
               default:
                       return DefWindowProc(hwnd, Message, wParam, lParam);
       }
       return 0;
}


Righto! At the top you may have noticed that I set "WndClass.lpszMenuName" back to NULL. That is because we are
making the menu on the spot and don't need a resource file. First you might notice we added WM_CREATE to our
switch() statement. This is the message that is sent when our window is first created. We also declare 2 variables
of type HMENU. You see that we set hMenu to CreateMenu(). This will start our whole menu. Then we set hSubMenu
to CreatePopupMenu(). This will make a blank sub menu. Then we need to fill it. You see we call AppendMenu() to
add items to our menu. AppendMenu() takes the following parameters:

hMenu - This identifies the menu bar.
uFlags - This specifies flags to control the appearence and behaviour of our menu item.
ulDNNewItem - This specifies either the identifier of the menu item or if the uFlags parameter is set to
"MF_POPUP", the handle to the drop-down menu or submenu.
lpNewItem - This specifies the content of the new menu item.

After we have done that, we see SetMenu(). This is what actually displays the menu to us. SetMenu() takes the following
parameters:

hWnd - This identifies the window to which the menu is to be assigned to.
hMenu - This identifies the new menu. If it is set to NULL then the windows current menu is removed.