Link to home
Start Free TrialLog in
Avatar of rickatseasoft
rickatseasoft

asked on

Change control type at runtime. SubclassWindow()

Change a control class at runtime.  For reasons that are not real important here, I have a dialog with about a hundred controls on it that sometimes sum columns and/or rows.  This begs for treatment as an array.

It works perfectly except for one thing, and that is the subclassing.  Some of the controls need to become CDollarEdits or CDateEdits, and rather than do this by declaring a large number of control variables, I would like to use SubclassDlgItem or SubclassWindow.

I'm not using variables at all, just GetDlgItem() for the controls all line up nicely in resource.h.  In other words, there is no conflict with DDX.

Something like

CDollarEdit  CtrlDollars[20];

CWnd *pWnd;
for(ii=0;ii<20;ii++){
   pWnd=GetDlgItem(IDC_XXXXXXXXXX+ii);
  //perform some operations on pWnd
   CtrlDollars[ii].SubclassWindow(pWnd->m_hWnd);
}

This compiles and executes without complaint except that the behavior of the controls doesn't change at all.

Any ideas, Rick
Avatar of AndyAinscow
AndyAinscow
Flag of Switzerland image

Have a try with SubclassDlgItem instead

CtrlDollars[ii].SubclassDlgItem(IDC_XXXXXXXXXX+ii, pWnd);
Avatar of rickatseasoft
rickatseasoft

ASKER

Andy:
Once again, it compiled without complaint, and ran without complaint, but didn't exhibit the desired the desired behaviour.

Maybe I am asking the wrong question. or trying to use the wrong function to accomplish the task.

I want to create a CEdit using the standard dialog editor.  Normally, I would use the ClassWizard to attach a variable to that control, let's call it m_ctrlDollar0.  The ClassWizard would then place in the code a line that looked something like CEdit m_ctrlDollar0.  I would then come back and change the control type by changing "CEdit m_ctrlDollar0" to "CDollarEdit m_ctrlDollar0" and viola, my control is a CDollarEdit control exhibiting all of the characteristics of that type of control.  

In this case, I want to do the same thing, but instead of using a variable, I want to step through an array of Dialog Control IDs.

Thanks, Rick
What you are currently doing should work.

Also nothing wrong with code like the following in the DoDataExchange (just the wizard doesn't support it)
for(UINT n = IDC_EDIT1; n <= IDC_EDIT5; n++)
  DDX_CONTROL(pDX, n, myctrl[n-IDC_EDIT1]);
Andy:

Thanks, found the problem----It was me.  Your advice helped me ferret out the problem.

Just two more questions please.

The place where Subclass... is called, is itself called every time that the dialog is resized (NOT by the user, bu tby the needs of the code).  I'm using something like if(!m_CtrlDollard[ii]._hWnd)m_CtrlDollar[ii].SubclassDlgItem(...);   Is this the correct way to do this.

When the CDialog closes, do I need to Unsubclass(), or just let them die a natural death.  The m_CtrlDollars[], etc. are members of the class, so they lose scope (I'm grasping for the C++ term here), and the controls obviously die with the destructor for their parent dialog.

Thanks again, Rick
ASKER CERTIFIED SOLUTION
Avatar of AndyAinscow
AndyAinscow
Flag of Switzerland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
You may also use DDX_Control() loop in your DoDataExchange.....

void CMyDlg::DoDataExchange(CDataExchange* pDX)
{
      CDialog::DoDataExchange(pDX);
      //{{AFX_DATA_MAP(CMyDlg)
          // Other DDX statements here...Dont put loop manually here
      //}}AFX_DATA_MAP

 for (int ii = 0; ii < 20; ii++)
     DDX_Control(pDX, IDC_XXXXXXXXXX+ii, CtrlDollars[ii]);

}

-MAHESH
hmmm.. cause of too late posting sorry agin !