The member function that is used as a dialog procedure must be static. Also, the class that encapsulates a dialog must capture and save its "this" pointer. The following example also passes the HINSTANCE to the dialog class for convenience instead of using a global variable.
Dialog resource "IDD_DIALOG"
IDD_DIALOG DIALOGEX 0, 0, 309, 176
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Dialog"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
DEFPUSHBUTTON "OK",IDOK,198,155,50,14
PUSHBUTTON "Cancel",IDCANCEL,252,155,50,14
END
Example that runs the dialog -
#include <Windows.h>
#include "resource.h"
class MyDlgClass
{
public:
MyDlgClass(HINSTANCE hInstance) : m_hInst(hInstance)
{
}
~MyDlgClass() = default;
static INT_PTR CALLBACK s_DlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
INT_PTR DoModal(UINT id);
private:
INT_PTR DlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
HINSTANCE m_hInst;
HWND m_hWnd;
};
INT_PTR CALLBACK MyDlgClass::s_DlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
MyDlgClass* pDlg;
if (msg == WM_INITDIALOG)
{
pDlg = reinterpret_cast<MyDlgClass*>(lParam);
pDlg->m_hWnd = hWnd;
SetWindowLongPtr(hWnd, DWLP_USER, reinterpret_cast<LONG_PTR>(pDlg));
}
else
{
pDlg = reinterpret_cast<MyDlgClass*>(GetWindowLongPtr(hWnd, DWLP_USER));
}
return pDlg ? pDlg->DlgProc(hWnd, msg, wParam, lParam) : FALSE;
}
INT_PTR MyDlgClass::DlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_INITDIALOG:
return (INT_PTR)TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hWnd, LOWORD(wParam));
return (INT_PTR)TRUE;
}
break;
}
return (INT_PTR)FALSE;
}
INT_PTR MyDlgClass::DoModal(UINT id)
{
return DialogBoxParam(m_hInst, MAKEINTRESOURCE(id), NULL, s_DlgProc, reinterpret_cast<LPARAM>(this));
}
int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevious, _In_ LPWSTR szCommandline, _In_ int nShow)
{
MyDlgClass dlg(hInstance);
dlg.DoModal(IDD_DIALOG);
return 0;
}
The above example is running the dialog as the application window. You can also modify the above code to pass an owner window to the DoMOdal that can be used to call DialogBoxParam to set the owner.