From: Oliver Regenfelder on
Hello,

Hopefully the title wasn't too confusing. I have a problem with the class wizard.
For classes which are derived from CDialog via 2 hops he looses the ability to
generate event handlers. If I add the event handlers by hand things work but the
automatic 'wizard' things in the resource editor no longer work.

1) What I wanted to achive and did

The project (a dialog based app) uses a tabulator control to display various
pages to the user where he can change values, send commands to an external
device and see the results. But certain operations have to be performed always
when a tab is selected or deselcted (configuration/initialization and reseting
of the external device). In the original approach the Tabs where directly derived
from CDialog and the CMyTabCtrl (derived from CTabCtrl) new which methods to call
for starting/stopping a tab.
I tried to make this more C++ like by introducing an additional class CTab dervied
from CDialog which defines two virtual methods TabSelected, TabDeselected and all Tabs are
now derived from that new class. Additionally as CTab is tightly related to
the tab control I made it a public inner class of the CMyTab Ctrl class.

Essential C++ code:

class CMyTabCtrl :: public CTabCtrl
{
public:
class CTab : public CDialog
{

public:
explicit CTab(LPCTSTR lpszTemplateName, CWnd* pParentWnd = NULL)
: CDialog(lpszTemplateName, pParentWnd)
{};

explicit CTab(UINT nIDTemplate, CWnd* pParentWnd = NULL)
: CDialog(nIDTemplate, pParentWnd)
{};

CTab() : CDialog()
{};

virtual void TabSelected()
{}
virtual void TabDeselected()
{}
};

// other methods to add and setup the needed tabs
}

// Tabs are now implemented via
class CSomeTab :: public CMyTabCtrl::CTab


2) What happened

Somehow the class wizard lost any ability to generate event handlers for all the
classes derived from CMyTabCtrl::CTab.

I suspect it has something to do with all the DECLARE_DYNAMIC and DECLARE_MESSAGE_MAP
macros but I do not have enough insight to point to the problem.

I tried to use DECLARE_DYNAMIC and IMPLEMENT_DYNAMIC but it seems that those macros
choke on inner classes.
Because

IMPLEMENT_DYNAMIC(CMyTabCtrl::CTab, CDialog); // and the needed DECLARE_DYNAMIC in the header file

leads to error messages from the compiler regarding the '::'.

Best regards,

Oliver
From: Joseph M. Newcomer on
See my essay on this topic on my MVP Tips site. It applies to deriving from CDialog,
CFormView, and CPropertyPage. I use it all the time; I even go back and read my own essay
when I need to do it, to remind me of all the details.

Note: a "tab" control uses "tabs". I do not know what a "tabulator control" is, but a
"tabulator" was an early computing device that used punched cards and was programmed with
a wired control panel.
joe

On Mon, 21 Jun 2010 12:39:55 +0200, Oliver Regenfelder <oliver.regenfelder(a)gmx.at> wrote:

>Hello,
>
>Hopefully the title wasn't too confusing. I have a problem with the class wizard.
>For classes which are derived from CDialog via 2 hops he looses the ability to
>generate event handlers. If I add the event handlers by hand things work but the
>automatic 'wizard' things in the resource editor no longer work.
>
>1) What I wanted to achive and did
>
>The project (a dialog based app) uses a tabulator control to display various
>pages to the user where he can change values, send commands to an external
>device and see the results. But certain operations have to be performed always
>when a tab is selected or deselcted (configuration/initialization and reseting
>of the external device). In the original approach the Tabs where directly derived
>from CDialog and the CMyTabCtrl (derived from CTabCtrl) new which methods to call
>for starting/stopping a tab.
>I tried to make this more C++ like by introducing an additional class CTab dervied
>from CDialog which defines two virtual methods TabSelected, TabDeselected and all Tabs are
>now derived from that new class. Additionally as CTab is tightly related to
>the tab control I made it a public inner class of the CMyTab Ctrl class.
>
>Essential C++ code:
>
>class CMyTabCtrl :: public CTabCtrl
>{
>public:
> class CTab : public CDialog
> {
>
> public:
> explicit CTab(LPCTSTR lpszTemplateName, CWnd* pParentWnd = NULL)
> : CDialog(lpszTemplateName, pParentWnd)
> {};
>
> explicit CTab(UINT nIDTemplate, CWnd* pParentWnd = NULL)
> : CDialog(nIDTemplate, pParentWnd)
> {};
>
> CTab() : CDialog()
> {};
>
> virtual void TabSelected()
> {}
> virtual void TabDeselected()
> {}
> };
>
> // other methods to add and setup the needed tabs
>}
>
>// Tabs are now implemented via
>class CSomeTab :: public CMyTabCtrl::CTab
>
>
>2) What happened
>
>Somehow the class wizard lost any ability to generate event handlers for all the
>classes derived from CMyTabCtrl::CTab.
>
>I suspect it has something to do with all the DECLARE_DYNAMIC and DECLARE_MESSAGE_MAP
>macros but I do not have enough insight to point to the problem.
>
>I tried to use DECLARE_DYNAMIC and IMPLEMENT_DYNAMIC but it seems that those macros
>choke on inner classes.
>Because
>
> IMPLEMENT_DYNAMIC(CMyTabCtrl::CTab, CDialog); // and the needed DECLARE_DYNAMIC in the header file
>
>leads to error messages from the compiler regarding the '::'.
****
It should. It will generate syntactically illegal code.

Note that you have not actually done *inheritance* here; you have *embedded* the control.
I do it by inheritance. The macros make an assumption of inheritance.
joe
****
>
>Best regards,
>
>Oliver
Joseph M. Newcomer [MVP]
email: newcomer(a)flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
From: Oliver Regenfelder on
Hello,

Joseph M. Newcomer wrote:
> See my essay on this topic on my MVP Tips site. It applies to deriving from CDialog,
> CFormView, and CPropertyPage. I use it all the time; I even go back and read my own essay
> when I need to do it, to remind me of all the details.

Are you refering to this essay: "Subclassing Dialogs and Property Pages" ?

Because I think I already do the passing of the resource ID.
Here is the original code of the CTab class.

class MyTabCtrl :: public CTabCtrl
{
class CTab : public CDialog
{
public:
explicit CTab(LPCTSTR lpszTemplateName, CWnd* pParentWnd = NULL)
: CDialog(lpszTemplateName, pParentWnd)
{};

explicit CTab(UINT nIDTemplate, CWnd* pParentWnd = NULL)
: CDialog(nIDTemplate, pParentWnd)
{};

CTab() : CDialog()
{};

virtual void TabSelected()
{}
virtual void TabDeselected()
{}
};
};

Now I make my tabs like

class CTabEPC : public CMyTabCtrl::CTab
{

}

and the constructor is

CTabEPC::CTabEPC(CWnd* pParent /*=NULL*/)
: CMyTabCtrl::CTab(CTabEPC::IDD, pParent)
, [variable initialization]
{
//{{AFX_DATA_INIT(CTabEPC)
//}}AFX_DATA_INIT
}

So this should essentially be what your essay suggests. But the problem persists that
visual studio 2008 looses its ability to add event handlers to the CTabEPC class.

I select a control in the resource editor and then start the 'add event handler wizard'.
Anytime I select one of the CMyTabCtrl::CTab derived classes the wizard will not present
any events for selection. Whereas when I select a directly CDialog derived class it works
fine.

So how do I get the functionallity of the event handler wizard back?

> Note: a "tab" control uses "tabs". I do not know what a "tabulator control" is, but a
> "tabulator" was an early computing device that used punched cards and was programmed with
> a wired control panel.

I meant the tab-control.

Best regards,

Oliver
From: Joseph M. Newcomer on
See below...
On Wed, 23 Jun 2010 13:08:21 +0200, Oliver Regenfelder <oliver.regenfelder(a)gmx.at> wrote:

>Hello,
>
>Joseph M. Newcomer wrote:
>> See my essay on this topic on my MVP Tips site. It applies to deriving from CDialog,
>> CFormView, and CPropertyPage. I use it all the time; I even go back and read my own essay
>> when I need to do it, to remind me of all the details.
>
>Are you refering to this essay: "Subclassing Dialogs and Property Pages" ?
>
>Because I think I already do the passing of the resource ID.
>Here is the original code of the CTab class.
>
>class MyTabCtrl :: public CTabCtrl
>{
> class CTab : public CDialog
> {
> public:
> explicit CTab(LPCTSTR lpszTemplateName, CWnd* pParentWnd = NULL)
> : CDialog(lpszTemplateName, pParentWnd)
> {};
>
> explicit CTab(UINT nIDTemplate, CWnd* pParentWnd = NULL)
> : CDialog(nIDTemplate, pParentWnd)
> {};
>
> CTab() : CDialog()
> {};
>
> virtual void TabSelected()
> {}
> virtual void TabDeselected()
> {}
> };
>};
>
>Now I make my tabs like
>
>class CTabEPC : public CMyTabCtrl::CTab
>{
>
>}
>
>and the constructor is
>
>CTabEPC::CTabEPC(CWnd* pParent /*=NULL*/)
> : CMyTabCtrl::CTab(CTabEPC::IDD, pParent)
> , [variable initialization]
>{
> //{{AFX_DATA_INIT(CTabEPC)
> //}}AFX_DATA_INIT
>}
>
>So this should essentially be what your essay suggests. But the problem persists that
>visual studio 2008 looses its ability to add event handlers to the CTabEPC class.
****
Sadly, Microsoft assumes that every class is self-contained. This is truly a bit of a
pain. For people like me, I can write the handlers "by hand" but it is not so easy for a
lot of people. And I still have to check the docs to see the correct format of the
handler.
****
>
>I select a control in the resource editor and then start the 'add event handler wizard'.
>Anytime I select one of the CMyTabCtrl::CTab derived classes the wizard will not present
>any events for selection. Whereas when I select a directly CDialog derived class it works
>fine.
>
>So how do I get the functionallity of the event handler wizard back?
****
Short of a bolt of lightning striking the implementor of ClassWizard, this is probably not
going to happen.
joe
***
>
>> Note: a "tab" control uses "tabs". I do not know what a "tabulator control" is, but a
>> "tabulator" was an early computing device that used punched cards and was programmed with
>> a wired control panel.
>
>I meant the tab-control.
>
>Best regards,
>
>Oliver
Joseph M. Newcomer [MVP]
email: newcomer(a)flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
 | 
Pages: 1
Prev: Oh No Not Again!
Next: Exception handling?