Exit MFC app from a modal dialog - c++

I am on a modal dialog and on the close of the modal dialog i want to exit application.
ASSERT(AfxGetApp()->m_pMainWnd != NULL);
PostMessage(WM_CLOSE, 0, 0);
But getting below exception form a member method for a private member variable of the modal:
Exception thrown: read access violation.
Is there any way to close application from ModalDialog safely?

In order to show the dialog, you would have called DoModal() from your application.
You can just exit the application after the call to DoModal();
dlg.DoModal();
//write code to exit application
You can check the return value from DoModal() and exit the application accordingly.

You ask how to post WM_CLOSE from a dialog to end your application.
and if this way to close application from ModalDialog is safely.
Yes, but you must post the WM_CLOSE to the MainWnd before closing the dialog.
The MainWnd have to handle the exit of the application.
BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
ON_BN_CLICKED(IDOK, &CAboutDlg::OnBnClickedOk)
END_MESSAGE_MAP()
void CAboutDlg::OnBnClickedOk()
{
ASSERT(AfxGetApp()->m_pMainWnd != NULL);
AfxGetApp()->m_pMainWnd->PostMessage(WM_CLOSE, 0, 0);
CDialogEx::OnOK();
}

In your CYouModal::OnDestroy() handler, call a PostMessage for main window with WM_CLOSE id. have you tried that ?

Related

MFC EndDialog crashes when modal dialog does not have focus

I am closing a modal dialog after I end a task, inside a separate thread from where I created a modal dialog:
void CmodguiApp::_notify_task_end() {
processingDialog->EndDialog(0);
}
This works fine if my application has focus (therefore the modal dialog has focus). But this causes the application to crash if I change window while the modal dialog is on (for instance, if I leave the application processing and switch to Firefox or so).
What could be wrong?
Do not end the dialog with EndDialog. Instead PostMessage with WM_CLOSE or WM_QUIT to the dialog window.

Main dialog destroys before command message handler returns

My program use a modeless dialog to interact with the user and also has a tray icon.
A user can quit the app immediately by using the tray icon.
BOOL OnInitDialog()
{
init data...
}
void OnDestroy()
{
destroy data...
}
void OnSomeButton()
{
CFileDialog dlg;
...
dlg.DoModal(m_hWnd));
access data...
...
}
void OnMenuExit()
{
DestroyWindow();
}
The problem is that when I popup a modal dialog(OnSomeButton), and then quit using the tray icon menu, the main dialog is destroyed first, and then the modal one returns, trying to access some invalid data, causing a crash.
I know i can add some check code before accessing the data, but is there any other way?
Is there any way to ensure OnSomeButton() returns before window destroy?
You need to add your own application level code. There is no system support for this issue primarily because there can be so many pecularities that no generic approach is possible.
Yeah. When you quit from the tray menu, you can send a WM_CLOSE or similar message to your modal dialog that causes it to exit. Even if your main window is destroyed before that OnSomeButton returns you will be okay provided the remainder of that function does not access any class internals (member variables etc). You could ensure this by having the window proc of your modal dialog return an 'abort' code or something when it is closed in this way.

mfc modeless dialog in dll destroyed when thread exit

I want to open a MFC modeless dialog from a MFC dll injected into another process, the dll's job is to hook the winsock send & recv, and the dialog will be the interface to communicate with the dll. The dll should be able to run the hook while the dialog is running.
BOOL CDriverApp::InitInstance()
{
CWinApp::InitInstance();
if (!AfxSocketInit())
{
AfxMessageBox(IDP_SOCKETS_INIT_FAILED);
return FALSE;
}
AfxMessageBox("I'm In!");
DetourTransactionBegin();
DetourUpdateThread( GetCurrentThread() );
DetourAttach( &(PVOID &)RealSend, MySend );
DetourAttach( &(PVOID &)RealRecv, MyRecv );
if ((DetourTransactionCommit()) == NO_ERROR)
{
AfxMessageBox("Winsock hooked");
}
dlg = new ControlDlg();
m_pMainWnd = dlg;
if(dlg->Create(IDD_CONTROL_DLG))
{
dlg->ShowWindow(SW_SHOW);
}
//ExitThread(0);
return TRUE; <---
}
dlg is the dialog which is a member of CDriverApp
From what i have observed, the dialog is destroyed because the thread has exited and the memory that hold the dialog is removed.
The thread '_DllMainCRTStartup' (0x418) has exited with code 1657602048 (0x62cd0000).
I have read MFC modeless dialog close immediately thread, but my InitInstance() already returned true from the first place, so it's a different problem (i think)
So, my question is how to prevent the dialog from destroyed? Or perhaps prevent the thread from exit? or is it doable with a modal dialog?
This may be your problem:
Regular DLLs must have a CWinApp-derived class and a single object of
that application class, as does an MFC application. However, the
CWinApp object of the DLL does not have a main message pump, as does
the CWinApp object of an application.
Note that the CWinApp::Run
mechanism does not apply to a DLL, because the application owns the
main message pump. If the DLL opens modeless dialogs or has a main
frame window of its own, the application's main message pump must call
a routine exported by the DLL that in turn calls the
CWinApp::PreTranslateMessage member function of the DLL's application
object.
http://msdn.microsoft.com/en-US/library/f22wcbea(v=vs.80)
EDIT:
THis shows how to do what you are doing with a cWnd instead of a CDialog. Personally I think thats a better way to go.
http://codinganswer.com/c/cwnd-in-a-new-thread-in-a-dll.html
Here is an example of attaching a message hook to a modeless.
http://support.microsoft.com/kb/q187988/

Creating a dialog in new thread

Suppose if i create a thread using CreateThread, and I want a modal or modeless dialog in that thread. Do i need to use a seperate message loop for that like I have here,
while(GetMessage(&msg, 0, 0, 0)) // Get any window messages
{
TranslateMessage(&msg); // Translate the message
DispatchMessage(&msg); // Dispatch the message
}
But for modal dialog, you don't use that, so why shouldn't it work when i create a dialog?
When you use a modal dialog, it creates its own message queue, that's why it works. If you want to use modeless dialogs then you will have to create a message queue yourself.
From the documentation for DialogBox:
The DialogBox macro uses the CreateWindowEx function to create the dialog box. (snip) and starts its own message loop to retrieve and dispatch messages for the dialog box.

How to end a dialog mfc application from CDialog::OnInitDialog or immediately after this function ends?

In one case of my application, I want to end the application in the dialog's OnInitDialog or immediately after this function. Is there any way to do it?
I tried using windows messages – in OnInitDialog calling SendMessage and in the handler of the sent message calling OnClose – but it didn't do what I intended since the dialog still appeared.
PostQuitMessage(0) in the WM_INITDIALOG handler body will do the job.
You can simulate the user clicking the X in the corner of the dialog by sending a WM_SYSCOMMAND message:
PostMessage(WM_SYSCOMMAND, SC_CLOSE, 0);
The easiest solution:
CMyDialog::OnInitDialog()
{
if( "My Condition is invalid" )
{
EndDialog(-1);
return FALSE;
}
}
You have to do "return FALSE" juste after EndDialog because as you can read in the Microsoft documentation CDialog(classe), EndDialog doesn't close the dialog immediately, but generates a notification which when handled by Microsoft has to effect to end the dialog.