PROWAREtech
Windows API: Hello World
See related: Windows API Example in C++
This code listing uses many symbols defined in windows.h
. Most of these symbols map to the long
or int
data types so don't be too confused by them. HINSTANCE
is just a void *
. The important parts of this code are the RegisterClassEx()
and the message loop at GetMessage()
which basically sits in a loop waiting for input from the user be it mouse movement, mouse clicking, key pressing or other event. Once an event occurs it is dispatched to the Window Procedure WndProc()
which the system knows to use because it was passed as a parameter in RegisterClassEx()
. Because of this, Windows API programming is very C friendly, not C++ friendly. There is no way to assign a class function to the lpfnWndProc
member of the WNDCLASSEX
struct (due to the this
pointer being passed on the stack as a hidden function parameter) unless it is static
(because the this
pointer is not applicable), but there is a way to assign a pointer to an object to each window — see C++ example.
// *******************************************************************
// * *
// * Example C Windows App *
// * *
// *******************************************************************
#ifndef UNICODE
#define UNICODE
#endif
#include <windows.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
HWND hwnd;
MSG msg;
WNDCLASSEX wcex;
wcex.cbSize = sizeof(wcex);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = L"HelloWin";
wcex.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
RegisterClassEx(&wcex);
hwnd = CreateWindow(wcex.lpszClassName, // window class name
L"Hello World", // window caption
WS_OVERLAPPEDWINDOW, // window style
CW_USEDEFAULT, // initial x position
CW_USEDEFAULT, // initial y position
CW_USEDEFAULT, // initial x size
CW_USEDEFAULT, // initial y size
NULL, // parent window handle
NULL, // window menu handle
hInstance, // program instance handle
NULL); // creation parameters
if (hwnd)
{
ShowWindow(hwnd, iCmdShow);
UpdateWindow(hwnd);
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return 0;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
switch (iMsg)
{
case WM_CREATE:
return 0; // return -1 to cancel the creation of the window
case WM_PAINT:
{
HDC hdc;
PAINTSTRUCT ps;
RECT rect;
hdc = BeginPaint(hwnd, &ps);
GetClientRect(hwnd, &rect);
SetBkMode(hdc, TRANSPARENT);
DrawText(hdc, L"Hello World!", -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
EndPaint(hwnd, &ps);
}
return 0;
case WM_CLOSE:
if (MessageBox(hwnd, L"Sure?", L"Confirm Close", MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2) == IDYES)
DestroyWindow(hwnd);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, iMsg, wParam, lParam);
}
Alternatively, the WM_PAINT
could look like this. This will paint three difference colors for the text and change the font being used to Arial 24pt.
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
HGDIOBJ hOrigFont = SelectObject(hdc,
CreateFontA(24, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE,
DEFAULT_CHARSET, OUT_OUTLINE_PRECIS, CLIP_DEFAULT_PRECIS,
CLEARTYPE_QUALITY, VARIABLE_PITCH, "Arial")
);
RECT rect;
GetClientRect(hWnd, &rect);
rect.top += 10;
DRAWTEXTPARAMS dtp;
dtp.cbSize = sizeof(dtp);
dtp.iLeftMargin = 15; // specify left margin of 15px
dtp.iRightMargin = 0;
dtp.iTabLength = 4; // specify tab size
dtp.uiLengthDrawn = 0; // ignored when DT_NOCLIP is specified
SetTextColor(hdc, 0x00FF0000); // 0x00BBGGRR (BB == BLUE, GG = GREEN, RR = RED)
DrawTextExA(hdc, (LPSTR)"Hello, World!", -1, &rect, DT_NOCLIP, &dtp);
SetTextColor(hdc, 0x0000AA00);
DrawTextExA(hdc, (LPSTR)"\r\nYes!", -1, &rect, DT_NOCLIP, &dtp);
SetTextColor(hdc, 0x000000FF);
DrawTextExA(hdc, (LPSTR)"\r\n\r\nNo!", -1, &rect, DT_NOCLIP, &dtp);
DeleteObject(SelectObject(hdc, hOrigFont));
EndPaint(hWnd, &ps);
}