CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 6 of 6
  1. #1
    Join Date
    May 1999
    Posts
    4

    No parent notification of dynamically created controls

    Hi,
    I have a CWnd dreived class A, created from a dialog template with CWnd::CreateDlg(). That's fine.
    I have also dynamically created some common controls (vertical CScrollBar, CHeader) with <controlClass>::create, als childs of the window A.
    Problem: These controls do NOT send messages to their parents. A::OnVScroll() ist never called! No header mnessage passes A::PreTranslateMessage or A:efWindowProc()! WHY?

    Isn't it ehough to create a control as its parent child, to notify him for everything?
    Looks like a basic misunderstanding of mine!

    Thanks for any hint! Thank You!


  2. #2
    Join Date
    May 1999
    Location
    Farnborough, Hants, England
    Posts
    710

    Re: No parent notification of dynamically created controls

    Post the code which creates the window from the dialogue resource, and the code which creates the controls; we can have a look then.



    --
    Jason Teagle
    [email protected]

  3. #3
    Join Date
    May 1999
    Posts
    4

    Re: No parent notification of dynamically created controls

    Here is the code:
    Actually my situation has one more window level. It looks like:

    // The window containing some Buttons and my selfmade CInfoListCtrl.
    class CInformationWnd : public CWnd {
    CInfoListCtrl m_infoList;
    }
    // My self made list control with a header, scollbar and several items of class CInfoListItem
    class CInfoListCtrl : public CWnd {
    CHeaderCtrl m_header;
    CScrollBar m_vScrollBar;
    // CObArray of CInfoListItems
    CInfoListItemArray m_items;
    }
    // An item listed in CInfoListCtrl with alternatively showing one of several controls.
    class CInfoListItem : public CWnd {
    CEdit m_editCtrl;
    CComboBox m_dropDownCtrl;
    CComboBox m_dropDownListCtrl;
    CDateTimeCtrl m_dateCtrl;
    CButton m_button;
    CListBox m_listBox;
    CStatic m_pixmap;

    }



    How the dialog based window is created

    BOOL CInformationWnd::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext)
    {
    BOOL ok = TRUE;

    if (!CreateDlg (MAKEINTRESOURCE (CInformationWnd::IDD), pParentWnd ))
    return FALSE;

    // Register a the window class...
    memset(&m_wndClass, 0, sizeof(WNDCLASS));
    m_wndClass.lpfnWndProc = :efWindowProc;
    m_wndClass.hInstance = theApp.m_hInstance;
    m_wndClass.hCursor = NULL;
    m_wndClass.hIcon = theApp.LoadIcon(IDR_MAINFRAME);
    m_wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
    m_wndClass.hbrBackground = (HBRUSH) (COLOR_WINDOW);
    m_wndClass.lpszMenuName = MAKEINTRESOURCE(0);
    m_wndClass.lpszClassName = "CInfoListCtrl";
    if (!AfxRegisterClass(&m_wndClass))
    {
    DWORD error = GetLastError ();
    AfxMessageBox("Unable to resgister window class ");
    return FALSE;
    }
    WINDOWPLACEMENT wp;
    // calc scroll area
    // here I subtitue a CStatic ctrl IDC_INFO_AREA designed with VStudio
    // with my CInfoListCtrl
    CWnd *pWnd = GetDlgItem (IDC_INFO_AREA);

    ok = pWnd != NULL;
    pWnd->GetWindowPlacement (&wp);
    HWND hWnd = pWnd->Detach ();
    pWnd->DestroyWindow ();
    dwStyle |= WS_VISIBLE;
    dwStyle |= WS_BORDER;
    dwStyle &= ~WS_CHILD;
    if ( !m_infoList.Create (m_wndClass.lpszClassName, "InfoListCtrl Window", dwStyle, wp.rcNormalPosition, this, IDC_INFO_AREA, pContext))
    return FALSE;

    if (!createStaticGUI ())
    return FALSE;

    // initialize controls etc; stolen from CFormView
    if (!ExecuteDlgInit(MAKEINTRESOURCE (CInformationWnd::IDD)))
    return FALSE;

    return ok;
    }



    How my Control is created, that lists items of type CInfoListItem, with a header and CScrollBar.

    BOOL CInfoListCtrl::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext)
    {
    BOOL ok = TRUE;
    ok = CWnd::Create(lpszClassName, lpszWindowName, dwStyle, rect, pParentWnd, nID, pContext);

    // creating Header Ctrl
    CWnd *pWnd = NULL;
    CRect hr = rect;
    hr.bottom = hr.top + GUI_HEADER_CTRL_HEIGHT;
    ok = ok && m_header.Create (HDS_HORZ | HDS_BUTTONS | CCS_NODIVIDER | CCS_TOP |
    WS_GROUP | WS_CHILD | WS_VISIBLE,
    hr, this, IDC_HEADER);
    ..... some successful header initialization

    // create Scroll Bar
    RECT srect;
    srect = rect;
    srect.top += GUI_HEADER_CTRL_HEIGHT;
    ok = ok && m_vScrollBar.Create ( WS_CHILD | WS_VSCROLL | SBS_RIGHTALIGN | SBS_VERT, srect, this, IDC_VSCROLL);
    // register window class for CInfoListItem
    memset(&m_ItemWndClass, 0, sizeof(WNDCLASS));
    // common initialization
    m_ItemWndClass.lpfnWndProc = :efWindowProc;
    m_ItemWndClass.hInstance = theApp.m_hInstance;
    m_ItemWndClass.hCursor = NULL;
    m_ItemWndClass.hIcon = theApp.LoadIcon(IDR_MAINFRAME);
    m_ItemWndClass.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
    // m_ItemWndClass.style = CS_DBLCLKS;
    m_ItemWndClass.hbrBackground = (HBRUSH) (COLOR_WINDOW);
    m_ItemWndClass.lpszMenuName = MAKEINTRESOURCE(0);
    m_ItemWndClass.lpszClassName = "CInfoListItem";
    if (!AfxRegisterClass(&m_ItemWndClass))
    {
    DWORD error = GetLastError ();
    AfxMessageBox("Unable to resgister window class ");
    return FALSE;
    }
    SendMessageToDescendants(WM_INITIALUPDATE, 0, 0, FALSE, FALSE);

    return ok;

    }



    After Create() several list items of type CInfoListItem are cretated with:

    CInfoListItem *pNewItem = new CInfoListItem;
    pNewItem->create (pInfoListCtrl, 0);
    // set a unique ID
    pNewItem->SetDlgCtrlID (ID_RESERVED_ITEMS_1 + i * ID_RESERVED_PER_ITEM + IDC_LIST_ITEM);



    BOOL CInfoListItem::create (CInfoListCtrl* pParentCtrl, UINT nID)
    {
    BOOL ok = TRUE;
    DBG_ASSERT_MSG (pParentCtrl != NULL, "Illeagal Initialization!");
    DBG_ASSERT_MSG (pParentCtrl->m_pLayout != NULL, "Illeagal Initialization!");
    if (pParentCtrl == NULL)
    return FALSE;

    m_pParentCtrl = pParentCtrl;

    RECT rect;
    pParentCtrl->GetClientRect (&rect);
    rect.top += GUI_HEADER_CTRL_HEIGHT;
    rect.left += 2;
    rect.bottom = rect.top + 50; // any default height
    ok = CWnd::Create(pParentCtrl->m_ItemWndClass.lpszClassName,
    NULL, // window Title
    0, // dwStyle
    rect,
    pParentCtrl,
    nID,
    NULL //CCreateContext* pContext
    );

    // the controls we control:
    ok = ok && m_fieldname.Create ("<fieldname>", // text
    WS_VISIBLE, // dwStyle
    rect,
    this // parent
    );
    // create the content controls
    DWORD dwStyle = WS_TABSTOP;
    int tab1Width = m_pParentCtrl->getTabWidth (0);
    rect.left += tab1Width;
    rect.left += m_pParentCtrl->m_pLayout->m_ulContentMarginLeft;
    ok = ok && m_editCtrl.Create (
    dwStyle,
    rect,
    this, // parent
    IDC_FIELD_CTRL);

    ok = ok && m_dropDownCtrl.Create (dwStyle|CBS_DROPDOWN,
    rect,
    this, // parent
    IDC_FIELD_CTRL);

    ok = ok && m_dropDownListCtrl.Create (dwStyle|CBS_DROPDOWNLIST,
    rect,
    this, // parent
    IDC_FIELD_CTRL);

    ok = ok && m_dateCtrl.Create (dwStyle|DTS_SHORTDATEFORMAT,
    rect,
    this, // parent
    IDC_FIELD_CTRL);

    ok = ok && m_button.Create ("",
    dwStyle|BS_CHECKBOX,
    rect,
    this, // parent
    IDC_FIELD_CTRL);

    ok = ok && m_listBox.Create (dwStyle|LBS_EXTENDEDSEL|LBS_MULTIPLESEL,
    rect,
    this, // parent
    IDC_FIELD_CTRL);

    ok = ok && m_pixmap.Create ("",
    dwStyle,
    rect,
    this, // parent
    IDC_FIELD_CTRL);

    return ok;
    }




    My main probles is, that I do not get notifications in CInfoListItem .e.g. from the m_editCtrl, when it edited or getting focus with ON_EN_CHANGE or ON_EN_SETFOCUS. CInfoListItem::OnNotify() is not called anyway!

    Hope my problem gets clear and Jason Teagle or somebody else can help me.
    Thanks anyway.
    Andreas Lücke


  4. #4
    Join Date
    May 1999
    Location
    Farnborough, Hants, England
    Posts
    710

    Re: No parent notification of dynamically created controls

    There are three types of window: a top-level window, an owned window and a child window. Both owned and child windows fit inside their parent and are hidden when the parent is hidden, but only child windows notify their parents.

    I have just noticed that when you create all the controls, such as m_editCtrl, m_button, m_listBox, you are giving them a parent, but you have NOT specified WS_CHILD (dwStyle is just WS_TABSTOP). Any window which is given a parent but is not declared a child specifically is an OWNED window, not a CHILD window. There is, unfortunately, a difference.

    I think if you change the line

    dwStyle = WS_TABSTOP ;

    to

    dwStyle = WS_CHILD|WS_TABSTOP ;

    ... that will cure your problem. Let me know how it goes.



    --
    Jason Teagle
    [email protected]

  5. #5
    Join Date
    May 1999
    Posts
    4

    Re: No parent notification of dynamically created controls

    Thanks for your help. It works now! The window style WS_CHILD helped.
    But there are still some odd things:
    1. The OnNotify() method of the control's parent is not called, BUT the Notify-handlers installed with

    BEGIN_MESSAGE_MAP(CInfoListItem, CWnd)
    //{{AFX_MSG_MAP(CInfoListItem)
    ON_EN_SETFOCUS(IDC_FIELD_CTRL, OnEditSetFocus )
    ON_EN_CHANGE( IDC_FIELD_CTRL, OnEditChange)
    //}}AFX_MSG_MAP
    END_MESSAGE_MAP()


    are called properly. Why?

    2. Only the header control notify messages pass the parent's ::OnNotify ().

    Anyway, You helped me a lot yet.
    Andreas Lücke



  6. #6
    Join Date
    May 1999
    Location
    Farnborough, Hants, England
    Posts
    710

    Re: No parent notification of dynamically created controls

    Only the new common controls (CListCtrl, CTreeCtrl, CHeaderCtrl, etc.) use the WM_NOTIFY message. Ordinary buttons, text boxes, combo boxes and list boxes (things that were around in 16-bit VC++) still use WM_COMMAND, as before. That's why.



    --
    Jason Teagle
    [email protected]

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured