Modeless Dialog
A Win32 example of running a dialog non-modally with CreateDialog plus a message loop, instead of the blocking DialogBox call.
Most sample code shows DialogBox, which blocks until the user closes the dialog. This project shows the other half of the API: CreateDialog returns immediately and hands you the dialog's HWND, so your main window stays alive and responsive while the dialog sits on top - necessary when the dialog must coexist with other windows, timers, or background work. The key piece is the message loop in WinMain: pump messages with GetMessage, route them through IsDialogMessage (which gives the dialog keyboard navigation like Tab), and only translate/dispatch what the dialog did not handle. The dialog procedure itself is the standard shape - WM_INITDIALOG to wire up controls, WM_COMMAND for buttons, EndDialog to close.
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevious, LPSTR CmdLine, int CmdShow)
{
AppInstance = hInstance;
HANDLE xMutex = NULL;
if(!InitializeApp())
{
return 1;
}
if( (xMutex = OpenMutex(SYNCHRONIZE, FALSE, gsTitleCaption)) )
{
MessageBox (NULL, "Only one instance can run at a time!" , gsTitleCaption, MB_ICONASTERISK + MB_SYSTEMMODAL);
ReleaseMutex(xMutex);
CloseHandle(xMutex);
return 0;
}
else xMutex = CreateMutex(0, 0, gsTitleCaption);
HWND MyDialog_hWnd = CreateDialog(AppInstance, MAKEINTRESOURCE(IDD_MAIN), 0, MainDialog);
BOOL bRet;
MSG msg;
while ( (bRet = GetMessage(&msg, MyDialog_hWnd, 0, 0)) != 0 )
{
if(bRet == -1)
{
MessageBox(NULL, "GetMessage Error." , gsTitleCaption, MB_SYSTEMMODAL);
return 0;
// handle the error and possibly exit
}
else if(!IsWindow(MyDialog_hWnd) || !IsDialogMessage(MyDialog_hWnd, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
if(!UninitializeApp())
{
return 1;
}
ReleaseMutex(xMutex);
CloseHandle(xMutex);
return 0;
}
The dialog procedure handles the usual messages; note that unlike a modal dialog it must keep returning control to the pump, and closing it with EndDialog makes IsWindow(MyDialog_hWnd) go false so the loop exits cleanly:
BOOL CALLBACK MainDialog(HWND xHandle, UINT xMessage, WPARAM wParam, LPARAM lParam)
{
static HWND TextEdit_hWnd = NULL;
static HWND TextStatic_hWnd = NULL;
static HMENU SystemMenu = NULL;
if(xMessage == WM_INITDIALOG)
{
MainDialog_hWnd = xHandle;
SystemMenu = GetSystemMenu(xHandle, FALSE);
AppendMenu(SystemMenu, MF_SEPARATOR, 0, 0);
AppendMenu(SystemMenu, MF_STRING, 1000, "About");
SendMessage(xHandle, (UINT)WM_SETTEXT, (WPARAM)0, (LPARAM)gsTitleCaption);
SendMessage(xHandle, WM_SETICON, TRUE, (LPARAM) LoadIcon(AppInstance, MAKEINTRESOURCE(IDI_MAIN)) );
TextEdit_hWnd = GetDlgItem(xHandle, IDC_TEXTBOX);
TextStatic_hWnd = GetDlgItem(xHandle, IDC_STATICTEXT);
Set_Text(TextEdit_hWnd, "Text here");
Set_Text(TextStatic_hWnd, "will appear here.");
CenterWindow(xHandle);
return TRUE; // Return TRUE to set the keyboard focus, Otherwise return FALSE
}
if(xMessage == WM_COMMAND)
{
if(wParam == IDC_OK) //- Ok (Dialog Command)
{
char TempText[256];
Get_TextEx(TextEdit_hWnd, TempText, 255);
Set_Text(TextStatic_hWnd, TempText);
return TRUE;
}
if(wParam == IDC_CANCEL) //- Cancel (Dialog Command)
{
EndDialog(xHandle, 0);
return TRUE;
}
return FALSE;
}
if(xMessage == WM_PAINT)
{
HDC ThisHDC;
PAINTSTRUCT ThisPS;
ThisHDC = BeginPaint(xHandle, &ThisPS);
// Any painting should be done here
EndPaint(xHandle, &ThisPS);
return TRUE;
}
if(xMessage == WM_CLOSE)
{
EndDialog(xHandle,0);
return TRUE;
}
return FALSE;
}
The single-instance mutex check around the whole thing is the same pattern as the modal examples - open first, create only if nobody else holds it.