I was reading a very old tutorial on how to create a dialog-based GUI application in Visual C++ (source - in portuguese). Based on my weak knowledge on WinAPI programming I decided to modify the proposed code mainly to achieve two things:
1) Consistency with Unicode programming standard (using wWinMain and MessageBoxW instead of WinMain and MessageBox/MessageBoxA for instance). Such "standard" seems to be enforced all around. Example: this question (comments)
2) Consistency with the model presented by Visual Studio when creating a non-empty Win32 Project. I did that and noticed that:
- The callback function for the "About" dialog box is of type
INT_PTRinstead ofBOOL; - The
WndProcfunction returns 0, instead of TRUE (which is 1) as is in the tutorial; - The
switchstatement for themsgvariable defaults to return DefWindowProc() instead of FALSE; - WM_CLOSE handling is not specified (I guess dialogs have default handling for some events).
_
As a result, there's a weird behavior in which the MessageBox entitled Confirm is out-of-focus - i.e I can't click the OK and Cancel buttons.
Question: Am I correct in my assumption that the template code generated by Visual Studio is more correct than the code in the tutorial, which just doesn't seem trustable to me? If yes, did I forget anything? And what's wrong with my code, why can't I click the Messagebox buttons?
My final code follows:
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include "resource.h"
INT_PTR CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_INITDIALOG:
return (INT_PTR)TRUE;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDOK:
if (MessageBoxW(hWnd, L"Close?", L"Confirm", MB_OKCANCEL) == IDOK)
DestroyWindow(hWnd);
break;
// more code to place here
}
break;
default:
return DefWindowProc(hWnd, msg, wParam, lParam);
}
return 0;
}
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow)
{
int ret = DialogBoxW(hInstance, MAKEINTRESOURCEW(IDD_DIALOG1), NULL, WndProc);
return 0;
}
For completeness, below is the code based on the tutorial, which actually works fine:
BOOL CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_INITDIALOG:
return TRUE;
case WM_CLOSE:
DestroyWindow(hWnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDOK:
if (MessageBoxW(hWnd, L"Close?", L"Confirm", MB_OKCANCEL) == IDOK)
DestroyWindow(hWnd);
break;
}
break;
default:
return FALSE;
}
return TRUE;
}