The following members of WNDCLASSEX
/WNDCLASS
are mandatory to register class.
Note that name of WNDCLASS
structure is NOT WINDOWCLASS or WNDCLS.
- cbSize
- lpszClassName (Must be NON-empty string, otherwise, RegisterClass or RegisterClassEx will fail)
- lpfnWndProc
- hInstance
- hCursor (Generally not-necessary but mandatory on layered window)
WNDCLASSEX c;
memset(&c, 0, sizeof(WNDCLASSEX));
c.cbSize = sizeof(WNDCLASSEX);
c.lpszClassName = L"ClassName";
c.lpfnWndProc = reinterpret_cast<WNDPROC>(WndProc);
c.hInstance = i;
c.hCursor = LoadCursor(NULL, IDC_ARROW);
ATOM atom = RegisterClassEx(&c);
if (!atom) return -1;
HWND hwnd = CreateWindowEx(NULL, reinterpret_cast<LPCTSTR>(atom),
WindowTitle, WS_OVERLAPPED | WS_VISIBLE, 0, 0, WindowWidth, WindowHeight,
NULL, NULL, h, NULL);
A basic message loop should loop until GetMessage returns -1
or 0
MSG m; BOOL r;
while ((r = GetMessage(&m, NULL, 0, 0)) != 0 && r != -1) {
TranslateMessage(&m); DispatchMessage(&m);
}
// NOTE: Must call DispatchMessage no matter if TranslateMessage returns non-zero value.
// Otherwise, window will be hung up.
// WRONG short form: TranslateMessage(&m) && DispatchMessage(&m);
In addition, != 0
can be abbreviated, so the most shortest form may be the following:
while (r = GetMessage(&m, NULL, 0, 0) && r != -1) { ...
If you want to completely purge curly brace, combine TranslateMessage
and DispatchMessage
with bit operator. Do not use &&
and ||
. But, note that this form might be slightly lose performance by meaningless bit operation.
while (r = GetMessage(&m, NULL, 0, 0) && r != -1)
TranslateMessage(&m) & DispatchMessage(&m);
In addition, compiler may warn like: "warning C4552: '&': operator has no effect". To prevent this, cast its result to void
.
while (r = GetMessage(&m, NULL, 0, 0) && r != -1)
static_cast<void>(TranslateMessage(&m) & DispatchMessage(&m));
WNDCLASSEX class;
memset(&class, 0, sizeof(WNDCLASSEX));
class.style = CS_HREDRAW | CS_VREDRAW; // mandatory?
// ...
These "Windows Class Style" are always set on most examples, but they are NOT mandatory for some applications.
They are described as follows at https://msdn.microsoft.com/en-us/library/windows/desktop/ff729176(v=vs.85).aspx
Constant | Value | Description |
---|---|---|
CS_HREDRAW | 0x0002 | Redraws the entire window if a movement or size adjustment changes the width of the client area. |
CS_VREDRAW | 0x0001 | Redraws the entire window if a movement or size adjustment changes the height of the client area. |
According to the above, perhaps they invalidate entire window and send WM_ERASEBKGND and WM_PAINT. if your application has non-standard redraw mechanism (like frequent redraw animation), CS_HREDRAW and CS_VREDRAW may be overhead, so they should be unset.
int wWinMain(HINSTANCE i, HINSTANCE p, PWSTR c, int s) {
// ...
HWND hwnd = CreateWindowEx(...);
ShowWindow(hwnd, s);
By default, created window is invisible, so, until call ShowWindow
, window does not appear and app will works as background process, excepting CreateWindow with WS_VISIBLE
.
WS_VISIBLE
(0x10000000L) The window is initially visible. This style can be turned on and off by using the ShowWindow or SetWindowPos function. https://msdn.microsoft.com/en-us/library/windows/desktop/ms632680(v=vs.85).aspx
Application termination is not responsibility of DefWindowProc
,
so must manually handle WM_DESTROY
and call PostQuitMessage(0)
,
otherwise, app will keep running as background process so after window was destroyed.
case WM_DESTROY:
PostQuitMessage(0);
break; // return DefWindowProc
Until call ShowWindow
, window does not appear and app will works as background process.
int WinMain(HINSTANCE,HINSTANCE,LPSTR,int)
int wWinMain(HINSTANCE, HINSTANCE, PWSTR, int)
- Type of command line string is not
const
. (LPCSTR
LPSTR
,PCWSTR
PWSTR
) - The last argument
int
is used for 2nd argument ofShowWindow
(like SW_SHOW) WinMain
cannot be used by Unicode programs. TheGetCommandLineW
function can be used to obtain the command line as a Unicode string. Some programming frameworks might provide an alternative entry point that provides a Unicode command line. For example, the Microsoft Visual Studio C++ complier uses the namewWinMain
for the Unicode entry point. ( https://msdn.microsoft.com/en-us/library/windows/desktop/ms633559(v=vs.85).aspx)
LRESULT WndProc(HWND, UINT, WPARAM, LPARAM)
WPARAM
first- No special type defined for message identifier, use
UINT
. This value is came frommessage
member of MSG structure used by GetMessage, TranslateMessage, and DispatchMessage. - Returns
LRESULT
notHRESULT
(Memorise as LRESULT-LPARAM sandwitch) - Must bypass to
DefWindowProc(HWND, UINT, WPARAM, LPARAM)
if no operation by yours.- This name is NOT DefWndProc!