4

I have followed this question to make a non-modal/modeless dialog: How to display a non-modal CDialog?

I'm using MFC/C++ in VS2008. I'm more fluent with C# and .net than with MFC and C++.

I have a menu item in my form that launches the dialog. There can only be one instance of the dialog opened. The dialog displays fine. I can close it by clicking the X in the corner and it closes when I close the main form. The problem I am having is the dialog cannot be opened again after I click the X to close the dialog. I know it is because the pointer is never set back to NULL.

I have this in my form's header file:

CChildDialog *m_pDialog;

I have this part in my form's constructor:

m_pDialog = NULL;

When clicking on a menu item I have this code in the menu item's method (I modified it from the other SO answer because I only want one instance of the dialog opened):

if(m_pDialog == NULL)
{
    // Invoking the Dialog
    m_pDialog = new CChildDialog();
    BOOL ret = m_pDialog->Create(IDD_CHILDDIALOG, this);

    if (!ret)   //Create failed.
    {
        AfxMessageBox(_T("Error creating Dialog"));
    }    

    m_pDialog->ShowWindow(SW_SHOW);
}

Now I know I need to execute this part and set the pointer to NULL, but I don't know where to put this:

// Delete the dialog once done
delete m_pDialog;
m_pDialog = NULL;

Do I need to keep monitoring if the dialog has been disposed? Is there an event triggered to the parent form when the dialog is closed?

4

4 に答える 4

4

Xでウィンドウを閉じた後にウィンドウの内容をリサイクルする場合は、ダイアログでWM_CLOSEメッセージを処理する必要があります。

void CChildDialog::OnClose()
{
    ShowWindow(SW_HIDE);
}

次に、ウィンドウを開くコードで:

if(m_pDialog == NULL)
{
    // Invoking the Dialog
    m_pDialog = new CChildDialog();
    BOOL ret = m_pDialog->Create(IDD_CHILDDIALOG, this);

    if (!ret)   //Create failed.
    {
        AfxMessageBox(_T("Error creating Dialog"));
    }    
}

m_pDialog->ShowWindow(SW_SHOW); //moved outside the if(m_pDialog == NULL)

それが役立つことを願っています

于 2012-08-08T17:00:15.090 に答える
3

モードレスダイアログを削除したい場合は、削除してください。

ユーザーがモードレスダイアログを閉じたときにダイアログのオブジェクトを削除したい場合は、を参照してくださいWM_PARENTNOTIFY。子ウィンドウが破棄され、子ウィンドウに拡張ウィンドウスタイルWS_EX_NOPARENTNOTIFYが設定されていない場合、windowsはWM_PARENTNOTIFYwith wParam=WM_DESTROYを親ウィンドウに送信します。親ウィンドウにそのメッセージのハンドラーを実装し、破棄されているのがモードレスダイアログであるかどうかを確認する必要があります。

于 2012-08-09T09:56:02.807 に答える
1

I had the question drafted up and was ready to post it, but then I had an idea and ended up solving my own problem. So for anyone else who has an issue with detecting the closing of a modeless dialog, this is what I did:

void Form1::MenuItemMethod()
{
    if(m_pDialog == NULL)
    {
        // Invoking the Dialog
        m_pDialog = new CChildDialog();
        BOOL ret = m_pDialog->Create(IDD_CHILDDIALOG, this);

        if (!ret)   //Create failed.
        {
            AfxMessageBox(_T("Error creating Dialog"));
        }    

        m_pDialog->ShowWindow(SW_SHOW);
    }
    else
    {
        // cannot check if visible at the beginning of method because
        // pointer could be NULL and will throw an exception

        if(m_pDialog->IsWindowVisible())
        {
            return;
        }

        m_pDialog->DestroyWindow();
        m_pDialog = NULL;
        MenuItemMethod();
    }
}

I just ended up checking if the modeless dialog is visible after clicking on the form's menu item again. If it is visible, don't do anything. If not, destroy the existing non-visible dialog, set the pointer to NULL, and recursively call the method again. Since the pointer is now NULL, it should recreate the dialog normally and then return to normal operation.

于 2012-08-08T16:20:29.653 に答える
0

PostNcDestroyこのようにメモリを削除する必要があります

void CChildDialog ::PostNcDestroy() 
{   
    CDialog::PostNcDestroy();
    GetParent()->PostMessage(WM_WIN_CLOSED,0,0);
    delete this;
}

そして、ウィンドウが閉じているというユーザー定義のメッセージを親ウィンドウに送信します。親ウィンドウで、次のWM_WIN_CLOSEDようなメッセージハンドラを追加します

LRESULT CMainDialog::OnMyMethod(WPARAM wParam, LPARAM lParam)
{
    m_pDialog = NULL; 
    return 0;
}
于 2012-08-09T07:35:25.283 に答える