Forcing a combobox to “dropdown” above instead of below
当您单击组合框的"下拉"按钮时,下拉列表框将显示在组合框下方,除非下面没有足够的空间,在这种情况下,该列表框将显示在上方。
现在我想知道是否有可能迫使lisbox出现在组合框的上方,即使下面有足够的空间。
插图
当我单击组合框时,我希望"下拉列表"列表框始终显示在左侧屏幕副本的上方。
一切皆有可能,并且您无需实现"从头开始"控件。
首先,您可以对ComboBox的ListBox部分进行子类化,以完全控制它,如MSDN中所述。您可以使用类向导创建从CListBox派生的类。您只需要在其中实现
1 2 3 4 5 6 7 8 | void CTopListBox::OnWindowPosChanging(WINDOWPOS* lpwndpos) { CListBox::OnWindowPosChanging(lpwndpos); if ((lpwndpos->flags & SWP_NOMOVE) == 0) { lpwndpos->y -= lpwndpos->cy + 30; } } |
在这里,为简单起见,我将盒子向上移(高度30)。您可以获取ComboBox的高度,而不是我的
然后在对话框类中声明一个成员变量:
1 | CTopListBox m_listbox; |
并像这样子类化:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | HBRUSH CMFCDlgDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) { if (nCtlColor == CTLCOLOR_LISTBOX) { if (m_listbox.GetSafeHwnd() == NULL) { m_listbox.SubclassWindow(pWnd->GetSafeHwnd()); CRect r; m_listbox.GetWindowRect(r); m_listbox.MoveWindow(r); } } HBRUSH hbr = CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor); return hbr; } |
请注意,我在那里打电话给
免责声明:这不是一个很干净的解决方案,因为如果启用了Windows动画,您会看到列表从上到下展开。
或者,您应该能够"愚弄"组合框,使其过于靠近屏幕底部;然后它会自行下降。我把它留给读者作为练习:)
这将相对容易,除非组合框具有"滑盖打开"效果。如果将下拉列表框移到顶部,并且组合幻灯片从上到下打开,则看起来很奇怪。因此,您必须禁用动画或将其反转。
在此函数中,我在
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | class CComboBox_ListBox : public CListBox { public: CWnd *comboBox; void OnWindowPosChanging(WINDOWPOS *wndpos) { CListBox::OnWindowPosChanging(wndpos); if (comboBox && wndpos->cx && wndpos->cy && !(wndpos->flags & SWP_NOMOVE)) { CRect rc; comboBox->GetWindowRect(&rc); //if listbox is at the bottom... if (wndpos->y > rc.top) { //if there is enough room for listbox to go on top... if (rc.top > wndpos->cy) { wndpos->y = rc.top - wndpos->cy; BOOL animation; SystemParametersInfo(SPI_GETCOMBOBOXANIMATION, 0, &animation, 0); //if combobox slides open... if (animation) { //we have to set the x coordinate otherwise listbox //is in the wrong place when parent window moves SetWindowPos(0, wndpos->x, wndpos->y, 0, 0, SWP_NOSENDCHANGING | SWP_HIDEWINDOW | SWP_NOSIZE); AnimateWindow(100, AW_VER_NEGATIVE); } } } } } DECLARE_MESSAGE_MAP() }; |
用法:
1 2 3 4 5 | COMBOBOXINFO ci = { sizeof(COMBOBOXINFO) }; comboBox.GetComboBoxInfo(&ci); CComboBox_ListBox *listBox = new CComboBox_ListBox; listBox->comboBox = &comboBox; listBox->SubclassWindow(ci.hwndList); |
还可以使用