Reputation: 13
I'm trying to learn win32 API by following some tutorial.
(Though, I did very minor tweaking to create a borderless fixed window.)
However, my simplest window application is exiting with some random code.
I have no idea why it is not exiting with code '0'.
For extra information, I'm using Visual Studio 2012 Pro.
Source code's file extension is .c and the compiler setting is probably default.
I created the project as an empty win32 application (not console).
Please, some help will be appreciated.
Thank you.
#include <Windows.h>
#include <windowsx.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int __stdcall WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
INT nCmdShow) {
HWND hWnd;
WNDCLASSEX wcex;
MSG msg;
ZeroMemory(&wcex, sizeof(WNDCLASSEX));
wcex.cbSize = sizeof(WNDCLASSEX);
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"WindowClass1";
wcex.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
if (!RegisterClassEx(&wcex))
{
MessageBox(
NULL,
L"Failed to register window!",
L"ERROR",
MB_OK | MB_ICONEXCLAMATION);
return EXIT_FAILURE;
}
hWnd = CreateWindowEx(
0,
L"WindowClass1",
L"Application",
WS_POPUP,
0, 0,
GetSystemMetrics(SM_CXSCREEN),
GetSystemMetrics(SM_CYSCREEN),
NULL, NULL, hInstance, NULL);
if (hWnd == NULL)
{
MessageBox(
NULL,
L"Failed to create window!",
L"ERROR",
MB_OK | MB_ICONEXCLAMATION);
return EXIT_FAILURE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
while (GetMessage(&msg, hWnd, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
switch (Msg)
{
case WM_CLOSE:
DestroyWindow(hWnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, Msg, wParam, lParam);
}
return 0;
}
Upvotes: 1
Views: 999
Reputation: 10613
Beyond covering the entire screen with a blank window, necessitating the use of ALT-F4 to exit your app, things look good, except for one thing:
GetMessage, despite claiming to return 'BOOL' actually returns int: some positive value when successful, 0 when WM_QUIT is received and -1 in the case of an error. Microsoft's policy of returning "BOOL plus a lil' something something" from GetMessage (and other functions) is stupid and dangerous for this reason, and they should be flogged for it.
If GetMessage returns -1 then the contents of msg may or may not be valid; in other words wParam may be zero or it may be potato
. This could translate into the "random" exit codes you are seeing.
I suggest something like this:
int nRet;
do
{
nRet = GetMessage(&msg, hWnd, 0, 0);
if(nRet == -1)
return GetLastError();
if(nRet != 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
} while(nRet != 0);
return msg.wParam;
Upvotes: 2
Reputation: 613272
In your program, GetMessage
is in fact returning -1
which is an error condition. Your message loop terminates when GetMessage
returns a value <=0, and so it terminates when GetMessage
returns -1.
Now, because the final call to GetMessage
fails with an error, the value of msg.wParam
is not well-defined. You should not return it as an exit code. You should only return msg.wParam
as an exit code when the final call to GetMessage
returned 0. This is all made clear in the documentation.
You can see all this if you change your message loop to look like this:
while( (bRet = GetMessage( &msg, hWnd, 0, 0 )) != 0)
{
if (bRet == -1)
{
return GetLastError();
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return msg.wParam;
On my machine, the bRet == -1
route is selected and the error code is 1400. Which is ERROR_INVALID_WINDOW_HANDLE
. I'm not quite sure why your app is behaving in this way, but I'm content that I've answered the question you asked about exit codes!
Upvotes: 3