Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Categories

Welcome to the new platform of Programmer's Heaven! We apologize for the inconvenience caused, if you visited us from a broken link of the previous version. The main reason to move to a new platform is to provide more effective and collaborative experience to you all. Please feel free to experience the new platform and use its exciting features. Contact us for any issue that you need to get clarified. We are more than happy to help you.

Dyanamically create controls

Elliott76Elliott76 Posts: 25Member
Hello,
I have a big question for Visual C++ not sure where it goes...I want to find out how to create controls dynamically. The number of Edit controls needed is not known until runtime..

In a simple example...say you have a dialog box with 1 Edit control and 1 Button control...enter a number in the Edit control and once you click the Button, the number you entered will be the number of Edit controls to appear in the dialog..

This would only occur only once each time it was run..

I figure that I will have a CEdit array(member of the dialogs class?) that is initialized at runtime...I found that a CDialog object has a CreateControl(CWnd::CreateControl) method but the parameters are a little confusing...any suggestions would be appreciated...thanks..

CES

Comments

  • pingpongpingpong Posts: 937Member
    Hello there,

    CreateControl is for creating ActiveX controls, so it wont help you here.

    Basically, there are 2 ways I can think of to achieve what you are looking for:

    ====================
    First method: As you suggested, with an array of CEdit's.

    You need to do the following:
    - In your CSomethingDlg .H file, add this:
    private: CEdit* m_pEditControls;

    - In your CSomethingDlg constructor, add this:
    m_pEditControls = NULL;

    - In your CSomethingDlg destructor, add this:
    if(m_pEditControls != NULL) delete[] m_pEditControls;

    This is your array and its initialization/cleanup. Time to use it.

    - In your "create edits" button click handler, add this code:
    [code]
    // base ID for the new edit controls, make sure the number you choose
    // does not conflict with other control ID's already in the dialog
    const int IDC_EDIT_CREATED1 = 2000;

    // say, IDC_EDIT1 is the edit box where they enter the number of
    // controls to create
    int nCount = GetDlgItemInt(IDC_EDIT1, NULL, FALSE);
    if(nCount > 0)
    {
    CWnd* pEdit1 = GetDlgItem(IDC_EDIT1);

    // you probably want to use the same font in those new dialogs as the one already
    // in IDC_EDIT1, so get it
    CFont* pFont = pEdit1->GetFont();

    // also, you probably want to use the same width and height as well
    CRect rc;
    pEdit1->GetWindowRect(rc);
    int nEditWidth = rc.Width();
    int nEditHeight = rc.Height();

    // now allocate your array
    m_pEditControls = new CEdit[nCount];

    // I'm going to assume the controls are created at position 0,0
    // going down, change that to suit your need

    int y = 0;
    for(int i = 0; i < nCount; i++)
    {
    // position and size (notice, CWnd::CreateEx wants to rect as left, top, right, bottom
    // unlike CreateWindow or CreateWindowEx where it should be left, top, width, height
    CRect rect(0, y, 0 + nEditWidth, y + nEditHeight);

    m_pEditControls[i].CreateEx(
    WS_EX_CLIENTEDGE,
    "edit",
    "",
    WS_CHILD | WS_VISIBLE | WS_TABSTOP,
    rect,
    this,
    IDC_EDIT_CREATED1 + i);

    y += nEditHeight * 2;

    // set the font
    m_pEditControls[i].SetFont(GetDlgItem(IDC_EDIT1)->GetFont());
    }
    }
    [/code]

    =============
    Second method: There's no need really to store the array of CEdit controls anywhere, you do not need them. Since you have the ID's, you can easily get the CWnd or HWND of the edit control you want through GetDlgItem whenever you need it. First method used that because doing something like:
    [code]
    for(int i = 0; i < nCount; i++)
    {
    CEdit edit;
    edit.CreateEx( something)
    }
    [/code]
    Wont work, edit's destructor gets called at the for loop } and we end up with our edit boxes getting destroyed as soon as we add them.

    Solution to that is to use the Win32 API to create your controls through CreateWindowEx, later on, whenever you want a CEdit of any of them, you can just do:
    CEdit* pEdit = (CEdit*)GetDlgItem(id);

    To use this, you need:
    - Forget about the CEdit* m_pEditControls member, we are not going to need that.

    - In your "create edits" button click handler, use the same code from the first method, only change the loop to look like this:
    [code]
    int y = 0;
    for(int i = 0; i < nCount; i++)
    {
    HWND hWndEdit = ::CreateWindowEx(
    WS_EX_CLIENTEDGE,
    "edit",
    "",
    WS_CHILD | WS_VISIBLE | WS_TABSTOP,
    0,
    y,
    nEditWidth,
    nEditHeight,
    GetSafeHwnd(),
    (HMENU)(IDC_EDIT_CREATED1 + i),
    AfxGetInstanceHandle(),
    NULL);
    y += nEditHeight * 2;

    ::SendMessage(hWndEdit, WM_SETFONT, (WPARAM)pFont->GetSafeHandle(), 0);
    }
    [/code]

    Hope this help.s
  • Elliott76Elliott76 Posts: 25Member
    : Hello there,
    :
    : CreateControl is for creating ActiveX controls, so it wont help you here.
    :
    : Basically, there are 2 ways I can think of to achieve what you are looking for:
    :
    : ====================
    : First method: As you suggested, with an array of CEdit's.
    :
    : You need to do the following:
    : - In your CSomethingDlg .H file, add this:
    : private: CEdit* m_pEditControls;
    :
    : - In your CSomethingDlg constructor, add this:
    : m_pEditControls = NULL;
    :
    : - In your CSomethingDlg destructor, add this:
    : if(m_pEditControls != NULL) delete[] m_pEditControls;
    :
    : This is your array and its initialization/cleanup. Time to use it.
    :
    : - In your "create edits" button click handler, add this code:
    : [code]
    : // base ID for the new edit controls, make sure the number you choose
    : // does not conflict with other control ID's already in the dialog
    : const int IDC_EDIT_CREATED1 = 2000;
    :
    : // say, IDC_EDIT1 is the edit box where they enter the number of
    : // controls to create
    : int nCount = GetDlgItemInt(IDC_EDIT1, NULL, FALSE);
    : if(nCount > 0)
    : {
    : CWnd* pEdit1 = GetDlgItem(IDC_EDIT1);
    :
    : // you probably want to use the same font in those new dialogs as the one already
    : // in IDC_EDIT1, so get it
    : CFont* pFont = pEdit1->GetFont();
    :
    : // also, you probably want to use the same width and height as well
    : CRect rc;
    : pEdit1->GetWindowRect(rc);
    : int nEditWidth = rc.Width();
    : int nEditHeight = rc.Height();
    :
    : // now allocate your array
    : m_pEditControls = new CEdit[nCount];
    :
    : // I'm going to assume the controls are created at position 0,0
    : // going down, change that to suit your need
    :
    : int y = 0;
    : for(int i = 0; i < nCount; i++)
    : {
    : // position and size (notice, CWnd::CreateEx wants to rect as left, top, right, bottom
    : // unlike CreateWindow or CreateWindowEx where it should be left, top, width, height
    : CRect rect(0, y, 0 + nEditWidth, y + nEditHeight);
    :
    : m_pEditControls[i].CreateEx(
    : WS_EX_CLIENTEDGE,
    : "edit",
    : "",
    : WS_CHILD | WS_VISIBLE | WS_TABSTOP,
    : rect,
    : this,
    : IDC_EDIT_CREATED1 + i);
    :
    : y += nEditHeight * 2;
    :
    : // set the font
    : m_pEditControls[i].SetFont(GetDlgItem(IDC_EDIT1)->GetFont());
    : }
    : }
    : [/code]
    :
    : =============
    : Second method: There's no need really to store the array of CEdit controls anywhere, you do not need them. Since you have the ID's, you can easily get the CWnd or HWND of the edit control you want through GetDlgItem whenever you need it. First method used that because doing something like:
    : [code]
    : for(int i = 0; i < nCount; i++)
    : {
    : CEdit edit;
    : edit.CreateEx( something)
    : }
    : [/code]
    : Wont work, edit's destructor gets called at the for loop } and we end up with our edit boxes getting destroyed as soon as we add them.
    :
    : Solution to that is to use the Win32 API to create your controls through CreateWindowEx, later on, whenever you want a CEdit of any of them, you can just do:
    : CEdit* pEdit = (CEdit*)GetDlgItem(id);
    :
    : To use this, you need:
    : - Forget about the CEdit* m_pEditControls member, we are not going to need that.
    :
    : - In your "create edits" button click handler, use the same code from the first method, only change the loop to look like this:
    : [code]
    : int y = 0;
    : for(int i = 0; i < nCount; i++)
    : {
    : HWND hWndEdit = ::CreateWindowEx(
    : WS_EX_CLIENTEDGE,
    : "edit",
    : "",
    : WS_CHILD | WS_VISIBLE | WS_TABSTOP,
    : 0,
    : y,
    : nEditWidth,
    : nEditHeight,
    : GetSafeHwnd(),
    : (HMENU)(IDC_EDIT_CREATED1 + i),
    : AfxGetInstanceHandle(),
    : NULL);
    : y += nEditHeight * 2;
    :
    : ::SendMessage(hWndEdit, WM_SETFONT, (WPARAM)pFont->GetSafeHandle(), 0);
    : }
    : [/code]
    :
    : Hope this help.s
    :


    Thank you very much...I'll try it tonight...really appreciate it..
    CES
Sign In or Register to comment.