2013-06-11 1 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와 모덜리스 대화 상자가 나타납니다.

모덜리스 대화 상자를 닫을 때 문제가 발생합니다.

모덜리스 대화 상자의 클로저/삭제를 올바르게 수행하는 방법을 찾을 수 없습니다. 오른쪽 상단 모서리에있는 십자 버튼을 클릭하면 어떤 메시지가 표시됩니까? ?

내가 시도한 현재 코드는 다음과 같습니다.

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();   
}  

아니 내가 잘못하고 또는 무엇을하고 무엇을 이해할 수 I 오전 있어야 할 곳에 없는?

필요한 경우 추가 정보를 제공 할 수 있습니다.

미리 감사드립니다.

편집-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

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을 반환하기 때문에 사용하는 방식이 충돌을 일으킬 수 있습니다.

여기에 기본 클래스 구현을 호출하기 전에 호출을 OnDestroy()으로 이동해보십시오.

또 다른 옵션은 부모의 hWnd를 캐시하고 해당 hWnd에 ::PostMessage()을 호출하는 것입니다.

+2

여기에 귀하의 조언은 잘못되어 위험합니다. PostNcDestroy는 대화 상자에서 마지막으로받은 메시지이므로 '삭제'를 수행하는 유일한 안전한 멤버 함수입니다. 더 빨리 삭제하면 삭제 된 개체가 메시지 처리를 시도합니다. CDialog 설명서에 "이 메시지를 삭제하려면 모덜리스 대화 상자에 대해 PostNCDestroy를 재정의해야합니다." –

+0

나는'Deleted this'로 전화를 옮기려하지 않고 그의'PostMessage' 호출을'OnDestroy'로 옮기기 만했다. 혼란을 드려 죄송합니다. – edtheprogrammerguy