【问题标题】:How to check if combobox drop down list is revealed up or down?如何检查组合框下拉列表是向上还是向下显示?
【发布时间】:2012-02-08 11:05:31
【问题描述】:

我有从组合框继承的控制(实现 C#,.Net 2.0)。它有过滤和其他东西。为了保持 UI 正确,当过滤期间的项目数量下降时,下拉列表会更改其大小以适应剩余的项目数量(由 NativeMethods.SetWindowPos(...) 完成)。

有什么方法可以检查下拉列表是向上还是向下显示(字面意思) - 不是检查它是否打开,它是打开的,而是在哪个方向,向上或向下?

干杯,jbk

【问题讨论】:

  • 你还需要 GetWindowRect() 来找出它在哪里。
  • 是的,我找到了答案,但我需要等待 8 小时才能发布它,因为至少没有 100 分 :) 很快得到组合和下拉的句柄,从中获取矩形,然后比较两者。

标签: c# .net combobox drop-down-menu


【解决方案1】:

ComboBox 有两个事件(DropDownDropDownClosed)在下拉部分打开和关闭时触​​发,因此您可能希望将处理程序附加到它们以监视控件的状态。

另外,还有一个布尔属性 (DroppedDown) 应该告诉您当前状态。

【讨论】:

  • 是的,但实际上我想知道下拉菜单是向上还是向下显示(字面意思)。我的意思是我知道组合何时显示,但它可以向上或向下显示取决于屏幕上的组合框位置。
  • 哦,你的意思是下拉列表部分是显示在文本字段的上方还是下方?
  • 我不知道是否有一种干净的方法可以做到这一点。我只是戳了一下,可以通过反射(一个名为 dropDownHandle 的私有字段)获取下拉列表的 HWND,然后使用 Windows API 调用来获取它在屏幕上的位置——但这似乎是非常讨厌的hack,我当然不想在生产代码中做这样的事情:)
【解决方案2】:

ComboBox 向下或向上打开取决于它们必须打开的空间:如果它们下方有可用空间,它们将像往常一样向下打开,否则它们将向上打开。

因此,您只需检查它们下方是否有足够的空间即可知道。试试这个代码:

void CmbTestDropDown(object sender, EventArgs e)
{
    Point p = this.PointToScreen(cmbTest.Location);
    int locationControl = p.Y; // location on the Y axis
    int screenHeight = Screen.GetBounds(new Point(0,0)).Bottom; // lowest point
    if ((screenHeight - locationControl) < cmbTest.DropDownHeight)
        MessageBox.Show("it'll open upwards");
    else MessageBox.Show("it'll open downwards");
}

【讨论】:

  • 感谢解决方案,但在这里我想添加一些增强功能:DropDownHeight 没有正确测量,所以我得到了“Items.Count * ItemHeight”的大小,locationControl 应该是“p.Y + cmbTest.Bottom" 覆盖所有屏幕
【解决方案3】:

于是我找到了答案:

这里我们有两个组合框的句柄:

    /// <summary>
    /// Gets a handle to the combobox
    /// </summary>
    private IntPtr HwndCombo
    {
        get
        {
            COMBOBOXINFO pcbi = new COMBOBOXINFO();
            pcbi.cbSize = System.Runtime.InteropServices.Marshal.SizeOf(pcbi);
            NativeMethods.GetComboBoxInfo(this.Handle, ref pcbi);
            return pcbi.hwndCombo;
        }
    }

然后到组合框的下拉列表:

    /// <summary>
    /// Gets a handle to the combo's drop-down list
    /// </summary>
    private IntPtr HwndDropDown
    {
        get
        {
            COMBOBOXINFO pcbi = new COMBOBOXINFO();
            pcbi.cbSize = System.Runtime.InteropServices.Marshal.SizeOf(pcbi);
            NativeMethods.GetComboBoxInfo(this.Handle, ref pcbi);
            return pcbi.hwndList;
        }
    }

现在,我们可以从句柄获取矩形:

    RECT comboBoxRectangle;
    NativeMethods.GetWindowRect((IntPtr)this.HwndCombo, out comboBoxRectangle);

    // get coordinates of combo's drop down list
    RECT dropDownListRectangle;
    NativeMethods.GetWindowRect((IntPtr)this.HwndDropDown, out dropDownListRectangle);

现在我们可以检查了:

    if (comboBoxRectangle.Top > dropDownListRectangle.Top)
    {
         ....
    }

【讨论】:

    猜你喜欢
    • 2014-07-11
    • 1970-01-01
    • 2017-09-02
    • 1970-01-01
    • 1970-01-01
    • 2012-03-26
    • 2011-02-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多