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_PTR
instead ofBOOL
; - The
WndProc
function returns 0, instead of TRUE (which is 1) as is in the tutorial; - The
switch
statement for themsg
variable 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;
}