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
相关产品推荐
相关产品推荐

