#pragma once
#include "window.hpp"
///
/// Generic dialog class
///
class Dialog : public Window
{
public:
typedef INT_PTR( Dialog::*fnDlgProc )(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
typedef std::map mapMsgProc;
typedef std::map mapCtrlProc;
public:
Dialog( int dialogID )
: _dialogID( dialogID )
{
_messages[WM_INITDIALOG] = &Dialog::OnInit;
_messages[WM_COMMAND] = &Dialog::OnCommand;
_messages[WM_CLOSE] = &Dialog::OnClose;
}
///
/// Run dialog as modal window
///
/// Parent window.
/// TRUE on success, FALSE otherwise
virtual INT_PTR RunModal( HWND parent = NULL )
{
// Stupid std::function and std::bind don't support __stdcall
// Had to do this idiotic workaround
Win32Thunk dlgProc( &Dialog::DlgProc, this );
return DialogBoxW( NULL, MAKEINTRESOURCEW( _dialogID ), parent, dlgProc.GetThunk() );
}
///
/// Run dialog as modeless window
///
/// Parent window
/// Accelerator ID to use
/// TRUE on success, FALSE otherwise
virtual INT_PTR RunModeless( HWND parent = NULL, int accelID = 0 )
{
MSG msg = { 0 };
BOOL bRet = FALSE;
HACCEL hAccel = LoadAcceleratorsW( NULL, MAKEINTRESOURCEW( accelID ) );
_modeless = true;
Win32Thunk dlgProc( &Dialog::DlgProc, this );
_hwnd = CreateDialogW( NULL, MAKEINTRESOURCE( _dialogID ), parent, dlgProc.GetThunk() );
ShowWindow( _hwnd, SW_SHOW );
while (IsWindow( _hwnd ) && GetMessageW( &msg, NULL, 0, 0 ) > 0)
{
if (TranslateAccelerator( _hwnd, hAccel, &msg ))
continue;
if (!IsDialogMessage( _hwnd, &msg ))
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
}
return TRUE;
}
protected:
///
/// Close dialog properly
///
/// status
INT_PTR CloseDialog()
{
if (_modeless)
{
DestroyWindow( _hwnd );
_hwnd = NULL;
}
else
EndDialog( _hwnd, 0 );
return TRUE;
}
///
/// Dialog message proc
///
INT_PTR DlgProc( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam )
{
if (_messages.count( message ))
return (this->*_messages[message])(hDlg, message, wParam, lParam);
return FALSE;
}
///
/// WM_INITDIALOG handler
///
virtual INT_PTR OnInit( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam )
{
_hwnd = hDlg;
return TRUE;
}
///
/// WM_COMMAND handler
///
virtual INT_PTR OnCommand( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam )
{
if (_events.count( LOWORD( wParam ) ))
return (this->*_events[LOWORD( wParam )])(hDlg, message, wParam, lParam);
if (_events.count( HIWORD( wParam ) ))
return (this->*_events[HIWORD( wParam )])(hDlg, message, wParam, lParam);
return FALSE;
}
///
/// WM_CLOSE handler
///
virtual INT_PTR OnClose( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam )
{
return CloseDialog();
}
protected:
mapMsgProc _messages; // Message handlers
mapCtrlProc _events; // Event handlers
int _dialogID; // Dialog resource ID
bool _modeless = false; // Modeless dialog
};