Writing Your First Windows Application with C++

Welcome to the first windows tutorial. In this tutorial I'll give you the basic information on how to code in windows and we'll go over a few important details first.

basic windows program has two important functions inside. The first one is the event handler(I'll talk about this one later on) and the second one is the main function(WinMain from now on). WinMain is similar to DOS' main function, in fact WinMain is called from the DOS main function but in windows we don't have access to the DOS main; everything is covered up by windows. Windows introduces us to messages. A message could be easily described as a pile of data that gets sent to the the event handler which then tells the window what to do. A message's name is prefixed with WM(stands for Windows Message as you might have guessed?). There's a whole lot of messages that a window can handle, however we'll only need a few of them. You can use these messages in many ways. For example, message WM_CREATE, can be used for initialization purposes, it gets sent to the window when it's created, and WM_PAINT is used when you want to draw something on the screen, and so on, you get the image. Most of the messages get sent to the window automatically, as an example when you move your mouse around you send a message to windows, and any other things such as that send messages to windows. You can also send a message to your window yourself, but you'll probably never need to.

Handles in windows. You will see a lot of these when programming a windows program. Handles are basically usual integers and they are used as identifiers to identify all kinds of stuff. Handles are usually prefixed with an H. For example HICON is a handle to the icon that your window will use, very simple. Other handles include HDLG - to a dialog box, HWND - to a window, HMENU - to a menu.

In your Windows program, the first thing you want to think about is the event handler(sometimes called message handler) function. This is the first function that you want to write in your code; it's your windows program starting point. As I said above, the event handler function takes care of all the messages that the window might send to it. After that you'll write your WinMain function; that's where you take care of the window class structure and finally create the window. The following text contain information on what should be done in a basic WinMain function.

You will need to know the structure of the window class because you have to fill it in before creating the window itself. There are two window class structures WNDCLASS, and WNDCLASSEX. They are basically the same, the only difference is that WNDCLASS is slowly becoming outdated, if it hadn't. Obviously you'll want to use the EX one and it looks like this:

typedef struct _WNDCLASSEX
{
    UINT cbSize;             // size of this structure in bytes 
    UINT style;              // style of the class 
    WNDPROC lpfnWndProc;     // pointer to the message handler f-n 
    int cbClsExtra;          // always 0 
    int cbWndExtra;          // always 0 
    HANDLE hInstance;        // handle to the main instance 
    HICON hIcon;             // which icon to show 
    HCURSOR hCursor;         // which cursor image to use 
    HBRUSH hbrBackground;    // the window background color 
    LPCTSTR lpszMenuName;    // you can attach a menu with this one 
    LPCTSTR lpszClassName;   // string, specifies the class name 
    HICON hIconSm;           // which small icon to use 
} WNDCLASSEX;

The truth is: you will need to fill the above structure with some info before creating any window. After you're done with that you will need to register this class. To register a class you make a call to RegisterClassEx(&ex_class), you have to pass the pointer of the structure to it. If you decided to use WNDCLASS instead of WNDCLASSEX for some reason, just use RegisterClass(&class) (without the Ex at the end).

After that, you're ready to create your window. In our case you create a window with CreateWindowEx that takes a chunk of parameters. I'll write about them in the next tutorial, but basically all you do is tell the window what it should look like visually, define it's name, and so on. Here's the function prototype:

HWND CreateWindowEx(DWORD dwExStyle,      // window extended style 
                   LPCTSTR lpClassName    // class name 
                   LPCTSTR lpWindowName,  // window name 
                   DWORD dwStyle,         // window style 
                   int x,                 // x and y position 
                   int y,
                   int nWidth,            // width 
                   int nHeight,           // height 
                   HWND hWndParent,       // handle to parent window 
                   HMENU hMenu,           // handle to menu 
                   HINSTANCE hInstance,   // handle to instance of window 
                   LPVOID lpParam);       // pointer to window creation data

After some event handler(this one is explained in the next tutorial) and WinMain hacking, you create the main event loop, which I'll show you how in the following tutorial. And that's it; by this time you should have your window up and running. If you're still confused, here's an overview of all the actions put together to create a window:

  • Write the event handler
  • Write WinMain( )
  • Fill in the class info
  • Register the class
  • Call CreateWindowEx( ) to create the window
  • Write the main event loop (covered in the next tutorial)

And here's the example of a sample application:

#include <windows.h>
#include <stdio.h>

// prototype of windows procedure function
LRESULT CALLBACK WindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam );

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
    // Design a window class
    WNDCLASS wndcls;
    wndcls.cbClsExtra = 0;
    wndcls.cbWndExtra = 0;
    wndcls.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    wndcls.hCursor = LoadCursor( NULL, IDC_ARROW );
    wndcls.hIcon = LoadIcon( NULL, IDI_APPLICATION );
    wndcls.hInstance = hInstance;
    wndcls.lpfnWndProc = WindowProc;
    wndcls.lpszClassName = "Win32Application";
    wndcls.lpszMenuName = NULL;
    wndcls.style = CS_HREDRAW | CS_VREDRAW;
    RegisterClass( &wndcls );

    // Create a window
    HWND hwnd = CreateWindow( "Win32Application", "Windows Application", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 640, 480, NULL, NULL, hInstance, NULL );

    // Show window and update it
    ShowWindow( hwnd, SW_SHOWNORMAL );
    UpdateWindow( hwnd );

    // Start event loop
    MSG msg;
    while ( GetMessage( &msg, NULL, 0, 0 ) )
    {
        TranslateMessage( &msg );
        DispatchMessage( &msg );
    }

    return msg.wParam;
}

// Windows Procedure Function
LRESULT CALLBACK WindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
    switch ( uMsg )
    {
        case WM_CREATE:
            // Initialize the window
            break;
        case WM_PAINT:
            // Paint the window's client area
            HDC hDC;
            PAINTSTRUCT ps;
            hDC = BeginPaint( hwnd, &ps );
            TextOut( hDC, 0, 0, "Welcome to the Win32 Programming world!", strlen("Welcome to the Win32 Programming world!") );
            EndPaint( hwnd, &ps );
            break;
        case WM_CLOSE:
            if ( MessageBox( hwnd, "Are you sure to quit?", "Message", MB_YESNO ) == IDYES )
                DestroyWindow( hwnd );
            break;
        case WM_DESTROY:
            // Clean up window-specific data objects.
            PostQuitMessage(0);
            break;
        default:
            // Process other messages.
            return DefWindowProc( hwnd, uMsg, wParam, lParam );
    }

    return 0;
}
Contact Us
  • SenseTime Research, Shenzhen Bay Eco-Technology Park
  • cshzxie [at] gmail [dot] com