0

I'm asking about a list or controls container in mfc dialog? i don't mean listing the child windows of the a dialog like this question Loop through MFC Child Dialogs, MDIFrames etc ,What i want is a list of the controls defined as variables in the dialog class those which DDX_Control method is applied on them.

i need to have a list of all control variables defined in the dialog

Community
  • 1
  • 1
ahmedsafan86
  • 1,776
  • 1
  • 26
  • 49
  • As far as I know, there's no such thing. Anytime I've had to loop through all the controls, I've looped through the child windows. What are you trying to do to need that? – MikMik Apr 24 '13 at 13:02
  • I have a previously written application with classes that don't depend on mfc but owl, the controls was initialized in the constructor but now I'm moving to MFC i need to initialize them in the DoDataExchange without changing any thing in the written code i have hundreds of dialogs, i have a strategy for mapping methods, event handling macros and messages, After finish I'll but my work on the answer to this question http://stackoverflow.com/questions/15930819/c-migration-from-borland-owl-to-microsoft-mfc . I must re-implement the basic controls in my project [TEdit,..] – ahmedsafan86 Apr 24 '13 at 14:54
  • so I will pass the parent to the child control at initialization and the control Resource ID, the control will store it's resource id in a member variable the child will add itself to the parent controls list, at the parent's DoDataExchange we will iterate over the controls and initialize them, I hoped that i could found a list of the controls from MFC – ahmedsafan86 Apr 24 '13 at 15:13

2 Answers2

1

There is no such thing. A control is used by DDX because the corresponding DDX_* function is called in the DoDataExchange method of your dialog class. There is no table that you could parse and therefore you cannot dynamically determine which DDX_* function is called in your DoDataExchange method.

void CMySampleDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialog::DoDataExchange(pDX);
    //{{AFX_DATA_MAP(CReprendBudgetDlg)
    DDX_Text(pDX, IDC_EDIT1, m_name1);
    DDX_Text(pDX, IDC_EDIT2, m_name2);
    //}}AFX_DATA_MAP
}

But you could "override" the DDX_* functions by some functions of your own that would put the control IDs in an array. So once the DoDataExchage function has been executed that array would contain all Control IDs used by DDX.

void AFXAPI MY_DDX_Text(CDataExchange* pDX, int nIDC, CString& value, CWordArray & ddxcontrols)
{
  DDX_Text(pDX, nIDC, value);
  if (!pDX->bSaveAndValidate)
    ddxcontrols.Add(nIDC) ;
}


#define DDX_Text(a,b,c) MY_DDX_Text(a,b,c)  // now we can continue to use DDX_Text
                                            // and the Class Wizard will be happy

class CMySampleDlg : public CDialog
{
 ...
  protected:
    CWordArray m_ddxcontrols ;  // array that will contain all control IDs use by DDX
  ...
}


void CMySampleDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialog::DoDataExchange(pDX);
    //{{AFX_DATA_MAP(CReprendBudgetDlg)
    DDX_Text(pDX, IDC_EDIT1, m_name1, m_ddxcontrols);
    DDX_Text(pDX, IDC_EDIT2, m_name2, m_ddxcontrols);
    //}}AFX_DATA_MAP
}

So all you have to do is

  • Write the MY_DDX_* functions for all DDX_* functions (they are defined in afxdd_.h).
  • In all your dialogs replace all calls to DDX_* functions my MY_DDX_* functions
  • Put the m_ddxcontrols members in all your dialogs
Jabberwocky
  • 48,281
  • 17
  • 65
  • 115
  • This is a solution but it seems that it will not be understood in Class Wizard, My question was if it's native in mfc or not, i'm not going to edit hundreds of code files, instead i'll add a list to the base dialog, and the base controls will append them selves to the list of their parent dialog, at the DoDataExchange i'll iterate over the list and call DDX_Control for each control. this will be written in one place [base dialog and base control] – ahmedsafan86 Apr 25 '13 at 08:20
  • I justed edited the answer. You could use macros so the class wizard continue to work. – Jabberwocky Apr 26 '13 at 14:32
0

None that I know of, but you can copy the control resource IDs from the DoDataExchange block into an array with a zero terminator:

const UINT myControls[] =
{
  IDC_EDIT1,      IDC_EDIT2,      IDC_EDIT3,
  IDC_BUTTON1,    IDC_BUTTON2,    IDC_BUTTON3,
  IDC_STATIC1,    IDC_STATIC2,    IDC_STATIC3,
  0
};

then you can use this array for iterating over the controls to do with as you wish:

for (const UINT* p = myControls; *p; ++p)
{
    CWnd *wnd = GetDlgItem(*p);
    ...
}

Not a dynamic solution, but simple enough.

acraig5075
  • 10,588
  • 3
  • 31
  • 50