From: Giovanni Dicanio on
On 13/06/2010 15:47, RB wrote:

> void CFileHandlingApp::OnAppAbout()
> {
> CAboutDlg aboutDlg;
> CString s;
> s.Format( _T(" version %d.%d.%d.%d"), VERMAJ, VERMIN, VERFIX, BUILDNUMBER );
> aboutDlg.m_CtrlStaticVer.SetWindowText(s); //gets a Debug Assertion Failed
> aboutDlg.DoModal();

You may want to add a method to your CAboutDlg class like
SetVersionString(LPCTSTR pszVersion) and a data member of type CString
(e.g. CString m_strVersion).
This new method should set the version string, storing it into the
proper data member.

Then, CAboutDlg::OnInitDialog would get this string and .SetWindowText()
it in the proper static control.

e.g.:

class CAboutDlg
{
...
public:
void SetVersionString(LPCTSTR pszVersion)
{
m_strVersion = pszVersion;
}

....

private:
CString m_strVersion;
};

In CAboudDlg::OnInitDialog() do:

m_CtrlStaticVer.SetWindowText(m_strVersion);


Giovanni
From: David Webber on


"RB" <NoMail(a)NoSpam> wrote in message
news:u1Z9q7vCLHA.4388(a)TK2MSFTNGP04.phx.gbl...

> Yea, I was using another format function but having problems with an
> assertion, so I tried your CString method. But I am still getting the
> assertion, I must not be calling it correctly. I first tried it in the
> dialog constructor, and got the assertion.
> So then I tried it in the handler that calls the dialog, but got
> the same assertion. I am foo barring somewhere.

In MFC there are two concepts: the Window with its HWND (looked after by
Windows), and the class (derived from CWnd, in this case CDialog) which
wraps the Window (looked after by MFC).

When you construct your class, it is not attached to a Window, so it doesn't
know about the controls, which are yet to become Windows. So you can't
touch them.

When you invoke DoModal() the window is attached to the class, and it gives
you a chance to initialise anything you need when it calls OnInitDialog().
That is where you can set the text in static controls.

Looked at from outside from an object oriented programming point of view,
this structure is a complete mess. But when MFC was invented I don't think
anyone at Microsoft had heard of object oriented programming. (Otherwise
why do you have to create the view of the document before you create the
document?) From the point of view of creating a thin wrapper round the
Windows API, it makes more sense. And in those days people who knew the
Windows API could learn MFC quite quickly, just because it was a thin
wrapper. But nowadays who writes programs in C using the Windows API?

[I suppose .NET was a bid to escape the historical quirks of MFC, but those
of us with lots of legacy MFC code we're still developing have grown to know
and, well not exactly love but coexist with, the vagaries of MFC's
structure.]

Dave

--
David Webber
Mozart Music Software
http://www.mozart.co.uk
For discussion and support see
http://www.mozart.co.uk/mozartists/mailinglist.htm



From: RB on
Thanks Giovanni, worked like a charm, though I changed the
SetVersionString function to no args. I have a couple of
questions if you would be so kind. See code and comments
below. Questions are at very bottom in the OnInitDialog.

#include .....others.....
#include "AppVer.h" // has version string data thanks
// to David Webber

/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
private:
CString m_strVersion;
public:
void SetVersionString( );
CAboutDlg( );

// Dialog Data
//{{AFX_DATA(CAboutDlg)
enum { IDD = IDD_ABOUTBOX };
CStatic m_CtrlStaticCr;
CStatic m_CtrlStaticVer;
//}}AFX_DATA

// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CAboutDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX);
//}}AFX_VIRTUAL

// Implementation
protected: /// ** used the class wizard to add suggested
// OnInitDialog handler ** //
//{{AFX_MSG(CAboutDlg)
virtual BOOL OnInitDialog( );
//}}AFX_MSG
DECLARE_MESSAGE_MAP( )
};
/// ** suggested SetVersion function, but no args ** //
void CAboutDlg::SetVersionString( )
{
m_strVersion.Format( _T(" version %d.%d.%d.%d"),
VERMAJ, VERMIN, VERFIX, BUILDNUMBER );
}

----constructor, nothing happening here

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAboutDlg)
DDX_Control(pDX, IDC_STATICcr, m_CtrlStaticCr);
DDX_Control(pDX, IDC_STATICver, m_CtrlStaticVer);
//}}AFX_DATA_MAP
}

...........message map stuff ..........
.............

//// handler that runs the dialog
//
void CFileHandlingApp::OnAppAbout( )
{
CAboutDlg aboutDlg;
aboutDlg.DoModal( );
}

/////////////////////////////////////////////////////////////////////////////
// CFileHandlingApp message handlers

BOOL CAboutDlg::OnInitDialog( )
{ //** Class Wizard added base call ** //
CDialog::OnInitDialog( );

//** being added code //
SetVersionString( ); // format the CString
HWND hDlg = m_CtrlStaticVer.GetSafeHwnd( );

//** Question 1.
//** here I used the API SetWindowText to get a return, the
// MFC SetWindowText was a void return, Is this a big deal ?

BOOL bResult = ::SetWindowText(hDlg, m_strVersion);

//**Question 2
//** Class Wizard put below return in ? when I had planned to return the
//** the result of the SetWindow, Can you explain what this is all about ?

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


From: RB on
>When you invoke DoModal( ) the window is attached to the class, and it gives you a chance to initialise anything you need when it
>calls OnInitDialog(). That is where you can set the text in static controls.

You know I had a gut feeling that it was the window was not yet
created or something like that, but I am just too inexperienced to
know what to do about it. Giovanni also suggested to me the
OnInitDialog and a SetString function that worked out great.
It would seem to me that MFC would have generated an empty
OnInitDialog handler from the start to give a hint to clueless newbs
like me, but I guess that might be asking too much. However I do
see other functions created just as said with //TODO: comments//
in the Doc/View structure.
In any case THANKS to you for all of this, it has solved my
version dilemma in a functional way that I am very pleased with.
RB



From: Joseph M. Newcomer on
Serious error: see below...
On Sun, 13 Jun 2010 09:47:05 -0400, "RB" <NoMail(a)NoSpam> wrote:

>
>Yea, I was using another format function but having problems with an
>assertion, so I tried your CString method. But I am still getting the
>assertion, I must not be calling it correctly. I first tried it in the
>dialog constructor, and got the assertion.
> So then I tried it in the handler that calls the dialog, but got
>the same assertion. I am foo barring somewhere.
>Code below.
>
>//// CAboutDlg dialog used for App About
>//
>class CAboutDlg : public CDialog
>{
>public:
> CAboutDlg();
>// Dialog Data
> //{{AFX_DATA(CAboutDlg)
> enum { IDD = IDD_ABOUTBOX };
> CStatic m_CtrlStaticCr;
> CStatic m_CtrlStaticVer;
> //}}AFX_DATA
>//............
>}
>
>//// DDX Stuff
>//
>void CAboutDlg::DoDataExchange(CDataExchange* pDX)
>{
> CDialog::DoDataExchange(pDX);
> //{{AFX_DATA_MAP(CAboutDlg)
> DDX_Control(pDX, IDC_STATICcr, m_CtrlStaticCr);
> DDX_Control(pDX, IDC_STATICver, m_CtrlStaticVer);
> //}}AFX_DATA_MAP
>}
>
>//// handler that runs the dialog
>//
>void CFileHandlingApp::OnAppAbout()
>{
> CAboutDlg aboutDlg;
> CString s;
> s.Format( _T(" version %d.%d.%d.%d"), VERMAJ, VERMIN, VERFIX, BUILDNUMBER );
> aboutDlg.m_CtrlStaticVer.SetWindowText(s); //gets a Debug Assertion Failed
****
This is incorrect code. You must put this in the OnInitDialog handler of the dialog.

The assertion failure, if you looked at it, said the window does not exist. Big surprise.
The window does not exist! In fact, the window does not exist until the OnInitDialog
handler is invoked in the context of the dialog.

As a general rule, you should NEVER touch a control variable of a dialog from outside the
dialog. In fact, it is a serious design error in the MFC framework that defaults control
variables to public and declares handlers as public methods. This design error was
induced by the incredibly bad ClassWizard of VS<=6, which couldn't parse the header files
because it had an /ad hoc/ parser. When VS.NET delivered an intelligent parsers, they
forgot to change the behavior to make sense. It *never* makes sense to declare a control
variable or handler as public, and the default should be 'protected'.

You violate that rule here by attempting to manipulate a control variable from outside the
dialog. The control variable is not bound to a control until INSIDE the OnInitDialog
handler (in fact, it is bound when the CDialog::OnInitDialog call invokes the
DoDataExchange method of the dialog class). Since the code you show here takes place long
before OnInitDialog, there is no possible way the variable could be bound to a control. In
fact, the control doesn't even exist at the point you are trying to manipulate it.
joe

> aboutDlg.DoModal();
>}
>
Joseph M. Newcomer [MVP]
email: newcomer(a)flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm