Here is a super ugly testcode that works, you can cheat from it. Compile it as an ANSI (not UNICODE) console program.
You can debug both this and your program to compare what is different. You can also copy paste parts.
DialogTest.cpp:
#include "stdafx.h"
#include "resource.h"
#include <windows.h>
const UINT WM_THREAD_OK = WM_USER + 10;
const int SHOW_DLG_BUTTON_ID = 2;
const int SIMULATE_THREAD_MESSAGE_BUTTON_ID = 3;
HINSTANCE g_hInstance = (HINSTANCE)GetModuleHandle(NULL);
HWND g_hThreadFinishSimulateWnd = NULL;
HWND g_hMainWnd = NULL;
HWND g_hDialog = NULL;
HWND g_hShowDlgButton = NULL;
HWND g_hSimulateThreadFinishButton = NULL;
bool g_ThreadRunning = false;
bool g_CloseDialogRequest = false;
bool g_CloseMainWndRequest = false;
void StartThread()
{
g_ThreadRunning = true;
SetWindowText(GetDlgItem(g_hDialog, IDC_STATIC_THREAD_STATE), "yes");
EnableWindow(GetDlgItem(g_hDialog, IDC_START_THREAD), FALSE);
EnableWindow(g_hSimulateThreadFinishButton, TRUE);
}
void OnThreadFinished()
{
g_ThreadRunning = false;
if (!g_CloseDialogRequest)
{
SetWindowText(GetDlgItem(g_hDialog, IDC_STATIC_THREAD_STATE), "no");
EnableWindow(GetDlgItem(g_hDialog, IDC_START_THREAD), TRUE);
}
EnableWindow(g_hSimulateThreadFinishButton, FALSE);
}
void RequestThreadExit()
{
}
void DisableAllChildControls(HWND wnd)
{
HWND child = GetWindow(wnd, GW_CHILD);
while (child)
{
EnableWindow(child, FALSE);
child = GetWindow(child, GW_HWNDNEXT);
}
}
void RequestThreadExitAndDialogClose()
{
if (g_CloseDialogRequest)
return;
RequestThreadExit();
g_CloseDialogRequest = true;
SetWindowText(g_hDialog, "Dialog close requested...");
#if 0
EnableWindow(g_hDialog, FALSE);
#elif 0
ShowWindow(g_hDialog, SW_HIDE);
#elif 1
DisableAllChildControls(g_hDialog);
#endif
}
void MyLog(const char* msg)
{
printf("- %-50s thread_running:%d dlg_close_req:%d main_wnd_close_req:%d\n",
msg,
g_ThreadRunning ? 1 : 0,
g_CloseDialogRequest ? 1 : 0,
g_CloseMainWndRequest ? 1 : 0);
}
INT_PTR CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_INITDIALOG:
MyLog("Dialog: WM_INITDIALOG");
g_CloseDialogRequest = false;
EnableWindow(g_hShowDlgButton, FALSE);
return TRUE;
case WM_CLOSE:
MyLog("Dialog: WM_CLOSE");
if (g_ThreadRunning)
{
RequestThreadExitAndDialogClose();
}
else
{
if (!g_CloseMainWndRequest)
EnableWindow(g_hShowDlgButton, TRUE);
EndDialog(hwndDlg, 0);
g_hDialog = NULL;
}
return TRUE;
case WM_THREAD_OK:
MyLog("Dialog: WM_THREAD_OK");
OnThreadFinished();
if (g_CloseDialogRequest)
PostMessage(hwndDlg, WM_CLOSE, 0, 0);
if (g_CloseMainWndRequest)
PostMessage(g_hMainWnd, WM_CLOSE, 0, 0);
return TRUE;
case WM_COMMAND:
{
int ctrl_id = LOWORD(wParam);
if (ctrl_id == IDC_START_THREAD)
{
MyLog("Dialog: WM_COMMAND/ID_START_THREAD");
if (!g_ThreadRunning)
StartThread();
return TRUE;
}
else if (ctrl_id == IDCANCEL)
{
MyLog("Dialog: WM_COMMAND/IDCANCEL");
PostMessage(hwndDlg, WM_CLOSE, 0, 0);
return TRUE;
}
}
break;
}
return FALSE;
}
LRESULT CALLBACK MainWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_CREATE:
MyLog("MainWnd: WM_CREATE");
g_hShowDlgButton = CreateWindowEx(0, "Button", "Create/show my test dialog", WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,
0, 0, 200, 35, hWnd, (HMENU)SHOW_DLG_BUTTON_ID, g_hInstance, NULL);
break;
case WM_CLOSE:
MyLog("MainWnd: WM_CLOSE");
if (g_ThreadRunning)
{
#if 1
if (!g_CloseMainWndRequest)
{
g_CloseMainWndRequest = true;
SetWindowText(hWnd, "Main window close requested...");
DisableAllChildControls(hWnd);
RequestThreadExitAndDialogClose();
}
#else
MessageBox(hWnd, "Sorry, can't exit while the thread is running!", "INFO", MB_OK|MB_ICONHAND);
#endif
return 0;
}
if (g_hDialog)
EndDialog(g_hDialog, 0);
break;
case WM_DESTROY:
MyLog("MainWnd: WM_DESTROY");
PostQuitMessage(0);
break;
case WM_COMMAND:
{
int ctrl_id = LOWORD(wParam);
if (ctrl_id == SHOW_DLG_BUTTON_ID)
{
MyLog("MainWnd: WM_COMMAND/SHOW_DLG_BUTTON_ID");
if (!g_hDialog)
{
g_hDialog = CreateDialog(g_hInstance, MAKEINTRESOURCE(IDD_DIALOG1), hWnd, DialogProc);
ShowWindow(g_hDialog, SW_SHOW);
}
return 0;
}
}
break;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
bool CreateMainWnd()
{
static const char CLASS_NAME[] = "MainWndClass";
WNDCLASS wc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hInstance = g_hInstance;
wc.lpfnWndProc = &MainWndProc;
wc.lpszClassName = CLASS_NAME;
wc.lpszMenuName = NULL;
wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
if (!RegisterClass(&wc))
return false;
g_hMainWnd = CreateWindowEx(
0,
CLASS_NAME,
"Main Window",
WS_OVERLAPPED | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,
0, 150, 250, 100,
NULL,
NULL,
g_hInstance,
NULL
);
return true;
}
LRESULT CALLBACK SimulateThreadFinishWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_CREATE:
g_hSimulateThreadFinishButton = CreateWindowEx(0, "Button", "Simulate thread finish", WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON|WS_DISABLED,
0, 0, 200, 35, hWnd, (HMENU)SIMULATE_THREAD_MESSAGE_BUTTON_ID, g_hInstance, NULL);
break;
case WM_CLOSE:
PostMessage(g_hMainWnd, WM_CLOSE, 0, 0);
return 0;
case WM_COMMAND:
{
int ctrl_id = LOWORD(wParam);
if (ctrl_id == SIMULATE_THREAD_MESSAGE_BUTTON_ID)
{
MyLog("MainWnd: WM_COMMAND/SIMULATE_THREAD_MESSAGE_BUTTON_ID");
if (g_hDialog && g_ThreadRunning)
PostMessage(g_hDialog, WM_THREAD_OK, 0, 0);
}
}
break;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
bool CreateSimulateThreadFinishWindow()
{
static const char CLASS_NAME[] = "SimulateWndClass";
WNDCLASS wc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hInstance = g_hInstance;
wc.lpfnWndProc = &SimulateThreadFinishWndProc;
wc.lpszClassName = CLASS_NAME;
wc.lpszMenuName = NULL;
wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
if (!RegisterClass(&wc))
return false;
g_hThreadFinishSimulateWnd = CreateWindowEx(
0,
CLASS_NAME,
"Thread finish simulate window",
WS_OVERLAPPED | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,
0, 0, 250, 100,
NULL,
NULL,
g_hInstance,
NULL
);
return true;
}
int main()
{
if (!CreateMainWnd() || !CreateSimulateThreadFinishWindow())
return -1;
ShowWindow(g_hThreadFinishSimulateWnd, SW_SHOW);
UpdateWindow(g_hThreadFinishSimulateWnd);
ShowWindow(g_hMainWnd, SW_SHOW);
UpdateWindow(g_hMainWnd);
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
if (!g_hDialog || !IsDialogMessage(g_hDialog, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
DestroyWindow(g_hThreadFinishSimulateWnd);
printf("Program finished, press ENTER to exit.\n");
getchar();
return (int)msg.wParam;
}
resource.h:
#define IDD_DIALOG1 101
#define IDC_START_THREAD 1001
#define IDC_STATIC_THREAD_STATE 1002
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 102
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1003
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
Test.rc:
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// Hungarian (Hungary) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_HUN)
LANGUAGE LANG_HUNGARIAN, SUBLANG_DEFAULT
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
IDD_DIALOG1 DIALOGEX 0, 0, 191, 48
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Dialog"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
PUSHBUTTON "Start thread",IDC_START_THREAD,7,27,50,14
PUSHBUTTON "IDCANCEL: simulating ESC",IDCANCEL,63,27,119,14
LTEXT "Thread running:",IDC_STATIC,7,7,52,8
LTEXT "no",IDC_STATIC_THREAD_STATE,63,7,76,8
END
/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
IDD_DIALOG1, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 182
TOPMARGIN, 7
BOTTOMMARGIN, 41
END
END
#endif // APSTUDIO_INVOKED
#endif // Hungarian (Hungary) resources
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
// English (United States) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""afxres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
#endif // English (United States) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED