|
-
January 25th, 2002, 10:06 AM
#1
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. 
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|