背景知识:
(1)ComboBox实际是一个Edit控件和一个ListBox控件的组合,列表实际是ListBox,那么要实现上述目标,最主要的一点就是得获取到ListBox的句柄.
(2)WM_CTLCOLOR消息及其处理函数OnCtlColor
The framework calls this member function when a child control is about to be drawn. Most controls send this message to their parent (usually a dialog box) to prepare the pDC for drawing the control using the correct colors.
To change the text color, call the SetTextColor member function with the desired red, green, and blue (RGB) values.
(3)CListBox有一个消息叫做LB_SETTOPINDEX,截获这个消息,通过设置wparam为0可以使列表置顶
(4)通过实现一个类的WindowProc,可以截获改类的消息,并自行处理
实现步骤:
(1)从CListBox派生一个子类CMyListBox
(2)实现CListBox的虚函数WindowProc
LRESULT CMyListBox::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
// TODO: Add your specialized code here and/or call the base class
if (message == LB_SETTOPINDEX)
{
wParam = 0;//wParam要传递给父类去处理,wParam在本消息中就是Topindex的位置
}
return CListBox::WindowProc(message, wParam, lParam);
}
(3)从CComboBox派生一个子类CMyComboBox,并增加两个成员变量,一个为CEdit类型,一个为CMyListBox类型
(4)为CMyComboBox实现WM_CTLCOLOR消息
HBRUSH CMyComboBox::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
if (nCtlColor == CTLCOLOR_EDIT)
{
if (m_edit.GetSafeHwnd() == NULL)
{
m_edit.SubclassWindow(pWnd->GetSafeHwnd());
//This method dynamically subclasses a window and attach it to this CWnd object
}
}
else if (nCtlColor == CTLCOLOR_LISTBOX)
{
if (m_listbox.GetSafeHwnd() == NULL)
{
m_listbox.SubclassWindow(pWnd->GetSafeHwnd());
}
}
HBRUSH hbr = CComboBox::OnCtlColor(pDC, pWnd, nCtlColor);
// TODO: Change any attributes of the DC here
// TODO: Return a different brush if the default is not desired
return hbr;
}
(5)为CMyComboBox实现WM_DESTORY消息
void CMyComboBox::OnDestroy()
{
if (m_edit.GetSafeHwnd() != NULL)
m_edit.UnsubclassWindow();
if (m_listbox.GetSafeHwnd() != NULL)
m_listbox.UnsubclassWindow();
CComboBox::OnDestroy();
// TODO: Add your message handler code here
}
(6)在程序初始化的时候,如在OnInitdialog中给CMyListBox对象发消息
::SendMessage(m_combobox.m_listbox.m_hWnd,LB_SETTOPINDEX,0,0);
并且
m_combobox.ShowDropDown();
m_combobox.ShowDropDown(FALSE);
(原因为:"Note that for subclassing to occur, the dialog box must be painted at leastonce. ")
参考知识:
SUMMARY
While it is simple to directly subclass a combo box control, it is not simple t...
One safe way to subclass the internal edit and list box controls is tosubclass them in the WM_CTLCOLORXXX messages. Because Win32 sends separateWM_CTLCOLOREDIT and WM_CTLCOLORLISTBOX messages, these messages are safeand easy ways to get the HWNDs of the child controls of the combo box.
Below is a CSuperComboBox class, which is an MFC implementation of thismethod. Because MFC routes all the WM_CTLCOLOR messages to OnCtlColor, thesubclassing takes place there.
MORE INFORMATION
Use ClassWizard to derive a class from CComboBox and add message handlers for W...
Use ClassWizard to derive a class from CComboBox and add message handlersfor WM_CTLCOLOR and WM_DESTROY. Then manually edit the header file to addthe data members, m_edit and m_listbox. Finally, copy the code from themessage handlers below:
Sample code
// SuperComboBox.h : header file class CSuperComboBox : public CComboBox { public: CEdit m_edit; CListBox m_listbox; protected: afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor); afx_msg void OnDestroy(); ... }; // SuperComboBox.cpp : implementation file HBRUSH CSuperComboBox::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) { if (nCtlColor == CTLCOLOR_EDIT) { //[ASCII 160][ASCII 160][ASCII 160]Edit control if (m_edit.GetSafeHwnd() == NULL) m_edit.SubclassWindow(pWnd->GetSafeHwnd()); } else if (nCtlColor == CTLCOLOR_LISTBOX) { //ListBox control if (m_listbox.GetSafeHwnd() == NULL) m_listbox.SubclassWindow(pWnd->GetSafeHwnd()); } HBRUSH hbr = CComboBox::OnCtlColor(pDC, pWnd, nCtlColor); return hbr; } void CSuperComboBox::OnDestroy() { if (m_edit.GetSafeHwnd() != NULL) m_edit.UnsubclassWindow(); if (m_listbox.GetSafeHwnd() != NULL) m_listbox.UnsubclassWindow(); CComboBox::OnDestroy(); }
Note that for subclassing to occur, the dialog box must be painted at leastonce. There are cases when the dialog box doesn't paint at all (forexample, closing the dialog box before it is displayed, hidden dialogboxes). This method may not be suitable when access to the subclassedwindows are needed in these cases.