Click here to Skip to main content
15,901,035 members
Home / Discussions / C / C++ / MFC
   

C / C++ / MFC

 
QuestionReadFile function returns 1 but number of bytes read is returning 0 Pin
learningvisualc8-Jun-10 20:35
learningvisualc8-Jun-10 20:35 
AnswerRe: ReadFile function returns 1 but number of bytes read is returning 0 Pin
Cedric Moonen8-Jun-10 20:40
Cedric Moonen8-Jun-10 20:40 
QuestionTab control Pin
john56328-Jun-10 19:53
john56328-Jun-10 19:53 
AnswerRe: Tab control Pin
Niklas L8-Jun-10 23:16
Niklas L8-Jun-10 23:16 
QuestionReg Excel Automation in SDI Pin
hellogany8-Jun-10 19:22
hellogany8-Jun-10 19:22 
AnswerRe: Reg Excel Automation in SDI Pin
«_Superman_»8-Jun-10 19:28
professional«_Superman_»8-Jun-10 19:28 
GeneralRe: Reg Excel Automation in SDI Pin
hellogany9-Jun-10 0:23
hellogany9-Jun-10 0:23 
QuestionFailure in SendMessage in Retail Verrsion only, has me baffled. Pin
Bram van Kampen8-Jun-10 14:16
Bram van Kampen8-Jun-10 14:16 
Hi,

I am using the following code for years without any complaints. It is used by me in many apps, and included in libs, too many to count.
Always worked a dream.

It concerns an MFC Type CProgressDlg Base Class. A User would derrive his own class thereof, Set a Workerthread function, and the thing takes off as expected.

Here is the Header
<br />
#if !defined(AFX_PROGRESSDLG_H__07E71F2A_E348_47C9_B150_F02855B96859__INCLUDED_)<br />
#define AFX_PROGRESSDLG_H__07E71F2A_E348_47C9_B150_F02855B96859__INCLUDED_<br />
<br />
#if _MSC_VER >= 1000<br />
#pragma once<br />
#endif // _MSC_VER >= 1000<br />
// ProgressDlg.h : header file<br />
//<br />
<br />
enum{	<br />
	WM_ENDDIALOG=WM_USER+1,<br />
	WM_UPDATE_DATA,<br />
	WM_SHOULD_TERMINATE,<br />
};<br />
<br />
<br />
class CProgressDlg;<br />
typedef DWORD (CProgressDlg::*PFN_PROGRESS_DLG_THREADPROC)(void);<br />
<br />
/////////////////////////////////////////////////////////////////////////////<br />
<br />
// Advance Declaration of the Thread Proc that calls the Worker Function<br />
// We need to make it a friend, so that it has access to the Private Members<br />
static int (ProgressDlgThread)(void*);<br />
<br />
<br />
////////////////////////////////////////////<br />
// CProgressDlg dialog<br />
class CProgressDlg : public CDialog<br />
{<br />
	friend ProgressDlgThread(void*);<br />
<br />
	DECLARE_DYNAMIC( CProgressDlg )<br />
<br />
public:<br />
	DWORD GetThreadResult();<br />
	PFN_PROGRESS_DLG_THREADPROC SetWorkerThreadProcedure(PFN_PROGRESS_DLG_THREADPROC pFn);<br />
	void EndDialog(int ExitCode);<br />
	BOOL ShouldTerminate(DWORD* pdwReason=NULL);<br />
	CProgressDlg(UINT nIDTemplate,CWnd* pParent =NULL);   <br />
<br />
protected:<br />
	CRITICAL_SECTION m_cs;<br />
	virtual void DoDataExchange(CDataExchange* pDX);    <br />
	virtual BOOL UpdateData(BOOL bSaveAndValidate = TRUE);<br />
	virtual void OnOK();<br />
	virtual void OnCancel();<br />
	virtual BOOL OnInitDialog();<br />
<br />
	DECLARE_MESSAGE_MAP()<br />
private:<br />
	// Private Implementation Functions<br />
	// If you compile this into a DLL, just remove the following:<br />
	// two lines in the Public DLL Header<br />
<br />
	void _OnEndDialog(int ExitCode);<br />
	void _OnUpdateData(BOOL bSaveAndValidate,BOOL*pbRes);<br />
	// Private Implementation Data<br />
	// If you compile this into a DLL, replace the following section with:<br />
	// DWORD Reserved[5] in the Public DLL Header<br />
	PFN_PROGRESS_DLG_THREADPROC m_pFnThreadProc;<br />
	BOOL m_bShouldTerminate;<br />
	int m_nDlgStatus;<br />
	DWORD m_dwDlgResult;<br />
	DWORD m_dwThreadResult;<br />
	CWinThread* m_pWinThread;<br />
<br />
<br />
<br />
};<br />
<br />
<br />
#endif // !defined(AFX_PROGRESSDLG_H__07E71F2A_E348_47C9_B150_F02855B96859__INCLUDED_)<br />


and Implementation.
<br />
// ProgressDlg.cpp : implementation file<br />
//<br />
<br />
#include "stdafx.h"<br />
#include "ProgressDlg.h"<br />
<br />
#ifdef _DEBUG<br />
#define new DEBUG_NEW<br />
#undef THIS_FILE<br />
static char THIS_FILE[] = __FILE__;<br />
#endif<br />
<br />
<br />
enum{<br />
	THREADSTATE_NOT_STARTED=0,<br />
	THREADSTATE_RUNNING,<br />
	THREADSTATE_COMPLETED,<br />
}; <br />
<br />
/////////////////////////////////////////////////////////////////////////////<br />
// CProgressDlg dialog<br />
IMPLEMENT_DYNAMIC( CProgressDlg, CDialog )<br />
<br />
CProgressDlg::CProgressDlg(UINT nIDTemplate,CWnd* pParent /*=NULL*/)<br />
	: CDialog(nIDTemplate, pParent)<br />
{<br />
<br />
	//{{AFX_DATA_INIT(CProgressDlg)<br />
		// NOTE: the ClassWizard will add member initialization here<br />
	//}}AFX_DATA_INIT<br />
	InitializeCriticalSection(&m_cs);<br />
<br />
	m_pFnThreadProc=NULL;<br />
	m_nDlgStatus=THREADSTATE_NOT_STARTED;<br />
	m_dwDlgResult=IDOK;<br />
	m_dwThreadResult=0;<br />
	m_bShouldTerminate=0;<br />
	m_pWinThread=NULL;<br />
<br />
}<br />
<br />
<br />
void CProgressDlg::DoDataExchange(CDataExchange* pDX)<br />
{<br />
	EnterCriticalSection(&m_cs);<br />
	CDialog::DoDataExchange(pDX);<br />
	LeaveCriticalSection(&m_cs);<br />
<br />
	//{{AFX_DATA_MAP(CProgressDlg)<br />
		// NOTE: the ClassWizard will add DDX and DDV calls here<br />
	//}}AFX_DATA_MAP<br />
}<br />
<br />
<br />
BEGIN_MESSAGE_MAP(CProgressDlg, CDialog)<br />
	//{{AFX_MSG_MAP(CProgressDlg)<br />
	ON_MESSAGE(WM_ENDDIALOG,_OnEndDialog)<br />
	ON_MESSAGE(WM_UPDATE_DATA,_OnUpdateData)<br />
	//}}AFX_MSG_MAP<br />
END_MESSAGE_MAP()<br />
<br />
<br />
<br />
//////////////////////////////////////////////////<br />
// This function runs as a Seperate Worker Thread<br />
static int ProgressDlgThread(void* P){<br />
<br />
	ASSERT(P);<br />
	CProgressDlg* pDlg=(CProgressDlg*)P;<br />
	ASSERT(pDlg->IsKindOf(RUNTIME_CLASS(CProgressDlg)));<br />
<br />
	ASSERT(pDlg->m_pFnThreadProc);<br />
	pDlg->m_nDlgStatus=THREADSTATE_RUNNING;<br />
<br />
	//Fire the User Callback<br />
	pDlg->m_dwThreadResult=(pDlg->*pDlg->m_pFnThreadProc)();<br />
<br />
	// Done<br />
	pDlg->m_nDlgStatus=THREADSTATE_COMPLETED;<br />
	pDlg->EndDialog(pDlg->m_dwDlgResult);<br />
	return 0;<br />
<br />
<br />
}<br />
/////////////////////////////////////////////////////////////////////////////<br />
// CProgressDlg message handlers<br />
<br />
BOOL CProgressDlg::OnInitDialog() <br />
{<br />
	CDialog::OnInitDialog();<br />
<br />
	ASSERT(m_pFnThreadProc);<br />
	m_dwDlgResult=IDOK;<br />
<br />
	m_pWinThread=AfxBeginThread((AFX_THREADPROC)ProgressDlgThread,this);<br />
	<br />
	return TRUE;  // return TRUE unless you set the focus to a control<br />
	              // EXCEPTION: OCX Property Pages should return FALSE<br />
}<br />
<br />
// Function to be Called by Workerthread ONLY<br />
// to See if the Workerthread ShouldTerminate <br />
//<br />
// bShouldTerminate can ONLY be set by EndDialog(nResult)<br />
// m_dwDlgResult is <br />
BOOL CProgressDlg::ShouldTerminate(DWORD* pdwReason)<br />
{<br />
	BOOL bShouldTerminate;<br />
<br />
	EnterCriticalSection(&m_cs);<br />
		if(pdwReason)*pdwReason=m_dwDlgResult;<br />
		bShouldTerminate=m_bShouldTerminate;<br />
	LeaveCriticalSection(&m_cs);<br />
<br />
	return bShouldTerminate;<br />
}<br />
<br />
<br />
void CProgressDlg::OnCancel()<br />
{<br />
	EndDialog(IDCANCEL);<br />
}<br />
<br />
void CProgressDlg::OnOK()<br />
{<br />
	UpdateData();<br />
	EndDialog(IDOK);<br />
}<br />
BOOL CProgressDlg::UpdateData(BOOL bSaveAndValidate)<br />
{<br />
	ASSERT(m_hWnd);<br />
	BOOL bRes=TRUE;<br />
	::SendMessage(m_hWnd,WM_UPDATE_DATA,bSaveAndValidate,(DWORD)&bRes);<br />
	return bRes;<br />
}<br />
<br />
void CProgressDlg::_OnUpdateData(BOOL bSaveAndValidate,BOOL* pbRes)<br />
{<br />
	BOOL bRes=CDialog::UpdateData(bSaveAndValidate);<br />
	if(pbRes)*pbRes=bRes;<br />
}<br />
<br />
PFN_PROGRESS_DLG_THREADPROC CProgressDlg::SetWorkerThreadProcedure(PFN_PROGRESS_DLG_THREADPROC pFn)<br />
{<br />
	// Do not change horses halfway diown the race!<br />
	ASSERT(m_nDlgStatus==THREADSTATE_NOT_STARTED);<br />
<br />
	PFN_PROGRESS_DLG_THREADPROC pfnOld=m_pFnThreadProc;<br />
	m_pFnThreadProc=pFn;<br />
	return pfnOld;<br />
}<br />
<br />
<br />
//////////////////////////////////////////////<br />
// This Function may be called by Both Threads.<br />
void CProgressDlg::EndDialog(int ExitCode)<br />
{<br />
	// Called before OnInitDialog??<br />
	ASSERT(m_hWnd);<br />
<br />
	// If the thread is running, set the Termination Flag.<br />
	// The Users Thread Function's Response to 'ShouldTerminate' should terminate<br />
	// the thread by Calling EndDialog again, and returning from the WorkerThhead<br />
	// User Function.<br />
	EnterCriticalSection(&m_cs);<br />
	if(m_nDlgStatus==THREADSTATE_RUNNING){<br />
<br />
		m_dwDlgResult=ExitCode;<br />
		m_bShouldTerminate=TRUE;<br />
		LeaveCriticalSection(&m_cs);<br />
<br />
		return;		<br />
	}<br />
	LeaveCriticalSection(&m_cs);<br />
<br />
	ASSERT(m_dwDlgResult==ExitCode);<br />
<br />
	try{<br />
	::SendMessage(m_hWnd,WM_ENDDIALOG,m_dwDlgResult,0);<br />
	}<br />
	catch(...){<br />
		return;<br />
	}<br />
<br />
}<br />
////////////////////////////////////////////////<br />
// This is the Target of SendMsg(WM_ENDDIALOG)<br />
void CProgressDlg::_OnEndDialog(int ExitCode)<br />
{<br />
	try{<br />
	m_pWinThread;<br />
	m_dwDlgResult=ExitCode;<br />
	ASSERT(::IsWindow(m_hWnd));<br />
<br />
	if (m_nFlags & (WF_MODALLOOP|WF_CONTINUEMODAL))<br />
		EndModalLoop(ExitCode);<br />
<br />
	::EndDialog(m_hWnd, ExitCode);<br />
	}<br />
	catch(...){<br />
		return;<br />
	}<br />
<br />
}<br />
<br />
DWORD CProgressDlg::GetThreadResult()<br />
{<br />
	return m_dwThreadResult;<br />
}<br />
<br />


Now, all works well in my latest App, until I want to End the Dialog.

All goes well,
CProgressDlg::EndDialog(int ExitCode)
is called, SendMessage calls OnEndDialog(...), which terminates successfully, and then the App terminates with an Exception.

In case you ask, why not trace and debug, the App behaves as expected in Debug Mode, I get this behaviuor only in the Retail version.

I got this far by setting 'StillAlive' traps in the retail version, and do not know how to get further.

Regards,

Smile | :) Smile | :)
Bram van Kampen

AnswerRe: Failure in SendMessage in Retail Verrsion only, has me baffled. Pin
Stephen Hewitt8-Jun-10 18:18
Stephen Hewitt8-Jun-10 18:18 
GeneralRe: Failure in SendMessage in Retail Verrsion only, has me baffled. Pin
Bram van Kampen8-Jun-10 21:53
Bram van Kampen8-Jun-10 21:53 
AnswerRe: Failure in SendMessage in Retail Verrsion only, has me baffled. Pin
ThatsAlok8-Jun-10 19:06
ThatsAlok8-Jun-10 19:06 
GeneralRe: Failure in SendMessage in Retail Verrsion only, has me baffled. Pin
Stephen Hewitt8-Jun-10 19:50
Stephen Hewitt8-Jun-10 19:50 
GeneralRe: Failure in SendMessage in Retail Verrsion only, has me baffled. Pin
Bram van Kampen8-Jun-10 21:40
Bram van Kampen8-Jun-10 21:40 
AnswerRe: Failure in SendMessage in Retail Verrsion only, has me baffled. Pin
SandipG 8-Jun-10 20:04
SandipG 8-Jun-10 20:04 
GeneralRe: Failure in SendMessage in Retail Verrsion only, has me baffled. Pin
Bram van Kampen8-Jun-10 21:46
Bram van Kampen8-Jun-10 21:46 
GeneralRe: Failure in SendMessage in Retail Verrsion only, has me baffled. Pin
SandipG 8-Jun-10 22:03
SandipG 8-Jun-10 22:03 
GeneralRe: Failure in SendMessage in Retail Verrsion only, has me baffled. Pin
Kelly Herald9-Jun-10 7:03
Kelly Herald9-Jun-10 7:03 
AnswerRe: Failure in SendMessage in Retail Verrsion only, has me baffled.(SOLVED) Pin
Bram van Kampen9-Jun-10 10:38
Bram van Kampen9-Jun-10 10:38 
AnswerRe: Failure in SendMessage in Retail Verrsion only, has me baffled. Pin
Richard MacCutchan8-Jun-10 22:37
mveRichard MacCutchan8-Jun-10 22:37 
GeneralRe: Failure in SendMessage in Retail Verrsion only, has me baffled. Pin
Bram van Kampen9-Jun-10 10:34
Bram van Kampen9-Jun-10 10:34 
QuestionCalling a function from another Class [newbie question] Pin
Schehaider_Aymen8-Jun-10 9:46
Schehaider_Aymen8-Jun-10 9:46 
AnswerRe: Calling a function from another Class [newbie question] Pin
Aescleal8-Jun-10 10:36
Aescleal8-Jun-10 10:36 
AnswerRe: Calling a function from another Class [newbie question] Pin
Garth J Lancaster8-Jun-10 11:52
professionalGarth J Lancaster8-Jun-10 11:52 
GeneralRe: Calling a function from another Class [newbie question] Pin
Schehaider_Aymen8-Jun-10 21:24
Schehaider_Aymen8-Jun-10 21:24 
QuestionBlank lines to seperate methods Pin
Steven Solberg8-Jun-10 9:03
Steven Solberg8-Jun-10 9:03 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.