CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 7 of 7
  1. #1
    Join Date
    May 1999
    Location
    Lat: 47.285235, Lon: 8.565238
    Posts
    293

    Message to Parent Dialog produces Crash in Release Version

    Hi
    From a MainDlg I dynamically create a SubDlg for showing sort of a work progress. At the end the user can close the SubDlg.
    In OnClose I post/send a message to the MainDlg to indicate that the SubDlg closes. The MainDlg does some clean-up work then and the SubDlg closes and deletes itself.

    Problem: this all workes well compiled as Debug Version, but crashes when compiled as Release (no matter whether MFC used statically or dynamically).
    Where is the crash: When posting/sending the message from the SubDlg to the Parent (MainDlg, the MainDlg exeutes the clean-up work (OnMessageCleanUp), but if the execution returns to where the message was sent/posted and wants to continue, it crashes before the next line in the SubDlg is executed.
    When I do not send/post a message and call the appropriate function (declared as public) directly from within SubDlg and its parent member, there's no problem.

    The code looks as follows:

    #if !defined(AFX_MAINDLG_H__27D8CA5A_A1E7_4549_9735_C4DD57694768__INCLUDED_)
    #define AFX_MAINDLG_H__27D8CA5A_A1E7_4549_9735_C4DD57694768__INCLUDED_

    #if _MSC_VER > 1000
    #pragma once
    #endif // _MSC_VER > 1000
    // MainDlg.h : header file
    //

    // Include for the udownloader interfaces

    #include "SubDlg.h"

    /////////////////////////////////////////////////////////////////////////////
    // CMainDlg dialog

    class CMainDlg : public CDialog
    {
    // Construction
    public:
    // CMutex m_mutexCloseProgressDlg;
    void AbortDownload(BOOL bAbort = TRUE) { m_bAbortDownload = bAbort; }
    CMainDlg(CWnd* pParent = NULL); // standard constructor

    virtual ~CMainDlg();

    // Dialog Data
    //{{AFX_DATA(CMainDlg)
    enum { IDD = IDD_CFGMGR_DIALOG };
    //}}AFX_DATA

    // ClassWizard generated virtual function overrides
    //{{AFX_VIRTUAL(CMainDlg)
    //}}AFX_VIRTUAL

    // Implementation
    protected:
    HICON m_hIcon;

    // Generated message map functions
    //{{AFX_MSG(CMainDlg)
    virtual BOOL OnInitDialog();
    afx_msg void OnPaint();
    afx_msg HCURSOR OnQueryDragIcon();
    afx_msg void OnClose();
    afx_msg void OnDestroy();
    afx_msg void OnBtnDownload();
    //}}AFX_MSG
    afx_msg void EndDownloadThread();
    DECLARE_MESSAGE_MAP()
    public:
    afx_msg void OnCloseSubDlg();

    private:
    BOOL m_bAbortDownload;
    CSubDlg* m_pProgressDlg;
    HANDLE m_hDownloadThread;
    };

    //{{AFX_INSERT_LOCATION}}
    // Microsoft Visual C++ will insert additional declarations immediately before the previous line.

    #endif // !defined(AFX_MAINDLG_H__27D8CA5A_A1E7_4549_9735_C4DD57694768__INCLUDED_)



    // MainDlg.cpp : implementation file
    //

    #include "StdAfx.h"
    #include "Main.h"
    #include "MainDlg.h"

    #ifdef _DEBUG
    #define new DEBUG_NEW
    #undef THIS_FILE
    static char THIS_FILE[] = __FILE__;
    #endif

    /////////////////////////////////////////////////////////////////////////////
    // CMainDlg Download Thread

    DWORD WINAPI DownloadThread(LPVOID pVoid)
    {
    CMainDlg* pParent = reinterpret_cast<CMainDlg*>(pVoid);

    // pParent->MessageBox(_T("Start Download"));
    Sleep(1000);
    // pParent->MessageBox(_T("End Download"));

    pParent->PostMessage(EV_END_DOWNLOAD_THREAD);

    return 0;
    } // DownloadThread(LPVOID pVoid)

    /////////////////////////////////////////////////////////////////////////////
    // CMainDlg dialog

    CMainDlg::CMainDlg(CWnd* pParent /*=NULL*/)
    : CDialog(CMainDlg::IDD, pParent),
    m_pProgressDlg(NULL), m_hDownloadThread(NULL), m_bAbortDownload(FALSE)
    {
    // Note that LoadIcon does not require a subsequent DestroyIcon in Win32
    m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
    } // CMainDlg::CMainDlg(CWnd* pParent /*=NULL*/)

    CMainDlg::~CMainDlg()
    {
    } // CMainDlg::~CMainDlg()

    BEGIN_MESSAGE_MAP(CMainDlg, CDialog)
    //{{AFX_MSG_MAP(CMainDlg)
    ON_WM_PAINT()
    ON_WM_QUERYDRAGICON()
    ON_BN_CLICKED(IDC_BTN_CLOSE, OnClose)
    ON_WM_DESTROY()
    ON_BN_CLICKED(IDC_BTN_DOWNLOAD, OnBtnDownload)
    //}}AFX_MSG_MAP
    ON_MESSAGE(EV_CLOSE_PROGRESS_DIALOG, OnCloseSubDlg)
    ON_MESSAGE(EV_END_DOWNLOAD_THREAD, EndDownloadThread)
    END_MESSAGE_MAP()

    /////////////////////////////////////////////////////////////////////////////
    // CMainDlg message handlers

    BOOL CMainDlg::OnInitDialog()
    {
    CDialog::OnInitDialog();

    // Set the icon for this dialog. The framework does this automatically
    // when the application's main window is not a dialog
    SetIcon(m_hIcon, TRUE); // Set big icon
    SetIcon(m_hIcon, FALSE); // Set small icon

    SIZE sizeDisplay;
    sizeDisplay.cx = GetSystemMetrics(SM_CXFULLSCREEN)/2;
    sizeDisplay.cy = GetSystemMetrics(SM_CYFULLSCREEN)/2;

    // Because LoadData() uses SetRedraw function, the taskbar icon is not displayed
    // This is fixed with the call of ShowWindow(SW_HIDE).
    ShowWindow(SW_HIDE);

    CRect rc;
    GetWindowRect(&rc);
    long lWidth = rc.Width();
    long lHeight = rc.Height();
    rc.left = sizeDisplay.cx - (lWidth / 2);
    rc.top = sizeDisplay.cy - (lHeight / 2);
    SetWindowPos(&wndTop, rc.left, rc.top, lWidth, lHeight, NULL);

    return TRUE; // return TRUE unless you set the focus to a control
    }

    // If you add a minimize button to your dialog, you will need the code below
    // to draw the icon. For MFC applications using the document/view model,
    // this is automatically done for you by the framework.

    void CMainDlg::OnPaint()
    {
    if (IsIconic())
    {
    CPaintDC dc(this); // device context for painting

    SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

    // Center icon in client rectangle
    int cxIcon = GetSystemMetrics(SM_CXICON);
    int cyIcon = GetSystemMetrics(SM_CYICON);
    CRect rect;
    GetClientRect(&rect);
    int x = (rect.Width() - cxIcon + 1) / 2;
    int y = (rect.Height() - cyIcon + 1) / 2;

    // Draw the icon
    dc.DrawIcon(x, y, m_hIcon);
    }
    else
    CDialog::OnPaint();
    } // CMainDlg::OnPaint()

    // The system calls this to obtain the cursor to display while the user drags
    // the minimized window.
    HCURSOR CMainDlg::OnQueryDragIcon()
    {
    return (HCURSOR) m_hIcon;
    }

    void CMainDlg::OnClose()
    {
    if (NULL != m_pProgressDlg)
    {
    // m_pProgressDlg->DestroyWindow();
    // delete m_pProgressDlg;
    m_pProgressDlg = NULL;
    } // if (NULL != m_pProgressDlg)
    OnOK();
    } // CMainDlg::OnClose

    void CMainDlg::OnDestroy()
    {
    CDialog::OnDestroy();
    } // CMainDlg::OnDestroy()

    void CMainDlg::OnBtnDownload()
    {
    // Check at the very beginning of Download, if the DownloadThread is still running
    if (NULL != m_hDownloadThread)
    {
    EndDownloadThread();
    } // if (NULL != m_hDownloadThread)

    // Now that it's sure that the thread doesn't run, create the dialog and start the thread
    m_pProgressDlg = new CSubDlg;
    if (!m_pProgressDlg->Create(IDD_PROGRESS_DIALOG, this))
    m_pProgressDlg = NULL;

    EnableWindow(FALSE);
    m_pProgressDlg->ShowWindow(SW_SHOW);

    m_hDownloadThread = CreateThread(NULL, 0, &DownloadThread, (LPVOID)this, CREATE_SUSPENDED, NULL);

    if (NULL == m_hDownloadThread)
    {
    CString str;
    str.Format(_T("Error #%d: Could not initiate Download"), GetLastError());
    MessageBox(str, _T("Error"), MB_ICONSTOP);

    CloseHandle(m_hDownloadThread);
    m_hDownloadThread = NULL;

    m_pProgressDlg->DestroyWindow();
    delete m_pProgressDlg;
    m_pProgressDlg = NULL;

    EnableWindow(TRUE);

    return;
    } // if

    ResumeThread(m_hDownloadThread);
    } // CMainDlg::OnBtnDownload()

    void CMainDlg::OnCloseSubDlg()
    {
    MessageBox(_T("OnCloseSubDlg"));
    // The SubDlg destroys and deletes itself.
    // m_pProgressDlg->DestroyWindow();
    // delete m_pProgressDlg;
    MessageBox(_T("ProgressDlg = NULL"));
    m_pProgressDlg = NULL;
    EnableWindow(TRUE);
    MessageBox(_T("Window enabled"));
    } // CMainDlg::OnCloseSubDlg()

    void CMainDlg::EndDownloadThread()
    {
    WaitForSingleObject(m_hDownloadThread, INFINITE);
    CloseHandle(m_hDownloadThread);
    m_hDownloadThread = NULL;
    if (NULL != m_pProgressDlg)
    m_pProgressDlg->SetAbortToClose();
    } // CMainDlg::EndDownloadThread()



    #if !defined(AFX_SUBDLG_H__30FDA0CE_7240_4C42_A779_7B593F2CC756__INCLUDED_)
    #define AFX_SUBDLG_H__30FDA0CE_7240_4C42_A779_7B593F2CC756__INCLUDED_

    #if _MSC_VER > 1000
    #pragma once
    #endif // _MSC_VER > 1000
    // SubDlg.h : header file
    //

    /////////////////////////////////////////////////////////////////////////////
    // CSubDlg dialog

    class CSubDlg : public CDialog
    {
    // Construction
    public:
    void SetAbortToClose();
    CSubDlg(CWnd* pParent = NULL); // standard constructor

    // Dialog Data
    //{{AFX_DATA(CSubDlg)
    enum { IDD = IDD_PROGRESS_DIALOG };
    //}}AFX_DATA

    // Overrides
    // ClassWizard generated virtual function overrides
    //{{AFX_VIRTUAL(CSubDlg)
    protected:
    virtual void PostNcDestroy();
    //}}AFX_VIRTUAL

    // Implementation
    protected:

    // Generated message map functions
    //{{AFX_MSG(CSubDlg)
    virtual void OnCancel();
    virtual BOOL OnInitDialog();
    //}}AFX_MSG
    DECLARE_MESSAGE_MAP()

    private:
    BOOL m_bCloseNextTime;
    BOOL m_bIsClosed;
    };

    //{{AFX_INSERT_LOCATION}}
    // Microsoft Visual C++ will insert additional declarations immediately before the previous line.

    #endif // !defined(AFX_SUBDLG_H__30FDA0CE_7240_4C42_A779_7B593F2CC756__INCLUDED_)



    // SubDlg.cpp : implementation file
    //

    #include "StdAfx.h"
    #include "Main.h"

    #include "MainDlg.h"

    #include "SubDlg.h"

    #ifdef _DEBUG
    #define new DEBUG_NEW
    #undef THIS_FILE
    static char THIS_FILE[] = __FILE__;
    #endif

    /////////////////////////////////////////////////////////////////////////////
    // CSubDlg dialog

    CSubDlg::CSubDlg(CWnd* pParent /*=NULL*/)
    : CDialog(CSubDlg::IDD, pParent), m_bCloseNextTime(FALSE), m_bIsClosed(FALSE)
    {}

    BEGIN_MESSAGE_MAP(CSubDlg, CDialog)
    //{{AFX_MSG_MAP(CSubDlg)
    //}}AFX_MSG_MAP
    END_MESSAGE_MAP()

    /////////////////////////////////////////////////////////////////////////////
    // CSubDlg message handlers

    void CSubDlg::OnCancel()
    {
    if (!m_bCloseNextTime)
    {
    AfxGetApp()->LoadStandardCursor(IDC_WAIT);
    ((CMainDlg*)GetParent())->AbortDownload(TRUE);
    } // if (m_bCloseNextTime)
    else
    {
    m_bIsClosed = TRUE;
    ShowWindow(SW_HIDE);
    MessageBox(_T("Posting Message"));
    // Send message doesn't work in Release Version (Debug okay)
    ((CMainDlg*)GetParent())->SendMessage(EV_CLOSE_PROGRESS_DIALOG);
    // Direct call works in both versions (Debug and Release)
    // ((CMainDlg*)GetParent())->OnCloseSubDlg();
    MessageBox(_T("Message Posted"));
    DestroyWindow();
    } // else
    } // CSubDlg::OnCancel()

    void CSubDlg::SetAbortToClose()
    {
    MessageBeep(MB_OK);
    m_bCloseNextTime = TRUE;
    m_bIsClosed = FALSE;
    GetDlgItem(IDCANCEL)->SetWindowText(_T("&Close"));
    AfxGetApp()->LoadStandardCursor(IDC_ARROW);
    } // CSubDlg::SetAbortToClose()

    BOOL CSubDlg::OnInitDialog()
    {
    CDialog::OnInitDialog();

    CRect rc;
    GetWindowRect(&rc);
    long lWidth = rc.Width();
    long lHeight = rc.Height();

    CRect rcParent;
    ((CMainDlg*)GetParent())->GetWindowRect(&rcParent);
    long lParentWidth = rcParent.Width();
    long lParentHeight = rcParent.Height();

    rc.left = rcParent.left + ((lParentWidth - lWidth) / 2);
    rc.top = rcParent.top + ((lParentHeight - lHeight) / 2);
    SetWindowPos(NULL, rc.left, rc.top, lWidth, lHeight, NULL);

    return TRUE; // return TRUE unless you set the focus to a control
    // EXCEPTION: OCX Property Pages should return FALSE
    } // CSubDlg::OnInitDialog()

    void CSubDlg::PostNcDestroy()
    {
    delete this;
    } // CSubDlg::PostNcDestroy()




    Any suggestions, why the Send-/Post-Message doesn't work here? Is this a bug?
    Many thanks for helping to solve this problem.
    (previous/related thread: http://www.codeguru.com/cgi-bin/bbs/...sb=5&category=)

    I do what I can to help - at least.
    And I really appreciate every help, as well!

    Ratings are always welcome - I give, too.

  2. #2
    Join Date
    Dec 2000
    Location
    Slovakia
    Posts
    1,043

    Re: Message to Parent Dialog produces Crash in Release Version

    You are declaring two functions:

    void OnCloseSubDlg();
    void EndDownloadThread();

    You use this function as messages handlers by using ON_MESSAGE macro.

    If you look into the MSDN, you will find out, that prototype of such message handlers has to be:
    LRESULT OnSomeMessagFnc(WPARAM wParam, LPARAM lParam);

    I thing, this is the cause of the crash!

    Martin


  3. #3
    Join Date
    May 1999
    Location
    Lat: 47.285235, Lon: 8.565238
    Posts
    293

    Re: Message to Parent Dialog produces Crash in Release Version

    Thanks, this really solves the problem. But the question that stays is WHY?

    I used ON_MESSAGE already so many times and had no problem with it. Also it's not comprehensive to me that it works in Debug version but not in Release version. Do you know these answers?

    Thanks

    Holi

    I do what I can to help - at least.
    And I really appreciate every help, as well!

    Ratings are always welcome - I give, too.

  4. #4
    Join Date
    Dec 2000
    Location
    Slovakia
    Posts
    1,043

    Re: Message to Parent Dialog produces Crash in Release Version

    Yes sure.

    Macro makes call of function which returns LRESULT and which have two parameters.
    You write just "void" function.
    Code generated by ON_MESSAGE macro puts WPARAM and LPARAM onto the stack before calling message handler and wants to get return value.
    Hoverver, parameters as well as return value are not supported by the function and it has to cause crash!

    Martin


  5. #5
    Join Date
    May 1999
    Location
    Lat: 47.285235, Lon: 8.565238
    Posts
    293

    Re: Message to Parent Dialog produces Crash in Release Version

    Hi Martin

    I have a new strange effect now: when closing the SubDlg, the MainDlg disappears behind the next other app (in z-order) that's open. When closing the SubDlg, OnCloseSubDlg() is called, where I enable the MainDlg again. Maybe it's because of that?

    When I call ShowWindow(SW_HIDE) and ShowWindow(SW_SHOW) after Enabling the window, the MainDlg shows up again. Calling ShowWindow(SW_SHOW) only doesn't work.

    Any idea? Thanks.

    Holi

    I do what I can to help - at least.
    And I really appreciate every help, as well!

    Ratings are always welcome - I give, too.

  6. #6
    Join Date
    Jan 2002
    Location
    Indianapolis, Indiana
    Posts
    2

    Re: Message to Parent Dialog produces Crash in Release Version

    Thank you. I had the very same problem in my code. The fact it worked in the Debug version, but not the Release really threw me off. Much appreciated.

    Daniel


  7. #7
    Join Date
    Apr 2001
    Location
    CA , USA
    Posts
    83

    Re: Message to Parent Dialog produces Crash in Release Version

    Hi

    I also have the same problem. User defined message works fine in debug mode but crashes in release version. But the problem is solved by changing the prototype of message handler as you told in the post. But i did not understand why this happens. Why it does not crash in debug mode also...

    Thanks
    Shashi


Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured