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::DefWindowProc()! 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!
Jason Teagle
May 18th, 1999, 06:26 AM
Post the code which creates the window from the dialogue resource, and the code which creates the controls; we can have a look then.
Andreas Lücke
May 18th, 1999, 09:36 AM
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;
// 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 = ::DefWindowProc;
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);
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 :)
Jason Teagle
May 19th, 1999, 07:08 AM
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.
Andreas Lücke
May 25th, 1999, 02:48 AM
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
2. Only the header control notify messages pass the parent's ::OnNotify ().
Anyway, You helped me a lot yet.
Andreas Lücke :)
Jason Teagle
May 25th, 1999, 04:13 AM
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.
codeguru.com
Copyright Internet.com Inc., All Rights Reserved.