PROWAREtech

articles » current » windows » application-programming-interface » hello-world

Windows API: Hello World

A basic hello world Windows program example; written in C.

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);
}
Windows API Hello World!

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);
}

This site uses cookies. Cookies are simple text files stored on the user's computer. They are used for adding features and security to this site. Read the privacy policy.
CLOSE