2013-06-11 6 views
0

Я создаю немодальное диалоговое окно. Диалоговое окно вызывается из пункта меню окна основного кадра.Сбой при выполнении GetParent(). Закрытие немодального диалогового окна

mainfrm.h

CModeless* modeless;  
bool modelessDlgOpen;  

MainFrm.cpp

void CMainFrame::OnDatabaseMLdlg()  
{  
    // TODO: Add your command handler code here  
    if (modelessDlgOpen == TRUE)  
     return;  

    modelessDlgOpen = TRUE;  

    modeless = new CModeless(this);  

    //modeless->Create(IDD_MLDLG, GetDesktopWindow());  
    modeless->Create(IDD_MLDLG, this);  
    mbPoll->ShowWindow(SW_SHOW);  
}  

Когда пункт меню нажата, функция OnDatabaseMLdlg() вызывается и появляется немодальный диалоговое окно с ресурсами ID IDD_MLDLG.

Проблема заключается в закрытии диалогового окна modeless.

Я не могу найти правильный метод, чтобы иметь чистое закрытие/уничтожение этого немодального диалогового окна. При нажатии на крестик в правом верхнем углу, какое сообщение получает ?

Мой текущий код, который я пробовал, выглядит следующим образом. (Производство код относится только к закрытию диалогового окна)

MLDLG.h

#pragma once  

#define WM_MLDLG_CLOSED (WM_USER + 555)  
// CModeless dialog  

class CModeless : public CDialog  
{  
    DECLARE_DYNAMIC(CModeless)  

public:  
    CModeless(CWnd* pParent = NULL); // standard constructor  
    virtual ~CModeless();  

// Dialog Data  
    enum { IDD = IDD_MLDLG };  

protected:  
    virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support  

    DECLARE_MESSAGE_MAP()  
public:  
    virtual BOOL Create(UINT nIDTemplate, CWnd* pParentWnd = NULL);  
    afx_msg void OnNcDestroy();  
    virtual void PostNcDestroy();  
    CWnd* mParent;  
    afx_msg void OnBnClickedCancel();  
};  

MLDLG.cpp

void CModeless::OnNcDestroy()  
{  
    CDialog::OnNcDestroy();  

    // TODO: Add your message handler code here  
}  

void CModeless::PostNcDestroy()  
{   
    CDialog::PostNcDestroy();  
    GetParent()->PostMessage(WM_MLDLG_CLOSED,0,0);  // **CRASHES HERE** 
    delete this;  
}  

void CModeless::OnBnClickedCancel()  
{  
    // TODO: Add your control notification handler code here  
    //CDialog::OnCancel();  
    DestroyWindow();   
}  

не в состоянии понять, что я делаю неправильно или что это я отсутствует?

Я могу предоставить дополнительную информацию в случае необходимости.

Заранее спасибо.

EDIT-20130612: Дополнительная информация:

Мой конструктор выглядит следующим образом:

CModeless::CModeless(CWnd* pParent /*=NULL*/)  
    : CDialog(CModeless::IDD, pParent)  
{  
    mParent = pParent;  
    if (mParent == NULL)  
    {  
     MessageBox(L"mParent is NULL"); 
    }  
    else  
    {  
     MessageBox(L"mParent is not NULL");  
    }  
}  

Вот, я проверил, что mParent не NULL.

+1

Does GetParent() возвращает NULL? Если это так, ваше переопределение функции «Создать» не позволяет передать pParent в конструктор CDialog. Если вы отправляете сообщение родителям, вы должны сохранить pParent и убедиться, что он не является NULL, так или иначе. –

+0

В конструкторе я сохраняю переменную pParent переменной-члену CWnd * mParent. Я думал, что GetParent вернет то же самое и будет безопаснее, чем что-то вроде mParent-> PostMessage(). Пожалуйста, поправьте меня, если я ошибаюсь. – Jay

+1

GetParent получает свойство окна. Он, конечно, не получает переменную-член mParent. Это свойство задается параметром CDialog :: Create pParentWnd.Независимо от того, используете ли вы свою собственную переменную-член или pParentWnd диалога (любой из них будет работать), вы должны убедиться, что он не является NULL. –

ответ

0

PostNCDestroy() называется ОЧЕНЬ поздним, и большинство полезного состояния окна MFC недействительно в этой точке. GetParent(), вероятно, возвращает NULL, что приведет к сбою, как вы его используете.

Попробуйте переместить PostMessage вызов OnDestroy() перед вызовом реализации базового класса.

Другим вариантом является кэширование hWnd родителя и вызов ::PostMessage() на этом hWnd;

+2

. Ваш совет здесь неверен и опасен. PostNcDestroy - это последнее сообщение, полученное диалоговым окном, так что это единственная безопасная функция-член, которая выполняет «удаление этого». При удалении какого-либо объекта удаленный объект пытается обработать сообщение. Документация CDialog гласит: «Вы должны переопределить PostNCDestroy для немодальных диалоговых окон, чтобы удалить это». –

+0

Я не хотел переводить вызов на 'delete this', только чтобы переместить его вызов' PostMessage' в 'OnDestroy'. Извините за путаницу. – edtheprogrammerguy