Attn: RONSLOW, mikeblas, chensu, other MFC gurus
Posted on 2000-02-24
This discussion goes back to a question about how to add items to a CComboBox. The crux of this is what is the acceptable method to get the pointer to a CComboBox (or other) MFC class in a window.
"Don't use GetDlgItem as it only returns a CWnd (ie not the appropriate class), so calling member functions may stuff up."
I don't know what "stuff up" means exactly but I gather it's a bad thing.
I contend that the following is a perfectly acceptable, legal C++/MFC, and safe way of getting the pointer to the CComboBox control in the dialog:
CComboBox *c = (CComboBox *)GetDlgItem(IDC_COMBO);
I contend that this is legal for ANY CWnd derived class in an MFC application. Not only have I always used this method and have NEVER once had a failure with it (except when using an invalid ID), I'll quote several references to support this:
1) MFC Docs. See CWnd::GetDlgItem where it gives the example:
pBoxOne = (CEdit*) GetDlgItem(IDC_EDIT1);
This code (or similar) is also littered throughout the MFC samples. There are too many to reference here.
2) Marshall Brain & Lance Lovett, "Visual C++ 2", Prentice Hall 1995, pg. 142:
"...GetDlgItem function is useful for converting the control's ID in the dialog into an actual CEdit pointer so you can call CEdit member functions"
3) Mike Blaszczak, "Professional MFC with Visual C++ 5", Wrox Press, 1997, pg. 223:
"...MFC implements a GetDlgItem() function of its own, as a member of the CWnd class. The MFC version of the function returns a pointer to a CWnd instead of a handle to a window. You can then CAST THIS CWnd POINTER TO A POINTER AT ANY CONTROL CLASS you'd like." (emphasis mine)
I could dig up more the this should be sufficient to backup my point that this is not only Microsoft recommended practice but a technique documented in books by leading MFC authors.
RONSLOW also takes exception to my bringing COM into this. I contend that COM works with what he calls "blindly casted" pointers for the same reason that MFC can do it. Namely that C++ maintains the vtbl order of functions for dervied classes. RONSLOW says:
"Your comparison to COM is like comparing apples to oragnges.
COM cast from a pointer-to-base-class (that is POINTING TO an object of the DERIVED class) to a pointer-to-derived. Quite legitimate as long as your "know" that the object being pointer to is of the correct type."
Like I said, COM works fine for the same reason that MFC CWnd derived classes work with a cast. The vtbl is compatible and you can cast a CWnd * to a CEdit *, CButton *, CComboBox *, etc... In COM all pointers are derived from IUnknown. Therefore you can cast an IUnknown * to an IDispatch *, etc.
Now I realize that there is more to COM that this, but it's an important point. For a given C++ compiler you can count on the structure of the member function order in the class binary object. It won't change unexpectedly and cause your application to "stuff up".
I've been doing it this way for a long time, but if I'm wrong (and others are as well) I'd like to understand why and also understand why my applications are NOT failing in the field due to this.
Again, RONSLOW says:
"Please .. listen and learn .. for your own sake and that of those you help here and elsewhere. It is BAD CODING. PERIOD."
Please control your urge to post an answer. Comments only. I'll award the
points to whoever offers the best explanation of why RONSLOW is right (and Brain, mikeblas, and Microsoft are wrong!) or why I'm OK on this and RONSLOW is overreacting.
Further, if the balance of opinion is that RONSLOW is correct, I'll also post another 200 pt question for him as a reward for being right.