by Wojciech Sura

How to create a pure WinAPI window?

Have you ever wondered, how does the mostly low-level Windows application look? I mean, one, which has at least one window. Well, here you go:

[cpp]#include <Windows.h>

LRESULT CALLBACK WindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_DESTROY:
{
PostQuitMessage(0);

return 0;
break;
}
default:
{
return DefWindowProc(hwnd, message, wParam, lParam);
}
}
}

int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
// Registering window class
WNDCLASSEX winClass;
winClass.cbClsExtra = 0;
winClass.cbSize = sizeof(WNDCLASSEX);
winClass.cbWndExtra = 0;
winClass.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
winClass.hCursor = LoadCursor(NULL, IDC_ARROW);
winClass.hIcon = LoadIcon(NULL, IDI_WINLOGO);
winClass.hIconSm = LoadIcon(NULL, IDI_WINLOGO);
winClass.hInstance = hInstance;
winClass.lpfnWndProc = WindowProc;
winClass.lpszClassName = L"MainWindowClass";
winClass.lpszMenuName = NULL;
winClass.style = CS_HREDRAW | CS_VREDRAW;

if (!RegisterClassEx(&winClass))
return -1;

// Creating a window
HWND mainWinHWND = CreateWindowEx(WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE,
L"MainWindowClass",
L"WinAPI window",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
640,
480,
NULL,
NULL,
hInstance,
NULL);

if (!mainWinHWND)
return -1;

ShowWindow(mainWinHWND, SW_SHOW);

// Processing messages
MSG message;
BOOL getMsgResult;

while ((getMsgResult = GetMessage(&message, NULL, 0, 0)) != 0 && getMsgResult != -1)
{
TranslateMessage(&message);
DispatchMessage(&message);
}

return message.lParam;
}[/cpp]

Now a few words of comments:

  1. Windows applications are driven by so-called messages: most of events are reported to an application in the form of a message. System maintains a message queue for each process and allows application to query for incoming messages. Message processing, however, has to be implemented by the programmer manually (the last while loop is usually called “main message loop”).
  2. A message is a simple structure consisting of the following fields:
    • A message code (int), for example mouse left button down is 0x201 = 513 (dec)
    • Two parameters: WParam and LParam (ints). If there’s a need to pass more data, LParam usually represents a pointer to bigger structure.
    • Target window handle (HWND, pointer)
  3. Applications receive a lot of messages, but fortunately Windows API provides a function, which processes them in a default way, if programmer didn’t planned anything special for them.
  4. Before window may be created, programmer has to define special window class, which describes window’s properties.
  5. Now an interesting fact. A “window” in terms of Windows API is not only awindow. Actually, every single UI object: button, checkbox, listbox etc., is a window and has its own window class. Windows API provides a set of default classes for most common controls you might want to use. I guess, that this is the real reason for the operating system to be named “Windows”

Before you urge to write a new application in pure WinAPI, here’s the equivalent of mentioned source code in C#/Windows Forms:

[csharp]Form form = new Form();
form.Show();[/csharp]