Prev: How to let a CFrameWnd based SDI application start in full screen?
Next: update CDialog region in a user defined message handler
From: Giovanni Dicanio on 13 Jun 2010 13:48 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 13 Jun 2010 14:22 "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 13 Jun 2010 15:34 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 13 Jun 2010 15:58 >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 13 Jun 2010 22:26
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 |