[C++] GUI Coding with the Windows API

DON'T post new tutorials here! Please use the "Pending Submissions" board so the staff can review them first.
Post Reply
User avatar
Gogeta70
^_^
^_^
Posts: 3275
Joined: 25 Jun 2005, 16:00
18

[C++] GUI Coding with the Windows API

Post by Gogeta70 »

Hey everyone. The purpose of this tutorial is to help people understand that the windows api isn't that hard, or scary - it's actually quite easy! And what better way than showing the most basic of all windows applications: creating a window. So in this tutorial, i'm going to show you the code for creating a window using only the windows api in C++. I will try to describe everything in detail and maybe give a few pointers too. Well, with that said, let's get started.



To start, i'm going to show you the entire code for creating a window. It IS about 70 lines of code, but i'll explain everything so that you understand it all at the end ^_^

Code: Select all

#include <windows.h>

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

char szClassName[ ] = "WinTut";

int WINAPI WinMain (HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nCmdShow)
{
    HWND hwnd;
    MSG messages;
    WNDCLASSEX wincl;

    wincl.hInstance = hThisInstance;
    wincl.lpszClassName = szClassName;
    wincl.lpfnWndProc = WindowProcedure;
    wincl.style = CS_DBLCLKS;
    wincl.cbSize = sizeof (WNDCLASSEX);
    wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
    wincl.lpszMenuName = NULL;
    wincl.cbClsExtra = 0;
    wincl.cbWndExtra = 0;

    wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;

    if (!RegisterClassEx (&wincl))
        return 0;

    hwnd = CreateWindowEx (
           0,
           szClassName,
           "Code::Blocks Template Windows App",
           WS_OVERLAPPEDWINDOW,
           CW_USEDEFAULT,
           CW_USEDEFAULT,
           544,
           375,
           HWND_DESKTOP,
           NULL,
           hThisInstance,
           NULL
           );

    ShowWindow (hwnd, nCmdShow);

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

    return messages.wParam;
}

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

    return 0;
}
The code above can be divided into three main parts.

First, the program entry point - winmain. In this function, you declare the window class. The window class sets various properties for the main window of your program. Such as pointer, icon, menu resource, etc. It's pretty much the same thing as a standard C++ structure:

Code: Select all

struct _WNDCLASSEX
{
  type property1;
  type property2;
  //etc
} WNDCLASSEX, *PWNDCLASSEX;
I often use MSDN as a reference when coding using the windows api - it has information on the entire api: functions, classes, notifications, messages, etc.
MSDN for WNDCLASSEX: Link

After that, you register the window class (WNDCLASSEX) that you defined the properties for. This simply tells windows "hey, i'm creating a window and this is the property set for the window". Unless the class name is already taken (set in szClassName), the function should return ok.

After registering the window, you actually create the window. The function does take a lot of arguments, but they're just for setting window styles, width and height, x and y position, parent window (HWND_DESKTOP in this case), etc. Notice that the name of the class we registered is used as an argument to this function - that's what that was all for ;)

After creating the window, you have to call ShowWindow() for the window to appear on the screen. This can also be set in the window style (in the createwindowex function call) to automatically show the window once it is created.

Ok, so i've explained a lot. Let's review:

In the WinMain() function, we do 3 main things:
Create the window class, which specifies certain properties about our application.
Register the window class to let windows know we're creating a window.
And then creating and showing the window.

Quite a bit of code, but 3 very simple tasks ^_^

Ok, the last part of the winmain() function is a while loop - the program remains in this loop indefinitely. The 2 functions in the loop do 2 things:
TranslateMessage() converts virtual-key messages into character messages. Basically, it handles keypresses (somewhat).

The DispatchMessage() function simply takes care of sending messages to the window procedure.

Now, you may be asking "What are these 'messages'?" Well, i'm about to tell you ^_^

Our next function, which was defined as

Code: Select all

LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
Is our callback function. Basically, we set this function when registering the window class as the function that handles all forms of input to our window. Input comes in the form of messages. In our code, we have only a WM_DESTROY message, which is sent when a user clicks the X button in the top right corner of the window. There are other messages, like WM_LBUTTONDOWN, and WM_LBUTTONUP, which are used for left mouse button down, and left mouse button up events.

To process these messages, we simply add a case for them:

Code: Select all

switch (message)
    {
        
       case WM_LBUTTONDOWN:
       {
              MessageBox(hwnd, "You clicked the left mouse button!", "Message", MB_OK);
       }
       break;
        case WM_DESTROY:
            PostQuitMessage (0);
            break;
        default:
            return DefWindowProc (hwnd, message, wParam, lParam);
    }
Now, our program will show a messagebox saying "You clicked the left mouse button!" any time a user clicks the left mouse button inside of the window. Pretty easy, right?
MSDN reference for window functions, messages, notifications, etc: Link

Ok, so now if you compile all the code above, you should have a working windows program that gives a nice messagebox upon clicking ^_^

Conclusion

Even though i only covered the basics of creating a windows program here, the foundation of windows programming is the same. One interesting thing is that buttons, edit boxes, and every control in a windows program is essentially a window. Hell, you even create a button using CreateWindowEx(). These are special windows with the main window specified as a the parent window.



Well anyway, that's the end of the tutorial. Feel free to ask any questions if something was unclear. I'll update the tutorial if anything was hard to understand or not covered enough.
¯\_(ツ)_/¯ It works on my machine...

Post Reply