Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

GetDlgItem : Is dynamic casting possible?

857 views
Skip to first unread message

rushm...@my-dejanews.com

unread,
Mar 5, 1999, 3:00:00 AM3/5/99
to
This is my problem:

CWnd * pWnd = GetDlgItem(IDD_EDIT1);

Can I determine the type of control returned? i.e. Is pWnd a CComboBox, a
CEdit...

Thank you in advance,
Jean-Simon Bolduc
CML Technologies Inc.

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/ Search, Read, Discuss, or Start Your Own

Jon Sturgeon

unread,
Mar 5, 1999, 3:00:00 AM3/5/99
to
On Fri, 05 Mar 1999 20:39:42 GMT, rushm...@my-dejanews.com wrote:

>This is my problem:
>
>CWnd * pWnd = GetDlgItem(IDD_EDIT1);
>
>Can I determine the type of control returned? i.e. Is pWnd a CComboBox, a
>CEdit...

Nope, it is a CWnd. The C++ object returned is *not* a CEdit, CComboBox or
anything else. The actual control is, but the C++ object is not. What
you're almost certainly better off doing is avoiding GetDlgItem()
altogether and creating a member variable of the required class (ie
CButton, CComboBox etc) and using DDX_Control() to associate the C++ object
with the actual control. Then you will have the correct type of object.

ClassWizard can do this for you:

* Run ClassWizard
* Select the "Member Variables" property page
* Select your project and dialog class from the two drop-down listboxes
* Select the ID of the control you're interested in from the list
* Click "Add Variable"
* Give it a name, eg m_UserNameEditCtrl
* Change category from "Value" to "Control"
* Click OK
* Marvel about how much easier and cleaner it is than using GetDlgItem()
with nasty and error-prone casts throughout your code.

btw, there was an article in MSJ about this a couple of months ago, perhaps
somebody else can remember which month and page etc.

Hope this helps,
Regards,
Jon Sturgeon
Jo...@futuresoft.com

Gordon Smith

unread,
Mar 5, 1999, 3:00:00 AM3/5/99
to
In article <7bpfed$aon$1...@nnrp1.dejanews.com>, rushmaniac@my-
dejanews.com writes

>CWnd * pWnd = GetDlgItem(IDD_EDIT1);
>
>Can I determine the type of control returned? i.e. Is pWnd a CComboBox, a
>CEdit...

I think that, if you look at the MFC hierarchy, you'll find that CWnd is
and ancestor of CEdit, etc.

Didn't you choose what IDD_EDIT1 was when you created the dialog and
therefore can't you cast it as such in the code? For example,

CEdit* pEditWnd = (CEdit*)GetDlgItem(IDD_EDIT1);

---
Gordon Smith

If you feel it's necesary to e-mail me directly my address should be:

gordon at gordys dot demon dot co dot uk

Scott McPhillips

unread,
Mar 5, 1999, 3:00:00 AM3/5/99
to
Jon Sturgeon wrote:
>
> On Fri, 05 Mar 1999 20:39:42 GMT, rushm...@my-dejanews.com wrote:
>
> >This is my problem:
> >
> >CWnd * pWnd = GetDlgItem(IDD_EDIT1);
> >
> >Can I determine the type of control returned? i.e. Is pWnd a CComboBox, a
> >CEdit...
>
> Nope, it is a CWnd. The C++ object returned is *not* a CEdit, CComboBox or
> anything else. The actual control is, but the C++ object is not. What
> you're almost certainly better off doing is avoiding GetDlgItem()
> altogether and creating a member variable of the required class (ie
> CButton, CComboBox etc) and using DDX_Control() to associate the C++ object
> with the actual control. Then you will have the correct type of object.
>

Well, I agree with everything in Jon's answer except "Nope"

GetClassName(pWnd->m_hWnd,...);

will return the window class name, which is a documented string ("COMBOBOX", "EDIT", etc.) for all the standard controls.

David McCabe

unread,
Mar 6, 1999, 3:00:00 AM3/6/99
to
Jon Sturgeon wrote:
> On Fri, 05 Mar 1999 20:39:42 GMT, rushm...@my-dejanews.com wrote:
> >CWnd * pWnd = GetDlgItem(IDD_EDIT1);
> >
> >Can I determine the type of control returned? i.e. Is pWnd a CComboBox, a
> >CEdit...
>
> Nope, it is a CWnd. The C++ object returned is *not* a CEdit, CComboBox or
> anything else. The actual control is, but the C++ object is not.

The returned object is a CWnd pointer, but it can be safely cast to CEdit*,
CComboBox* or whatever since those classes have no additional data members.
You can therefore do

CEdit *pEdit = (CEdit *)GetDlgItem(IDD_EDIT1);

without fear.
--
Dave
david....@balliol.oxford.ac.uk
http://users.ox.ac.uk/~ball0597/

Jon Sturgeon

unread,
Mar 8, 1999, 3:00:00 AM3/8/99
to
On Fri, 05 Mar 1999 21:36:04 -0500, Scott McPhillips
<scot...@REMOVEhome.com> wrote:

>Jon Sturgeon wrote:
>>
>> On Fri, 05 Mar 1999 20:39:42 GMT, rushm...@my-dejanews.com wrote:
>>

>> >This is my problem:


>> >
>> >CWnd * pWnd = GetDlgItem(IDD_EDIT1);
>> >
>> >Can I determine the type of control returned? i.e. Is pWnd a CComboBox, a
>> >CEdit...
>>
>> Nope, it is a CWnd. The C++ object returned is *not* a CEdit, CComboBox or

>> anything else. The actual control is, but the C++ object is not. What
>> you're almost certainly better off doing is avoiding GetDlgItem()
>> altogether and creating a member variable of the required class (ie
>> CButton, CComboBox etc) and using DDX_Control() to associate the C++ object
>> with the actual control. Then you will have the correct type of object.
>>
>
>Well, I agree with everything in Jon's answer except "Nope"
>
> GetClassName(pWnd->m_hWnd,...);
>
>will return the window class name, which is a documented string ("COMBOBOX", "EDIT", etc.) for all the standard controls.

You can disagree if you like, but you'd be wrong :-)

The call to GetClassName() does not disprove my assertion, namely that the
C++ object is a CWnd and *not* a CEdit. The actual control most certainly
is an edit control and this is what GetClassName() is returning.

The reason that casting the result of GetDlgItem() to the type of C++
object that you "know it is" works is that the functions you then call on
these objects simply send window messages to the control and return the
results. If any of these functions tried to access any member variables
that a CEdit or similar class had in addition to the CWnd base class then
you'd get an exception, because the object returned by GetDlgItem *is* a
CWnd, not a CEdit. If you want further proof, you can switch on generation
of RTTI in the compiler and try to use IsKindOf() or dynamic_cast() on the
pointer returned from GetDlgItem(). If you try to cast it to anything
except a CWnd, the cast will fail.

You can use whichever method suits you best. But it is always good to know
exactly what is going on under the hood.

Try going to http://www.microsoft.com/msj and searching for GetDlgItem -
you should find the December 1997 C/C++ Q&A section where Paul DiLascia
talks about this in more detail. If you have access to MSDN it should
contain the full text of the article - in my installation of MSDN the URL
is mk:@ivt:period97/html/cpp1212.htm but I am still running July 1998, so
this might not be correct for later editions.

Regards,
Jon Sturgeon
Jo...@futuresoft.com

danny_pav

unread,
Mar 8, 1999, 3:00:00 AM3/8/99
to
In article <36E0888A...@balliol.oxford.ac.uk>,

David McCabe <david....@balliol.oxford.ac.uk> wrote:
> Jon Sturgeon wrote:
> > On Fri, 05 Mar 1999 20:39:42 GMT, rushm...@my-dejanews.com wrote:
> > >CWnd * pWnd = GetDlgItem(IDD_EDIT1);
> > >
> > >Can I determine the type of control returned? i.e. Is pWnd a CComboBox, a
> > >CEdit...
> >
> > Nope, it is a CWnd. The C++ object returned is *not* a CEdit, CComboBox or
> > anything else. The actual control is, but the C++ object is not.
>
> The returned object is a CWnd pointer, but it can be safely cast to CEdit*,
> CComboBox* or whatever since those classes have no additional data members.
> You can therefore do
>
> CEdit *pEdit = (CEdit *)GetDlgItem(IDD_EDIT1);
>
> without fear.
> --
> Dave
> david....@balliol.oxford.ac.uk
> http://users.ox.ac.uk/~ball0597/
>

Here's what happens: MFC keeps two maps of HWNDs to CWnd *'s: a permanent one
and a temporary one. When you do GetDlgItem, it looks through the permanent
list and if it finds one it returns that one. (Entries get into the permanent
list through the DDX mechanism.) If it finds nothing, it will create a CWnd
(generic) and put it into the temporary list and return that. From time to
time MFC will clean out the temporary list. That is why you shouldn't store
the CWnd pointers you get from some functions. To answer your question: if
you get a temporary CWnd *, dynamic casting will not work prpoperly because
it will just be a generic CWnd even though it may point to a combo box
control. If it is permanent (see FromHandlePermanent()), the dynamic casting
will work because it will refer to a CComboBox instance created as data
member of a CDialog or CFormView and added to the permanent list via DDX.
You can safely do the cast: CEdit *pEdit = (CEdit *)GetDlgItem(IDD_EDIT1);
because CEdit and the other window control classes do not add any data
members to CWnd and access evertything via messaging.

Hope this helps
Danny Pav

Kurt Grittner

unread,
Mar 8, 1999, 3:00:00 AM3/8/99
to
Hi JonS,

I don't understand why you say that. I call specific member functions
from upcast CWnds obtaind from GetDlgItem() all of the time... here's
an example:

CWnd* pCBtn = m_wndDlgBar.GetDlgItem(nID);
BOOL bNew = ((CButton*)(pCBtn))->GetCheck();
...
CWnd* pCBtn = m_wndDlgBar.GetDlgItem(IDC_SEND_SPEED);
int newrate = ((CSliderCtrl*)(pCBtn))->GetPos();

Notice that GetPos is not a member of CWnd, and yet this code works
fine.

The docs say you should cast this returnvalue to the appropriate type.
I think your theory needs some work...

Regards,
Kurt

Jon Sturgeon

unread,
Mar 8, 1999, 3:00:00 AM3/8/99
to
On Mon, 08 Mar 1999 16:04:00 GMT, danny_pav <dann...@geocities.com>
wrote:

>Here's what happens: MFC keeps two maps of HWNDs to CWnd *'s: a permanent one
>and a temporary one. When you do GetDlgItem, it looks through the permanent
>list and if it finds one it returns that one. (Entries get into the permanent
>list through the DDX mechanism.) If it finds nothing, it will create a CWnd
>(generic) and put it into the temporary list and return that. From time to
>time MFC will clean out the temporary list. That is why you shouldn't store
>the CWnd pointers you get from some functions. To answer your question: if
>you get a temporary CWnd *, dynamic casting will not work prpoperly because
>it will just be a generic CWnd even though it may point to a combo box
>control. If it is permanent (see FromHandlePermanent()), the dynamic casting
>will work because it will refer to a CComboBox instance created as data
>member of a CDialog or CFormView and added to the permanent list via DDX.
>You can safely do the cast: CEdit *pEdit = (CEdit *)GetDlgItem(IDD_EDIT1);
>because CEdit and the other window control classes do not add any data
>members to CWnd and access evertything via messaging.

Thanks for the follow-up, Danny. I'm glad I'm not the only one trying to
defend my assertion :-)

Regards,
Jon Sturgeon
Jo...@futuresoft.com


Andy Yee

unread,
Mar 8, 1999, 3:00:00 AM3/8/99
to
The reason it works for all of us, is that the control classes are thin
wrappers around calling messages to these controls. If there were data
or virtual functions for these control classes, this scheme would fall
apart. Refer to Paul DiLascia's article in Dec 97 MSJ...

In article <36e3eedc...@msnews.microsoft.com>, grit...@mailbag.com (Kurt

Grittner) wrote:
>Hi JonS,
>
>I don't understand why you say that. I call specific member functions
>from upcast CWnds obtaind from GetDlgItem() all of the time... here's
>an example:
>
>CWnd* pCBtn = m_wndDlgBar.GetDlgItem(nID);
>BOOL bNew = ((CButton*)(pCBtn))->GetCheck();

>....


>CWnd* pCBtn = m_wndDlgBar.GetDlgItem(IDC_SEND_SPEED);
>int newrate = ((CSliderCtrl*)(pCBtn))->GetPos();
>
>Notice that GetPos is not a member of CWnd, and yet this code works
>fine.
>
>The docs say you should cast this returnvalue to the appropriate type.
>I think your theory needs some work...

------------------------------------------------------------------------
Andy Yee Corporate E-Mail: See Above
Software Engineer Coporate Web Page: http://www.jasc.com
Jasc Software, Inc. Personal E-Mail: n...@yuck.net
Personal Web Page: http://www.visi.com/~nde

Question authority...and the authorities will question YOU!
------------------------------------------------------------------------

Stephe...@dbce.csiro.au

unread,
Mar 12, 1999, 3:00:00 AM3/12/99
to
danny_pav <dann...@geocities.com> wrote:
> Here's what happens: MFC keeps two maps of HWNDs to CWnd *'s: a permanent one
> and a temporary one. When you do GetDlgItem, it looks through the permanent
> list and if it finds one it returns that one. (Entries get into the permanent
> list through the DDX mechanism.)

What if the control is not created as a child of a dialog or a form,
but is instead created using the CWnd::Create function? Presumably
the DDX mechanism doesn't apply then? ...so are such controls on the
"permanent" list?

--
Stephen Oakes Stephe...@dbce.csiro.au
CSIRO Division of Building, Construction and Engineering
PO Box 56, Highett, Victoria, 3190, Australia.
Tel: +61 3 92526000 Mobile: +61 41 605 9408
Fax: +61 3 92526249

0 new messages