模拟combo box,该如何处理
模拟combo box
想自己做一个combo box,当然点击下拉接纽时,会弹出自己的列表框,如一个树控件等。
从CWnd类继承,在内部动态生成一个编辑框子控件,一个按纽子控件,一个列表子控件。点击按纽后,CWnd变高,显示出列表子控件.
但列表子控件显示后,如果对话框中还有别的控件,被列表虽然挡住了,但如果点击到,会显示出来遮住列表。
我把CWnd和列表SetWindowPos()成HWND_TOPMOST,也无济于事。
不知combo box的原码中是怎么处理这个问题的。
------解决方案--------------------
刚才找了下CComboBox源码,先贴出来
想自己做一个combo box,当然点击下拉接纽时,会弹出自己的列表框,如一个树控件等。
从CWnd类继承,在内部动态生成一个编辑框子控件,一个按纽子控件,一个列表子控件。点击按纽后,CWnd变高,显示出列表子控件.
但列表子控件显示后,如果对话框中还有别的控件,被列表虽然挡住了,但如果点击到,会显示出来遮住列表。
我把CWnd和列表SetWindowPos()成HWND_TOPMOST,也无济于事。
不知combo box的原码中是怎么处理这个问题的。
------解决方案--------------------
刚才找了下CComboBox源码,先贴出来
- C/C++ code
BOOL CComboBox::Create(DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID) { CWnd* pWnd = this; return pWnd->Create(_T("COMBOBOX"), NULL, dwStyle, rect, pParentWnd, nID); } CComboBox::~CComboBox() { DestroyWindow(); } // Derived class is responsible for implementing these handlers // for owner/self draw controls (except for the optional DeleteItem) void CComboBox::DrawItem(LPDRAWITEMSTRUCT) { ASSERT(FALSE); } void CComboBox::MeasureItem(LPMEASUREITEMSTRUCT) { ASSERT(FALSE); } int CComboBox::CompareItem(LPCOMPAREITEMSTRUCT) { ASSERT(FALSE); return 0; } void CComboBox::DeleteItem(LPDELETEITEMSTRUCT) { /* default to nothing */ } BOOL CComboBox::OnChildNotify(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult) { switch (message) { case WM_DRAWITEM: ASSERT(pResult == NULL); // no return value expected DrawItem((LPDRAWITEMSTRUCT)lParam); break; case WM_MEASUREITEM: ASSERT(pResult == NULL); // no return value expected MeasureItem((LPMEASUREITEMSTRUCT)lParam); break; case WM_COMPAREITEM: ASSERT(pResult != NULL); // return value expected *pResult = CompareItem((LPCOMPAREITEMSTRUCT)lParam); break; case WM_DELETEITEM: ASSERT(pResult == NULL); // no return value expected DeleteItem((LPDELETEITEMSTRUCT)lParam); break; default: return CWnd::OnChildNotify(message, wParam, lParam, pResult); } return TRUE; } void CComboBox::GetLBText(int nIndex, CString& rString) const { ASSERT(::IsWindow(m_hWnd)); GetLBText(nIndex, rString.GetBufferSetLength(GetLBTextLen(nIndex))); rString.ReleaseBuffer(); }
------解决方案--------------------
ListBox下面不该有别的控件,Combo中的list也有这个问题,只是combo中你一点,list就收起来了。你可以用‘simple’的combo试试,同样有你说的问题。
要模拟就要模拟list收起来。这样就好了。
------解决方案--------------------
- C/C++ code
//重写CComboBox类,处理WM_CTLCOLORLISTBOX消息 HWND m_hTreeWnd = NULL; LRESULT CNewComboBo::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) { // TODO: Add your specialized code here and/or call the base class if(WM_CTLCOLORLISTBOX == message) { HWND hListBox = (HWND)lParam; if(NULL == m_hTreeWnd) { RECT rc; ::GetClientRect(hListBox, &rc); m_hTreeWnd = CreateWindow(_T("SysTreeView32"), _T("TreeView"), WS_CHILD | WS_VISIBLE | TVS_FULLROWSELECT | TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, hListBox, (HMENU)0x11, AfxGetInstanceHandle(), NULL); TVINSERTSTRUCT tvs; TVITEM tvi; tvi.mask = TVIF_TEXT; tvi.pszText = _T("AAA"); tvs.hInsertAfter = TVI_LAST; tvs.hParent = TVI_ROOT; tvs.item = tvi; HTREEITEM hItem = TreeView_InsertItem(m_hTreeWnd, &tvs); tvi.pszText = _T("BBB"); tvs.item = tvi; TreeView_InsertItem(m_hTreeWnd, &tvs); } } return CComboBox::WindowProc(message, wParam, lParam); }
------解决方案--------------------
可以解决这个问题:
在PreTranslateMessage(MSG* pMsg)中,检查pMsg->pt,看是不是在LISTBOX内,如果是则:
m_LisrBox.SetCapture()
否则:
ReleaseCapture();