c# - Windows 窗体 ComboBox 下拉位置

标签 c# .net winforms combobox

enter image description here

通常下拉项的起始位置与 ComboBox 的起始位置对齐,如上图所示。 但我需要开发 ComboBox 控件,它具有冗长的下拉项并在中间对齐。我的意思是下拉项的左侧位置应该比 ComboBox 更靠左,如下图所示。任何帮助将不胜感激。

enter image description here

最佳答案

这是一个扩展 ComboBox它有 2 个有用的新功能,可让您设置下拉菜单的位置和大小:

  • DropDownAlignment:您可以将它设置为Left,然后下拉菜单将出现在它的正常位置并且它的左边与控件的左边对齐。如果将其设置为Middle,则下拉菜单的中间将与控件对齐,如果将其设置为Right,则下拉的右侧将与控件对齐控制权。

  • AutoWidthDropDown:如果将其设置为true,则DropdownWidth 将设置为最长项目的宽度。如果将其设置为 false,它会将 Width 用作 DropDownWidth

这是将 AutoWidthDropDown 设置为 true 并将 DropDownAlignment 设置为 Left 后下拉菜单的外观,中间右边:

Left

Middle

Right

实现 - ComboBox 与 DropDown Position 和 AutoWith DropDown

你可以处理WM_CTLCOLORLISTBOX消息,lparam 是下拉菜单的句柄,然后您可以使用 SetWindowPos 设置下拉菜单的位置.

如果 AutoWidthDropDown 为真,您还可以计算最长项目的宽度并设置为 DropDownWidth

using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Linq;
public class MyComboBox : ComboBox
{
    private const UInt32 WM_CTLCOLORLISTBOX = 0x0134;
    private const int SWP_NOSIZE = 0x1;
    [DllImport("user32.dll")]
    static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter,
        int X, int Y, int cx, int cy, uint uFlags);
    public enum DropDownAlignments { Left = 0, Middle, Right }
    public bool AutoWidthDropDown { get; set; }
    public DropDownAlignments DropDownAlignment { get; set; }
    protected override void WndProc(ref Message m)
    {
        if (m.Msg == WM_CTLCOLORLISTBOX)  {
            var bottomLeft = this.PointToScreen(new Point(0, Height));
            var x = bottomLeft.X;
            if (DropDownAlignment == MyComboBox.DropDownAlignments.Middle)
                x -= (DropDownWidth - Width) / 2;
            else if (DropDownAlignment == DropDownAlignments.Right)
                x -= (DropDownWidth - Width);
            var y = bottomLeft.Y;
            SetWindowPos(m.LParam, IntPtr.Zero, x, y, 0, 0, SWP_NOSIZE);
        }
        base.WndProc(ref m);
    }
    protected override void OnDropDown(EventArgs e)
    {
        if (AutoWidthDropDown)
            DropDownWidth = Items.Cast<Object>().Select(x => GetItemText(x))
                  .Max(x => TextRenderer.MeasureText(x, Font,
                       Size.Empty, TextFormatFlags.Default).Width);
        else
            DropDownWidth = this.Width;
        base.OnDropDown(e);
    }
}

关于c# - Windows 窗体 ComboBox 下拉位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39019644/

相关文章:

c# - SQL 更新在使用 C# 的 asp.net 中不起作用

.net - Entity Framework 6 with SQLite 3 Code First - 不会创建表

c# - 在没有 UAC 提示的情况下从 .NET 应用程序执行进程

c# - 我们可以在 Window Forms (.Net) 应用程序中使用 Google Ads 吗?

c# - SQLite 错误 : Failed to find or load the registered .Net Framework 数据提供程序

C# 隐藏枚举集合/公共(public)和私有(private)选项可访问性的一部分的可见性

c# - 在 ASP.NET MVC 2 中,我可以使用默认的 ModelBinder 将查询字符串反序列化为数组吗?

c# - 处理双 NaN 和 Inf 时的 ILASM 问题

c# - 参数字典包含不可为 null 类型 'id' 的参数 'System.Int32' 的 null 条目

c# - 禁用 TreeView 节点焦点提示