zhuang@linux:~/reading/programming-windows/03-windows-and-messages/$ less

Programming Windows / chapter 03

Windows and Messages

$ grep tags 03-windows-and-messages.md

This post extracts some knowledge from Programming Windows Chapter 3 – Windows and Messages.

Windows Program Basic Framework

c
#include <windows.h>
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
    static TCHAR szAppName[] = TEXT ("HelloWin") ;
    HWND hwnd;
    MSG msg ;
    WNDCLASS wndclass ;
    wndclass.style = CS_HREDRAW | CS_VREDRAW ;
    wndclass.lpfnWndProc = WndProc ;
    wndclass.cbClsExtra = 0 ;
    wndclass.cbWndExtra = 0 ;
    wndclass.hInstance = hInstance ;
    wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
    wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
    wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
    wndclass.lpszMenuName = NULL ;
    wndclass.lpszClassName = szAppName ;
    if (!RegisterClass (&wndclass))
    {
        MessageBox (NULL, TEXT ("This program requires Windows NT!"),
                    szAppName, MB_ICONERROR) ;
        return 0 ;
    }
    hwnd = CreateWindow (szAppName, // window class name
                         TEXT ("The Hello Program"), // 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
    ShowWindow (hwnd, iCmdShow) ;
    UpdateWindow (hwnd) ;
    while (GetMessage (&msg, NULL, 0, 0))
    {
        TranslateMessage (&msg) ;
        DispatchMessage (&msg) ;
    }
    return msg.wParam ;
}
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    HDC hdc ;
    PAINTSTRUCT ps ;
    RECT rect ;
    switch (message)
    {
        case WM_CREATE:
            PlaySound (TEXT ("hellowin.wav"), NULL, SND_FILENAME | SND_ASYNC) ;
            return 0 ;
        case WM_PAINT:
            hdc = BeginPaint (hwnd, &ps) ;
            GetClientRect (hwnd, &rect) ;
            DrawText (hdc, TEXT ("Hello, Windows 98!"), -1, &rect,
                      DT_SINGLELINE | DT_CENTER | DT_VCENTER) ;
            EndPaint (hwnd, &ps) ;
            return 0 ;
        case WM_DESTROY:
            PostQuitMessage (0) ;
            return 0 ;
    }
    return DefWindowProc (hwnd, message, wParam, lParam) ;
}

CreateWindow declarition as follows:

c
HWND CreateWindowW(
  [in, optional] LPCWSTR   lpClassName,
  [in, optional] LPCWSTR   lpWindowName,
  [in]           DWORD     dwStyle,
  [in]           int       x,
  [in]           int       y,
  [in]           int       nWidth,
  [in]           int       nHeight,
  [in, optional] HWND      hWndParent,
  [in, optional] HMENU     hMenu,
  [in, optional] HINSTANCE hInstance,
  [in, optional] LPVOID    lpParam
);

Hungarian Notation

Many Windows programmers use Hungarian notation as a variable naming convention. This is in honor of the legendary Microsoft programmer Charles Simonyi. This notation is very simple: variable names begin with a lowercase letter indicating the data type of the variable.

When naming structure variables, you can use the lowercase form of the structure name (or an abbreviation of the structure name) as a prefix or the entire variable name. For example, in the WinMain function of HELLOWIN, the variable msg is a structure of type MSG, and wndclass is a structure of type WNDCLASS. In the WndProc function, ps is a structure of type PAINTSTRUCT, and rect is a structure of type RECT.

Common variables name prefix as follows:

prefixdata type
cchar or WCHAR or TCHAR
byBYTE(unsigned char)
nshort
iint
x, yint used as x-coordinate or y-coordinate
cx, cyint used as x or y length; c stands for “count”
B or fBOOL(int); f stands for “flag”
wWORD(unsigned short)
lLONG(long)
dwDWORD(unsigned long)
fnfunction
sstring
szstring terminated by 0 character
hhandle
ppointer

Queued Messages and Non-queued Messages

Messages can be either “queued messages” or “unqueued messages.” Queued messages are those placed in a program’s message queue by Windows. In the program’s message loop, messages are retrieved and then delivered to the window procedure. Unqueued messages are generated by direct calls to the window procedure by Windows. Generally, queued messages are “posted” to the message queue, while unqueued messages are “sent” to the window procedure. In either case, the window procedure retrieves all messages for the window—whether queued or unqueued. Therefore, the window procedure is essentially the window’s “message center.”

Queued messages are primarily generated by user input, mainly in the form of keystroke messages (such as WM_KEYDOWN and WM_KEYUP messages), character messages generated by keystrokes WM_CHAR, mouse movement WM MOUSEMOVE, mouse clicks WM_LBUTTONDOWN, etc. In addition, queued messages include timer messages WM_TIMER, repaint messages WM_PAINT, and exit messages WM_QUIT.

Non-queued messages include all other messages besides those in the queue. Non-queued messages are typically caused by calls to specific Windows functions. For example, when WinMain calls the CreateWindow function, Windows creates the window and sends a WM_CREATE message to the window procedure during creation. When WinMain calls the ShowWindow function, Windows sends WM_SIZE and WM_SHOWWINDOW messages to the window procedure. Next, WinMain calls UpdateWindow, which prompts Windows to send a WM_PAINT message to the window procedure.

zhuang@linux:~/reading/programming-windows/03-windows-and-messages/$ comments