C#——ComboBox下拉选项过长显示不全的处理方法

我们需要重写ComboBox控件

class CustomCombox : ComboBox {
        protected override void OnDropDown(EventArgs e) {
            base.OnDropDown(e);
            AdjustComboBoxDropDownListWidth();
        }
 
        private void AdjustComboBoxDropDownListWidth() {
            int vertScrollBarWidth = (this.Items.Count > this.MaxDropDownItems) ? SystemInformation.VerticalScrollBarWidth : 0;
 
            int maxWidth = this.DropDownWidth;
            foreach (var layouts in this.Items) {
                int measureTextWidth = TextRenderer.MeasureText(layouts.ToString(), this.Font).Width;
                maxWidth = maxWidth < measureTextWidth ? measureTextWidth : maxWidth;
            }
 
            this.DropDownWidth = maxWidth + vertScrollBarWidth;
        }
    }

在winform编程中,combox是我们经常用到的控件,往往因为界面排版或者其它原因,comboBox的宽度受到限制,而下拉列表中的内容太长。如果按照combobox的默认设置 ,下拉列表和comboBox的宽度一样,并不会跟随内容的变化而变化,这就造成下拉列表中有些项的内容太长而不能全部显示出来,就是下面这个样子:
如果能够让下拉列表的宽度随着内容的变化而变化,这个问题不就解决了。下面我们看看如何让comboxBox的下拉列表宽度自适应内容的宽度:

private void AdjustComboBoxDropDownListWidth(object comboBox)
        {
            Graphics g = null;
            Font font = null;
            try
            {
                ComboBox senderComboBox = null;
                if (comboBox is ComboBox)
                    senderComboBox = (ComboBox)comboBox;
                else if (comboBox is ToolStripComboBox)
                    senderComboBox = ((ToolStripComboBox)comboBox).ComboBox;
                else
                    return;

                int width = senderComboBox.Width;
                g = senderComboBox.CreateGraphics();
                font = senderComboBox.Font;

                //checks if a scrollbar will be displayed.
                //If yes, then get its width to adjust the size of the drop down list.
                int vertScrollBarWidth =
                    (senderComboBox.Items.Count > senderComboBox.MaxDropDownItems)
                    ? SystemInformation.VerticalScrollBarWidth : 0;

                int newWidth;
                foreach (object s in senderComboBox.Items)  //Loop through list items and check size of each items.
                {
                    if (s != null)
                    {
                        newWidth = (int)g.MeasureString(s.ToString().Trim(), font).Width
                            + vertScrollBarWidth;
                        if (width < newWidth)
                            width = newWidth;   //set the width of the drop down list to the width of the largest item.
                    }
                }
                senderComboBox.DropDownWidth = width;
            }
            catch
            { }
            finally
            {
                if (g != null)
                    g.Dispose();
            }
        }

上面的方法,只要在我们向combox添加完所有项后,调用一下,就可以调整comboBox下拉列表的宽度了

private void button1_Click(object sender, EventArgs e)
        {
            comboBox1.Items.Add("美国");
            comboBox1.Items.Add("中华人民共和国");
            comboBox1.Items.Add("新疆维吾尔族自治区");
            AdjustComboBoxDropDownListWidth(comboBox1);
        }

到这里,问题并没有完结,如果每次在我们向comboBox中添加一项后,就要调用一下这个方法,那就太麻烦了。能不能把这种自适应宽度的功能集成到comboBox中呢?可以,这里我们继承ComboBox,实现一个自定义的控件,在用户每次打开下拉列表的时候,让控件自动调整下拉列表的宽度。
 

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;

namespace WindowsApplication2
{
    class MyComboBox : ComboBox
    {
        protected override void OnDropDown(EventArgs e)
        {
            base.OnDropDown(e);
            AdjustComboBoxDropDownListWidth();  //调整comboBox的下拉列表的大小
        }

        private void AdjustComboBoxDropDownListWidth()
        {
            Graphics g = null;
            Font font = null;
            try
            {
                int width = this.Width;
                g = this.CreateGraphics();
                font = this.Font;

                //checks if a scrollbar will be displayed.
                //If yes, then get its width to adjust the size of the drop down list.
                int vertScrollBarWidth =
                    (this.Items.Count > this.MaxDropDownItems)
                    ? SystemInformation.VerticalScrollBarWidth : 0;

                int newWidth;
                foreach (object s in this.Items)  //Loop through list items and check size of each items.
                {
                    if (s != null)
                    {
                        newWidth = (int)g.MeasureString(s.ToString().Trim(), font).Width
                            + vertScrollBarWidth;
                        if (width < newWidth)
                            width = newWidth;   //set the width of the drop down list to the width of the largest item.
                    }
                }
                this.DropDownWidth = width;
            }
            catch
            { }
            finally
            {
                if (g != null)
                    g.Dispose();
            }
        }
    }
}

combobox之下拉宽度自适应

从上图中可看到,combobox优化后可以自适应不同长度的字符串,保证每个字符串都能够显示完整。

实现过程
当我们触发CBN_DROPDOWN事件时,不再使用默认的实现,而是利用消息反射机制,重新计算下拉列表的宽度,具体步骤如下:

生成CMyComboBox类,这个类继承CComboBox
将CMyComboBox绑定combobox控件
响应CBN_DROPDOWN消息响应
重新计算最大的下拉列表长度
CMyComboBox类
 

类声明
class CMyComboBox : public CComboBox
{
    DECLARE_DYNAMIC(CMyComboBox)
 
public:
    CMyComboBox();
    virtual ~CMyComboBox();
 
protected:
    DECLARE_MESSAGE_MAP()
public:
    afx_msg void OnCbnDropdown();
};
BEGIN_MESSAGE_MAP(CMyComboBox, CComboBox)
//消息反射声明
ON_CONTROL_REFLECT(CBN_DROPDOWN, &CMyComboBox::OnCbnDropdown)
END_MESSAGE_MAP()
 
// CMyComboBox 消息处理程序
void CMyComboBox::OnCbnDropdown()
{
    CClientDC dc(this);
    int nWitdh = 10;
    int nSaveDC = dc.SaveDC();
 
    //获取字体信息,
    dc.SelectObject(GetFont());
 
    //计算最大的显示长度
    for (int i = 0; i < GetCount(); i++)
    {
        CString strLable = _T("");
        GetLBText(i, strLable);
 
        nWitdh = max(nWitdh,dc.GetTextExtent(strLable).cx);
    }
 
    //多增加的冗余宽度
    nWitdh += 10;
 
    //设置下拉列表宽度
    SetDroppedWidth(nWitdh);
    //恢复实际dc
    dc.RestoreDC(nSaveDC);
}

 

  • 4
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
你需要用到ComboBox和ListBox控件,然后将ListBox控件嵌入到ComboBox下拉框中。 代码示例: ``` // 创建一个ListBox控件 ListBox listBox1 = new ListBox(); listBox1.Dock = DockStyle.Fill; // 将需要滑动的选项添加到ListBox中 for (int i = 0; i < 20; i++) { listBox1.Items.Add("选项" + i.ToString()); } // 创建一个ComboBox控件 ComboBox comboBox1 = new ComboBox(); comboBox1.DropDownStyle = ComboBoxStyle.DropDown; comboBox1.DropDownHeight = 200; // 将ListBox控件嵌入到ComboBox下拉框中 comboBox1.DropDown += (sender, e) => { ComboBox cb = sender as ComboBox; if (cb == null) return; // 设置ListBox的位置和大小 listBox1.Location = new Point(0, cb.DropDownHeight); listBox1.Size = new Size(cb.DropDownWidth, cb.DropDownHeight); // 将ListBox添加到ComboBox下拉框中 cb.Controls.Add(listBox1); // 设置ListBox的滚动条可见 listBox1.ScrollAlwaysVisible = true; }; // 如果ListBox控件被点击,则将选中的文本显示ComboBox中 listBox1.SelectedIndexChanged += (sender, e) => { ListBox lb = sender as ListBox; if (lb == null) return; ComboBox cb = lb.Parent as ComboBox; if (cb == null) return; // 将选中的文本显示ComboBox中 cb.Text = lb.SelectedItem.ToString(); // 隐藏ListBox控件 lb.Parent.Controls.Remove(lb); }; // 将ComboBox添加到Form中 this.Controls.Add(comboBox1); ``` 这样,当你点击ComboBox下拉框时,就会弹出一个带有滚动条的ListBox控件,你可以通过滑动滚动条来选择选项,选择后会自动隐藏ListBox控件,并将选中的文本显示ComboBox中。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值