WinMain
All Windows programs begin execution with a call to WinMain(). WinMain is the Windows equivalent of the C function main() and serves as the primary entry point for any Win32-based application. It contains the code required to initialise and register the application, create and display its main window, and enter the message retrieval and dispatch loop.
The prototype of this function is as follows:
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow);
The four parameters are:
hInstance – A handle to the current instance of the application. The operating system uses this value to identify the executable (EXE) when it is loaded into memory.
hPrevInstance – Used in 16-bit applications to provide a handle to the previous application instance. In a Win32-based application, this parameter is always NULL and has no meaning.
pCmdLine – A pointer to a null-terminated string used to pass command-line parameters to Windows programs.
nCmdShow – A flag that specifies whether the main application window is minimised, maximised, or shown normally.
The function returns an int value. Although the operating system does not utilise this value, it can convey a status code to another program.
Defining and Registering the Windows Class
The Windows class structure WNDCLASSEX contains information relating to the behaviour and appearance of a window. The syntax of the WNDCLASSEX structure is as follows:
typedef struct _WNDCLASSEX
{
UINT cbSize; // size of this structure
UINT style; // style flags
WNDPROC lpfnWndProc; // pointer to the window callback procedure
int cbClsExtra; // extra window-class info (usually 0)
int cbWndExtra; // extra window info (usually 0)
HANDLE hInstance; // instance of the application
HICON hIcon; // main application icon
HCURSOR hCursor; // cursor for the window
HBRUSH hbrBackground; // background brush
LPCTSTR lpszMenuName; // name of the menu, if any
LPCTSTR lpszClassName; // name of the registered class
HICON hIconSm; // handle to the small icon
} WNDCLASSEX;
style – Specifies the class style(s). Styles can be combined by using the bitwise OR (|) operator. The style can be any combination of the following: CS_BYTEALIGNCLIENT, CS_BYTEALIGNWINDOW, CS_CLASSDC, CS_DBLCLKS, CS_GLOBALCLASS, CS_HREDRAW, CS_NOCLOSE, CS_OWNDC, CS_PARENTDC, CS_SAVEBITS, CS_VREDRAW.
RegisterClassEx – Before a window can be displayed on the screen, its window class must be registered. RegisterClassEx() takes a pointer to a WNDCLASSEX structure. The registered class name is later used when calling CreateWindowEx().
In addition to the WNDCLASSEX structure, a window can be registered using the deprecated WNDCLASS structure and the associated RegisterClass function. The main difference between the two is that WNDCLASSEX includes a size member and an additional member that specifies a handle to a small icon for the window.
Windows also provides a standard set of predefined child window classes, which can be used to implement the functionality of common controls.
CreateWindow
A window is created by a call to the CreateWindowEx() or CreateWindow() function. CreateWindowEx differs from CreateWindow in that it uses an extended window style. The prototype for this function is:
HWND CreateWindowEx(
DWORD dwExStyle,
LPCTSTR lpClassName,
LPCTSTR lpWindowName,
DWORD dwStyle,
int x,
int y,
int nWidth,
int nHeight,
HWND hwndParent,
HMENU hmenu,
HANDLE hinst,
LPVOID lpvParam
);
The parameter description is as follows:
DWORD dwExStyle – Defines the extended window style.
LPCTSTR lpClassName – A pointer to a null-terminated string containing the predefined control class name. The class name can be registered using RegisterClass or RegisterClassEx, or it can be one of the predefined classes used to create child controls.
LPCTSTR lpWindowName – A pointer to a null-terminated string that specifies the window name.
DWORD dwStyle – Indicates the style of the window to be created. The style consists of values combined using the | operator.
int x – The horizontal position of the window.
int y – The vertical position of the window.
int nWidth – The width of the window.
int nHeight – The height of the window.
HWND hwndParent – A handle to the parent or owner window. A NULL value is used if there is no parent window.
HMENU hMenu – A handle to the menu, or a child-window identifier.
HINSTANCE hInst – A handle to the application instance.
LPVOID lpvParam – A pointer to additional data passed to the window during creation.
The function returns a handle to the new window or NULL if it fails.
Message Loop
A Windows program is event-driven. This means that program flow is determined by a continuous stream of notifications generated by the system or by users, such as a key press, mouse click, or application change. Each of these events is converted into a message. Windows creates a message queue for every running application. The application, in turn, contains a small message loop that retrieves these queued messages and dispatches them back to the window.
Windows, by way of a message handler, then identifies and calls the appropriate window procedure, WndProc(), passing the message as one of its parameters. Each time the application is ready to read a message, it must call the API function GetMessage(). The prototype for the GetMessage function is:
BOOL GetMessage(
LPMSG lpMsg, // pointer to MSG structure
HWND hWnd, // window whose messages are retrieved
UINT wMsgFilterMin, // first message
UINT wMsgFilterMax // last message
);
Inside the message loop, there are two functions:
TranslateMessage() – This Windows API call translates virtual-key messages into character messages.
DispatchMessage() – Dispatches the message to the appropriate window procedure.
What is a Message?
Messages are represented by the MSG structure and have the following format:
typedef struct tagMSG
{
HWND hwnd; // window whose procedure receives the message
UINT message; // message number
WPARAM wParam; // additional message-specific information
LPARAM lParam; // additional message-specific information
DWORD time; // time at which the message was posted
POINT pt; // cursor position when the message was posted
} MSG;
SendMessage Function
The SendMessage() API function allows specified messages to be sent to a window by directly calling the window procedure associated with that window. The prototype for the SendMessage function is:
LRESULT SendMessage(
HWND hWnd,
UINT Msg,
WPARAM wParam,
LPARAM lParam
);
Where:
HWND hWnd – A handle to the window whose window procedure will receive the message. If this parameter is set to HWND_BROADCAST, the message is sent to all top-level windows in the system, including those that are disabled or invisible.
UINT Msg – The message to be sent.
WPARAM wParam – Holds additional, message-specific information.
LPARAM lParam – Holds additional, message-specific information.
The return value specifies the result of the message processing and will depend on the message sent.
Windows Procedure
The Windows procedure WndProc() is used by a Windows application to process messages until the application is terminated. Each application window must have a WndProc declaration with the return type LRESULT and the calling convention CALLBACK. In Windows, a callback function is any function that is invoked by the operating system.
Although the system generates hundreds of different messages, an application typically needs to filter and process only a small fraction of them. In our simple window, WndProc calls DefWindowProc() to ensure default processing for messages that the application does not handle.
The prototype of WndProc is:
LRESULT CALLBACK WindowProc(
HWND hwnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam
);
The four parameters are:
HWND hwnd – A handle to the window to which the message was sent.
UINT uMsg – Specifies the message.
WPARAM wParam – Specifies additional message-specific information.
LPARAM lParam – Specifies additional message-specific information.