You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C# WinForms自定义ListBox:取消文本换行,显示水平滚动条

嘿,我碰到过类似的问题,OwnerDraw模式下的ListBox确实不会自动帮你处理水平滚动的逻辑——毕竟你接管了绘制工作,控件默认没法感知你要显示的文本实际宽度。咱们一步步来解决这个问题:

解决自定义OwnerDraw ListBox的水平滚动问题

1. 手动计算项的最大宽度,设置HorizontalExtent

ListBox的HorizontalScrollbar=true只是开启了滚动条的显示权限,但它不知道要滚动多远。你需要遍历所有项,计算文本的实际宽度,然后把HorizontalExtent设为这个最大值,滚动条才会生效。

可以添加一个方法来完成这个计算:

private void UpdateHorizontalExtent()
{
    if (Items.Count == 0) return;
    using (var graphics = CreateGraphics())
    {
        int maxTextWidth = 0;
        foreach (var item in Items)
        {
            string itemText = item.ToString();
            SizeF textSize = graphics.MeasureString(itemText, Font);
            maxTextWidth = Math.Max(maxTextWidth, (int)Math.Ceiling(textSize.Width));
        }
        // 加一点边距,避免文本紧贴滚动条
        HorizontalExtent = maxTextWidth + 10;
    }
}

然后在合适的时机调用它,比如构造函数、项集合变化时:

protected override void OnItemsChanged(EventArgs e)
{
    base.OnItemsChanged(e);
    UpdateHorizontalExtent();
}

2. 绘制文本时禁止自动换行

即使滚动条显示了,如果绘制文本时不指定不换行规则,文本还是会在控件可视宽度内自动折行。修改你的OnDrawItem方法:

protected override void OnDrawItem(DrawItemEventArgs e)
{
    e.DrawBackground();
    if ((e.State & DrawItemState.Focus) == DrawItemState.Focus)
        e.DrawFocusRectangle();

    // 确保索引有效,避免越界
    if (e.Index >= 0 && e.Index < Items.Count)
    {
        string itemText = Items[e.Index].ToString();
        // 创建不换行的字符串格式
        using (var stringFormat = new StringFormat(StringFormatFlags.NoWrap))
        {
            e.Graphics.DrawString(itemText, Font, new SolidBrush(ForeColor), e.Bounds, stringFormat);
        }
    }
}

3. 保持现有正确设置

你已经设置了DrawMode.OwnerDrawFixed和ItemHeight=20,这个是对的——Fixed模式下所有项高度统一,符合你的需求,继续保留即可。

把这些修改加上后,你的自定义ListBox就会显示水平滚动条,文本也不会自动换行了。

内容的提问来源于stack exchange,提问作者Seth

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 10:21:44