DDX Assertion on Dialog Initialization
Rick Esterling -- rick@eco.twg.com Saturday, December 28, 1996 Environment: MSVC 4.2b Windows 95 I have a dialog based application. On it there is an edit control immediately followed in z-order by a spin control whose properties include UDS_AUTOBUDDY and UDS_SETBUDDYINT. The edit control has a ddx variable of type int associated with it. Also on the dialog is a Checkbox which *follows* the spin control in the z-order and this control has a ddx variable of type BOOL associated with it. I have an OnUpdate() handler member method for the edit control. The first thing this method does, naturally, is call UpdateData( TRUE ). Given the setup of the app, here's the sequence of events that occurs when the dialog is invoked: CDlg::CDlg // ddx variables are initialized CDlg::OnUpdateEdit1 // (then CDlg::OnChange if mapped) CDlg::DoDataExchange CDlg::OnInitDialog Just as a matter of clarification, OnUpdateEdit1 is being called here because of the UDS_SETBUDDYINT flag on the spin control. Without that flag, OnChangeEdit1 (and/or OnUpdateEdit1) are not called at this point. But, I'm using that flag so this is what I'm seeing. When OnUpdateEdit1 calls UpdateData( TRUE ) the first time through, the checkbox has not been created yet so dlgdata.cpp asserts at line 45 inside CDataExchange::PrepareCtrl: m_pDlgWnd->GetDlgItem(nIDC, &hWndCtrl); // Line 41 if (hWndCtrl == NULL) { TRACE1("Error: no data exchange control with ID 0x%04X.\n", nIDC); ASSERT(FALSE); AfxThrowNotSupportedException(); } The control ID it's referring to (nIDC) is the ID of the checkbox which, as I said, has not been created yet so the assertion makes sense. Nonetheless, it's an assertion that I'd like to get rid of. As a work around, I have added a member varible to the dialog class, m_bInitDone, that I set to FALSE in the dialog's constructor and then to TRUE in OnInitDialog. In OnChangeEdit1, I check this variable and if it's FALSE, I simply return before doing anything else; i.e., CDlg::OnChangeEdit1( ) { if( !m_bInitDone ) { return; } UpdateData( TRUE ); // etc., etc., etc. } BTW, if the checkbox (remember the checkbox?) precedes the edit/spin controls in the z-order, then, of course, the assertion doesn't always occur (see note) because the checkbox has already been created by the time OnChangeEdit1 -- and subsequently UpdateData( TRUE ) -- is called for the edit control. This, too, makes sense. Note: I say "doesn't always occur" because it still does occur the first time you run your app and will continue occurring as long as you select "Ignore" on the assertion messagebox and "OK" on the error dialog that follows the assertion. If you select "Abort" on the assertion messagebox, the assertion won't happen again until you reboot Win95 and run your app the first time again. The real point is if you want to see this assertion +consistently+, set the z-order as described in this message. My real question, then, is simply this: Is my work around appropriate? Is there a preferred method for handling this type of problem? Later, Rick "If you can't explain something to a six-year old, you really don't understand it yourself." -- Albert Einstein
Dan Kirby -- dkirby@accessone.com Saturday, December 28, 1996 Hi, Why are you calling UpdateData(TRUE) as a result of the EN_UPDATE or EN_CHANGE notifications? UpdateData() is basically designed for calling during an OnOK() situation where everthing is typed in and then user presses OK for example. The way you have it srtup now is that UpdateData will be called for every change in the edit control. So for every keystroke for example, this is being called, this is excessive and actually could be a bad thing if you have DDV routines. For example, if a DDV routine forced the user to be between 100 and 200 in the edit control and the user begins to type and presses a 1 for example, the UpdateData() is going to make the DDV routines kick in and of course you'll get a message about being out of a valid range. Basically, don't call UpdateData. If you need to know what the value is in the edit control at anytime before OnOK, you can call GetWindowText on the control. Or if you really need to transfer the data to the variable for every EN_UPDATE notification, then don't call UpdateData() but instead just call GetWindowText on the edit control and assign the value to the specific variable yourself. --dan ---------- > From: Rick Esterling> To: mfc-l@netcom.com > Subject: DDX Assertion on Dialog Initialization > Date: Saturday, December 28, 1996 1:41 PM > > Environment: MSVC 4.2b Windows 95 > > I have a dialog based application. On it there is an edit control > immediately followed in z-order by a spin control whose properties include > UDS_AUTOBUDDY and UDS_SETBUDDYINT. The edit control has a ddx variable of > type int associated with it. Also on the dialog is a Checkbox which > *follows* the spin control in the z-order and this control has a ddx > variable of type BOOL associated with it. > > I have an OnUpdate() handler member method for the edit control. The first > thing this method does, naturally, is call UpdateData( TRUE ). Given the > setup of the app, here's the sequence of events that occurs when the dialog > is invoked: > > CDlg::CDlg // ddx variables are initialized > CDlg::OnUpdateEdit1 // (then CDlg::OnChange if mapped) > CDlg::DoDataExchange > CDlg::OnInitDialog > > Just as a matter of clarification, OnUpdateEdit1 is being called here > because of the UDS_SETBUDDYINT flag on the spin control. Without that > flag, OnChangeEdit1 (and/or OnUpdateEdit1) are not called at this point. > But, I'm using that flag so this is what I'm seeing. > > When OnUpdateEdit1 calls UpdateData( TRUE ) the first time through, the > checkbox has not been created yet so dlgdata.cpp asserts at line 45 inside > CDataExchange::PrepareCtrl: > > m_pDlgWnd->GetDlgItem(nIDC, &hWndCtrl); // Line 41 > if (hWndCtrl == NULL) > { > TRACE1("Error: no data exchange control with ID 0x%04X.\n", nIDC); > ASSERT(FALSE); > AfxThrowNotSupportedException(); > } > > The control ID it's referring to (nIDC) is the ID of the checkbox which, as > I said, has not been created yet so the assertion makes sense. > Nonetheless, it's an assertion that I'd like to get rid of. > > As a work around, I have added a member varible to the dialog class, > m_bInitDone, that I set to FALSE in the dialog's constructor and then to > TRUE in OnInitDialog. In OnChangeEdit1, I check this variable and if it's > FALSE, I simply return before doing anything else; i.e., > > CDlg::OnChangeEdit1( ) { > if( !m_bInitDone ) { > return; > } > > UpdateData( TRUE ); > // etc., etc., etc. > } > > BTW, if the checkbox (remember the checkbox?) precedes the edit/spin > controls in the z-order, then, of course, the assertion doesn't always > occur (see note) because the checkbox has already been created by the time > OnChangeEdit1 -- and subsequently UpdateData( TRUE ) -- is called for the > edit control. This, too, makes sense. > > Note: I say "doesn't always occur" because it still does occur the first > time you run your app and will continue occurring as long as you select > "Ignore" on the assertion messagebox and "OK" on the error dialog that > follows the assertion. If you select "Abort" on the assertion messagebox, > the assertion won't happen again until you reboot Win95 and run your app > the first time again. The real point is if you want to see this assertion > +consistently+, set the z-order as described in this message. > > My real question, then, is simply this: Is my work around appropriate? Is > there a preferred method for handling this type of problem? > > Later, > Rick > > "If you can't explain something to a six-year old, you really don't > understand it yourself." -- Albert Einstein >
Rick Esterling -- rick@eco.twg.com Monday, December 30, 1996 Dan Kirby wrote: > Basically, don't call UpdateData. If you need to know what the value > is in the edit control at anytime before OnOK, you can call > GetWindowText on the control. Appreciate the recommendation, Dan, it helped streamline the design of my application. The original problem, however, remains even though I'm no longer calling UpdateData() anywhere in my project. Let me start from scratch so any newcomers to this conversation can join in. VC 4.2b, Win95 Dialog-based app (AppWiz generated) Use the resource editor to add an edit control and a spin control to the dialog. Modify the properties of the spin control such that "Auto Buddy" and "Set Buddy Integer" are set. Ensure the spin control follows the edit control in the z-order so it will, in fact, be a "buddy" control. Use class wizard to create a control ddx variable for the edit control (type CEdit, of course). I'll call this variable "m_edtOne". Use class wizard to map EN_CHANGE for the edit control to the dialog; i.e., CDlg::OnChangeEdit1. Modify the message handler as follows: void CDlg::OnChangeEdit1( ) { CString strText; m_edtOne.GetWindowText( strText ); } Launch the app. The code shown above will fire before the edit control has been created. This causes an assertion in wincore.cpp at line 1012. That code reads as follows: void CWnd::GetWindowText(CString& rString) const { ASSERT(::IsWindow(m_hWnd)); // Line 1012 // etc. } The order in which my dialog class' member methods are being called is as follows: CDlg::CDlg CDlg::OnChangeEdit1 CDlg::OnInitDialog CDlg::DoDataExchange Clearing the UDS_SETBUDDYINT flag from the spin control makes this problem go away; OnChangeEdit1 does not get called during creation as shown above. One more oddity. On the assertion messagebox that shows up to report this problem, there are three buttons: Abort, Retry, and Ignore. If I click Abort, my app closes after which I can run it over and over again without ever seeing the assertion recurring until I reboot Win95 and run the app again. If, on the other hand, I press Ignore, the app continues but I'll get the assertion everytime I start the app over (and will keep asserting as long as I click Ignore everytime and not Abort). I add this because if you're trying to debug this problem and you hit abort on the assertion messagebox, you won't see the assertion again until you reboot. Alternatively, you can run the first instance of the application and simply leave the assertion box on the screen. Fire up another instance of the app and it won't assert. You can do this as many times as you want until you dismiss the assertion messagebox from the first instance of the app, and then the same rules outlined above are back in effect (if you press Abort, no more problems for the duration of your Win95 session, if you press ignore, problem keeps happening.) That, at least, is what's happening here. The assertion itself is easy enough to avoid altogether by adding a class variable, BOOL m_bInit, that gets set to FALSE in the contructor and TRUE in OnInitDialog. In OnChangeEdit1, check m_bInit == TRUE before calling GetWindowText. While this is effective for avoiding the assertion, I would rather understand what's really going on and what other alternatives I have for eliminating the assertion. If anyone has a better understanding of this whole subject and the root cause of this particular problem, I'd appreciate their enlightement. Later, Rick
P.J. Tezza -- pj@exemplarsoftware.com Tuesday, December 31, 1996 >The assertion itself is easy enough to avoid altogether by adding a = class variable, BOOL m_bInit, that gets set to FALSE in the contructor and = TRUE in OnInitDialog. In OnChangeEdit1, check m_bInit =3D=3D TRUE before = calling GetWindowText. While this is effective for avoiding the assertion, I = would rather understand what's really going on and what other alternatives I = have for eliminating the assertion. If anyone has a better understanding of this whole subject and the root cause of this particular problem, I'd appreciate their enlightement. It sounds like you found a bug (feature?). Grep for WINBUG in the MFC = source code to see how MFC deals with these kinds of problems. A = possible workaround is to test the validity of m_edtOne.m_hWnd before = calling UpdateData and/or m_edtOne.GetWindowText. PJ pj@exemplarsoftware.com
Ronald D. Patton -- rpatton@sky.net Wednesday, January 01, 1997 Rick, Try this: if (::IsWindow(m_edtOne.m_hWnd)) m_edtOne.GetWindowText( strText ); instead of just: m_edtOne.GetWindowText( strText ); Ron Patton Informix Software ---------- > From: Rick Esterling> To: mfc-l@netcom.com > Subject: Re: DDX Assertion on Dialog Initialization > Date: Monday, December 30, 1996 11:13 PM > > Dan Kirby wrote: > > > Basically, don't call UpdateData. If you need to know what the value > > is in the edit control at anytime before OnOK, you can call > > GetWindowText on the control. > > Appreciate the recommendation, Dan, it helped streamline the design of my > application. The original problem, however, remains even though I'm no > longer calling UpdateData() anywhere in my project. Let me start from > scratch so any newcomers to this conversation can join in. > > VC 4.2b, Win95 > Dialog-based app (AppWiz generated) > > Use the resource editor to add an edit control and a spin control to the > dialog. Modify the properties of the spin control such that "Auto Buddy" > and "Set Buddy Integer" are set. Ensure the spin control follows the edit > control in the z-order so it will, in fact, be a "buddy" control. > > Use class wizard to create a control ddx variable for the edit control > (type CEdit, of course). I'll call this variable "m_edtOne". Use class > wizard to map EN_CHANGE for the edit control to the dialog; i.e., > CDlg::OnChangeEdit1. Modify the message handler as follows: > > void CDlg::OnChangeEdit1( ) { > CString strText; > m_edtOne.GetWindowText( strText ); > } > > Launch the app. The code shown above will fire before the edit control has > been created. This causes an assertion in wincore.cpp at line 1012. That > code reads as follows: > > void CWnd::GetWindowText(CString& rString) const > { > ASSERT(::IsWindow(m_hWnd)); // Line 1012 > // etc. > } > > The order in which my dialog class' member methods are being called is as > follows: > > CDlg::CDlg > CDlg::OnChangeEdit1 > CDlg::OnInitDialog > CDlg::DoDataExchange > > Clearing the UDS_SETBUDDYINT flag from the spin control makes this problem > go away; OnChangeEdit1 does not get called during creation as shown above. > > One more oddity. On the assertion messagebox that shows up to report this > problem, there are three buttons: Abort, Retry, and Ignore. If I click > Abort, my app closes after which I can run it over and over again without > ever seeing the assertion recurring until I reboot Win95 and run the app > again. If, on the other hand, I press Ignore, the app continues but I'll > get the assertion everytime I start the app over (and will keep asserting > as long as I click Ignore everytime and not Abort). I add this because if > you're trying to debug this problem and you hit abort on the assertion > messagebox, you won't see the assertion again until you reboot. > Alternatively, you can run the first instance of the application and simply > leave the assertion box on the screen. Fire up another instance of the app > and it won't assert. You can do this as many times as you want until you > dismiss the assertion messagebox from the first instance of the app, and > then the same rules outlined above are back in effect (if you press Abort, > no more problems for the duration of your Win95 session, if you press > ignore, problem keeps happening.) That, at least, is what's happening > here. > > The assertion itself is easy enough to avoid altogether by adding a class > variable, BOOL m_bInit, that gets set to FALSE in the contructor and TRUE > in OnInitDialog. In OnChangeEdit1, check m_bInit == TRUE before calling > GetWindowText. While this is effective for avoiding the assertion, I would > rather understand what's really going on and what other alternatives I have > for eliminating the assertion. If anyone has a better understanding of > this whole subject and the root cause of this particular problem, I'd > appreciate their enlightement. > > Later, > Rick
Mike Blaszczak -- mikeblas@nwlink.com Wednesday, January 01, 1997 At 21:13 12/30/96 -0800, Rick Esterling wrote: >The original problem, however, remains even though I'm no >longer calling UpdateData() anywhere in my project. Calling UpdateData() isn't the cause of your problem. UpdateData() ends up calling DoDataExchange(). If you're calling UpdateData(FALSE), DoDataExchange() does two things: + it copies and validates data from controls involved in DDX and DDV. + it subclasses controls that you've set up for DDX_Control(). That means that the control member variable in your dialog class isn't initialized until UpdateData() has been called at least once. MFC's implementation of CDialog::OnInitDialog() calls UpdateData() for you, so after your dialog is initialized, it is done. I don't have 4.2b installed at home (I do, but my laptop is charging) but the code is someplace around line 650 of DLGCORE.CPP. >Use the resource editor to add an edit control and a spin control to the >dialog. Modify the properties of the spin control such that "Auto Buddy" >and "Set Buddy Integer" are set. Ensure the spin control follows the edit >control in the z-order so it will, in fact, be a "buddy" control. > >Use class wizard to create a control ddx variable for the edit control >(type CEdit, of course). I'll call this variable "m_edtOne". Use class >wizard to map EN_CHANGE for the edit control to the dialog; i.e., >CDlg::OnChangeEdit1. Modify the message handler as follows: So, the reason you're noticing these symptoms is because the order of events is out of your control. What happens is that: You call yourDialog.DoModal() to create the box. MFC asks Windows to create the box from the template MFC creates the template The newly created up/down control sees that it is autobuddy, so: it buddies with its edit control The newly buddied control sees that it has the "set buddy integer" style, so: it sets its buddy's integer The edit control has been changed, so it fires the changed notification Your CDlg::OnChangeEdit() function gets called Since your implementation of this function: > void CDlg::OnChangeEdit1( ) { > CString strText; > m_edtOne.GetWindowText( strText ); > } tries to play with m_edtOne, which hasn't yet been initialized, you get the assertion. There's nothing MFC can do about this; Windows is behaving as designed, and MFC can't be modified to account for that behaviour without risking the demise of other applications that expect the control not to be subclassed (or the DDX variables to be stuffed) until after CDialog::OnInitDialog() is called. >The assertion itself is easy enough to avoid altogether by adding a class >variable, BOOL m_bInit, that gets set to FALSE in the contructor and TRUE >in OnInitDialog. Right. > ... oddity ... I can't reproduce the problem you're having with not being able to repeat the problem after abort. I'm using Windows 95 and a different version of Visual C++ and MFC, though. >While this is effective for avoiding the assertion, I would >rather understand what's really going on and what other alternatives I have >for eliminating the assertion. You don't say what you're doing in your OnChangeEdit1() function, but if you really need this first change notification, you could call UpdateData(FALSE) if !m_bInitalized. That is, something like: void CDlg::OnChangeEdit() { if (!m_bInitialized) UpdateData(FALSE); CString strText; m_edtOne.GetWindowText(strText); } so you can get your m_edtOne member initialized before you use it but after the edit control gets stuffed by its buddy. .B ekiM http://www.nwlink.com/~mikeblas/ I'm afraid I've become some sort of speed freak. These words are my own. I do not speak on behalf of Microsoft.
P. Senthil -- senthilp@geocities.com Thursday, January 02, 1997 Rick Esterling wrote: > Dan Kirby wrote: > > > Basically, don't call UpdateData. If you need to know what the value > > is in the edit control at anytime before OnOK, you can call > > GetWindowText on the control. > > Appreciate the recommendation, Dan, it helped streamline the design of my > application. The original problem, however, remains even though I'm no > longer calling UpdateData() anywhere in my project. Let me start from > scratch so any newcomers to this conversation can join in. > > VC 4.2b, Win95 > Dialog-based app (AppWiz generated) > > Use the resource editor to add an edit control and a spin control to the > dialog. Modify the properties of the spin control such that "Auto Buddy" > and "Set Buddy Integer" are set. Ensure the spin control follows the edit > control in the z-order so it will, in fact, be a "buddy" control. > > Use class wizard to create a control ddx variable for the edit control > (type CEdit, of course). I'll call this variable "m_edtOne". Use class > wizard to map EN_CHANGE for the edit control to the dialog; i.e., > CDlg::OnChangeEdit1. Modify the message handler as follows: > > void CDlg::OnChangeEdit1( ) { > CString strText; > m_edtOne.GetWindowText( strText ); > } > > Launch the app. The code shown above will fire before the edit control has > been created. This causes an assertion in wincore.cpp at line 1012. That > code reads as follows: > > void CWnd::GetWindowText(CString& rString) const > { > ASSERT(::IsWindow(m_hWnd)); // Line 1012 > // etc. > } > > The order in which my dialog class' member methods are being called is as > follows: > > CDlg::CDlg > CDlg::OnChangeEdit1 > CDlg::OnInitDialog > CDlg::DoDataExchange > > Clearing the UDS_SETBUDDYINT flag from the spin control makes this problem > go away; OnChangeEdit1 does not get called during creation as shown above. > > One more oddity. On the assertion messagebox that shows up to report this > problem, there are three buttons: Abort, Retry, and Ignore. If I click > Abort, my app closes after which I can run it over and over again without > ever seeing the assertion recurring until I reboot Win95 and run the app > again. If, on the other hand, I press Ignore, the app continues but I'll > get the assertion everytime I start the app over (and will keep asserting > as long as I click Ignore everytime and not Abort). I add this because if > you're trying to debug this problem and you hit abort on the assertion > messagebox, you won't see the assertion again until you reboot. > Alternatively, you can run the first instance of the application and simply > leave the assertion box on the screen. Fire up another instance of the app > and it won't assert. You can do this as many times as you want until you > dismiss the assertion messagebox from the first instance of the app, and > then the same rules outlined above are back in effect (if you press Abort, > no more problems for the duration of your Win95 session, if you press > ignore, problem keeps happening.) That, at least, is what's happening > here. > > The assertion itself is easy enough to avoid altogether by adding a class > variable, BOOL m_bInit, that gets set to FALSE in the contructor and TRUE > in OnInitDialog. In OnChangeEdit1, check m_bInit == TRUE before calling > GetWindowText. While this is effective for avoiding the assertion, I would > rather understand what's really going on and what other alternatives I have > for eliminating the assertion. If anyone has a better understanding of > this whole subject and the root cause of this particular problem, I'd > appreciate their enlightement. > > Later, > Rick I did what you said and yes there was an assertion as you said. The calling of OnChangeEdit1 for the Edit control in the case of a buddy with Auto buddy set seems to be the design of Win 32, which MFC redirects to the control. But it appears that the problem is actually with MFC DDX/DDV framework. If the line m_edtOne.GetWindowText( strText ); is replaced with GetDlgItem(IDC_EDIT1)->GetWindowText(strText); then it works fine. The variable m_edtOne is associated with the edit control (valid m_hWnd) only when DoDataExchange is called. This occurs only after OnInitDialog is processed. So I guess it is a bug with MFC. PS: I've tried it with MSVC 4.0 only.
Mike Blaszczak -- mikeblas@nwlink.com Thursday, January 02, 1997 At 21:10 1/2/97 +0530, P. Senthil wrote: >The variable m_edtOne is associated with the edit control (valid m_hWnd) >only when DoDataExchange is called. This occurs only after OnInitDialog >is processed. >So I guess it is a bug with MFC. I'm afraid your guess is incorrect.
sunil Kumar -- suniln@geocities.com Friday, January 03, 1997 Mike Blaszczak wrote: > There's nothing MFC can do about this; Windows is behaving as designed, MFC was designed long before Windows came up with this Buddy stuff. So, by way of design of MFC this Windows feature could not (could be for a variety of reasons) be incorporated in MFC. But telling that MFC can do nothing about this is going too far. > and MFC can't be modified to account for that behaviour without risking > the demise of other applications that expect the control not to be subclassed > (or the DDX variables to be stuffed) until after CDialog::OnInitDialog() is > called. I can't understand why applications would want the control to be subclassed ~only~ after OnInitDialog() is called. I don't think current applications would be affected if the control was actually subclassed before OnInitDialog. > You don't say what you're doing in your OnChangeEdit1() function, but if > you really need this first change notification, you could call UpdateData(FALSE) > if !m_bInitalized. That is, something like: > > void CDlg::OnChangeEdit() > { > if (!m_bInitialized) > UpdateData(FALSE); > CString strText; > m_edtOne.GetWindowText(strText); > } > Is this good programming? What about the overhead of time? P. Senthil mail : senthilp@geocities.com www : www.geocities.com/SiliconValley/Heights/6504
Mike Blaszczak -- mikeblas@nwlink.com Friday, January 03, 1997 At 19:46 1/3/97 +0530, sunil Kumar wrote: >Mike Blaszczak wrote: >> There's nothing MFC can do about this; Windows is behaving as designed, > >MFC was designed long before Windows came up with this Buddy stuff. So, >by way of design of MFC this Windows feature could not (could be for a >variety of reasons) be incorporated in MFC. But telling that MFC can do >nothing about this is going too far. Really? What solution would you suggest? .B ekiM http://www.nwlink.com/~mikeblas/ I'm afraid I've become some sort of speed freak. These words are my own. I do not speak on behalf of Microsoft.
Mike Blaszczak -- mikeblas@nwlink.com Saturday, January 04, 1997 At 09:37 1/3/97 +0300, Alexander Grigoriev wrote: >It is dangerous to call UpdateData() here, because the EN_CHANGE >notification is sent _before_ OnInitDialog() is called, thus some class >data may not be properly initialized yet. The only data that won't be initialized is whatever you've decided to set up for yourself in your OnInitDialog() handler. If you add this code to your OnChangeEdit(), you're doing so because you know you need it (as I said: >> You don't say what you're doing in your OnChangeEdit1() function, but if >> you really need this first change notification, you could call >> UpdateData(FALSE) if !m_bInitalized. ). CDialog itself is ready to be used by this time. If you need to do intialization in your OnInitDialog() that you'll depend on for your first call to DoDataExchange(), you're right--the UpdateData() call is better off not being made from OnChangeEdit(). But I wouldn't categorize this as "dangerous"; it's no more dangerous than any other code you'll write yourself--you need to know the order in which functions are called and what do to in reponse to them so that you can handle dependencies you've created yourself. This is, though, why I say that it is inappropriate for MFC to change the order of calls: that _would_ be fatally dangerous. If MFC forced a call to DoDataExchange() before OnInitDialog(), many programs would break. (MFC would have to jump through some funny hoops to get the call to happen, anyway; both the EN_CHANGED notification and the WM_INITDIALOG messages are sent, and they are fired before MFC's call to CreateDialogIndirect() returns, so MFC would have to actually subclass the dialog in order to make the early OnInitDialog() call.) I don't see a reasonable way around that problem, and I don't think it would be a safe change, anyway, and thus I'm eager to hear back from Sunil Kumar (or was it actually P. Senthil?--the signature didn't match the message header) about why it's going "too far" to say that MFC can't reasonably do something about the rare situation the original poster was experiencing. Letting the developer decide to handle things in their own special way is fine, but for me to change the way MFC works in this area would simply be irresponsible. .B ekiM http://www.nwlink.com/~mikeblas/ I'm afraid I've become some sort of speed freak. These words are my own. I do not speak on behalf of Microsoft.
P. Senthil -- senthilp@geocities.com Sunday, January 05, 1997 Mike Blaszczak wrote: > > This is, though, why I say that it is inappropriate for MFC to change > the order of calls: that _would_ be fatally dangerous. If MFC forced > a call to DoDataExchange() before OnInitDialog(), many programs would > break. (MFC would have to jump through some funny hoops to get the > call to happen, anyway; both the EN_CHANGED notification and the > WM_INITDIALOG messages are sent, and they are fired before MFC's > call to CreateDialogIndirect() returns, so MFC would have to actually > subclass the dialog in order to make the early OnInitDialog() call.) > > I don't see a reasonable way around that problem, and I don't think > it would be a safe change, anyway, and thus I'm eager to hear back from > Sunil Kumar (or was it actually P. Senthil?--the signature didn't match > the message header) about why it's going "too far" to say that MFC can't > reasonably do something about the rare situation the original poster was > experiencing. > I give up. I can't see of any possible workaround in the MFC source. I was bothered about subclassing the edit control with the autobuddy property set only (which happens in the DoDataExchange) and not the entire OnInitDialog process. This can't be done the first time the OnChangeEdit is called. I guess "Letting the developer decide to handle things in their own special way is fine". PS: It was me. I sent it from my friends machine. P. Senthil ----------------------------------------------------------------------- 1, 7th Avenue (West), 7th Main Road, Dhandeeswaram Nagar, Velachery, MADRAS - 600 042. Mail: senthilp@geocities.com Homepage: www.geocities.com/SiliconValley/Heights/6504
| Вернуться в корень Архива |