0
votes

Say, I create a dialog window from my context menu that could be invoked by right-clicking the tray icon of my application:

CDialogDerivedClass dlg;
dlg.DoModal();

In case a user right-clicks my context menu again and picks another command I need to close that dialog window and show another one. I thought that simply sending WM_CLOSE to that first window would do the trick:

dlg.SendMessage(WM_CLOSE);

but evidently it messes something up inside the MFC class because that dialog's CDialogDerivedClass::OnDestroy() method is never called at that moment. This only happens when my app or its process exits (way later.)

So I'm curious, how do you close the MFC's CDialog derived class from outside (from the same / main thread)?

4
I think this is only going to work if the dialog is modeless.user1793036
Yeah, I thought so. I was just trying to avoid rewriting dialogs into modeless.c00000fd
If your dialog is modal, surely you can't interact with your application via the context menu until it's closed? In any case, I would use DestroyWindow to close it.Roger Rowland

4 Answers

0
votes

I suppose you could simulate a click on cancel: ::EndDialog(dlg.m_hWnd, IDCANCEL);

0
votes

Sorry on my misunderstanding on your question.

You could create one pointer for each dialogue you want to start from System Tray Menu in your main class:

Add pointers to your dialogues in your main class header:

CDialog1 *m_pDialog1;
CDialog2 *m_pDialog2;

Don't forget to initialize them to NULL in your main class constructor.

Add a MAP to handle the menu options:

ON_COMMAND(ID_DIALOG1, &CSystemTrayApp::OnDialog1)
ON_COMMAND(ID_DIALOG2, &CSystemTrayApp::OnDialog2)

And them, call "EndDialog" for any started dialogue, using the pointer, before you start the new one:

void CSystemTrayApp::OnDialog1()
{
    if ( m_pDialog2 != NULL && m_pDialog2->GetSafeHwnd() )
    {
        m_pDialog2->EndDialog(IDCANCEL);
        delete m_pDialog2;
        m_pDialog2 = NULL;
    }

    m_pDialog1 = new CDialog1();
    m_pDialog1->DoModal();
}


void CSystemTrayApp::OnDialog2()
{
    if ( m_pDialog1 != NULL && m_pDialog1->GetSafeHwnd() )
    {
        m_pDialog1->EndDialog(IDCANCEL);
        delete m_pDialog1;
        m_pDialog1 = NULL;
    }

    m_pDialog2 = new CDialog2();
    m_pDialog2->DoModal();
}

On the descructor of your main class, clean up the dialogues if needed:

if ( m_pDialog1 != NULL ) delete m_pDialog1;
if ( m_pDialog2 != NULL ) delete m_pDialog2;
0
votes

Via a handle to some window an application can send/post any type messages to that window. Hence , here comes a possible solutions you may want to have a try.

Simply, when the first modeless window(the one invoking DoModel()) has created, then to save its handle as a global or another Static varibles. when you want to close the modeless , you can post a message of WM_CLOSE to that window.

what matters is the API to deliver the WM_CLOSE message.As the official doc describes that:

  • the sendmessage() function calls the window procedure for the specified window and does not return until the window procedure has processed the message.
  • the postmessage() function just places(posts) a message in the message queue associated with the thread that created the specified window and returns without waiting for the thread to process the message.

Briefly speaking, first to save the handle ; second to deliver the WM_CLOSE(or some type message) to that window.

-1
votes

Try

EndDialog(IDCANCEL); or EndDialog(IDOK);

Hope it helps,

Vinicius