如何为重写OnPaint的ToolStripStatusLabel子类添加缺失属性支持?
完善SpringLabel类以支持ToolStripStatusLabel原有属性
问题背景
我实现了一个继承自ToolStripStatusLabel的SpringLabel类,开启Spring属性并重写OnPaint方法实现了超长文本的省略显示,但该类缺失父控件的BorderSides、图片等属性支持。现有@Hans提供的解决方案代码可正常运行,但仍不支持图片属性,且要求父StatusStrip控件的LayoutStyle设为默认的Table。
现有代码的问题
现有方案重新定义了Text属性,导致与父类的属性逻辑脱节;同时在OnPaint中先调用base.OnPaint再叠加绘制文本,会导致原文本和新绘制的省略文本重叠,且父类的图片、边框绘制逻辑被干扰或未正确复用。
完善后的实现方案
要复用ToolStripStatusLabel的原有行为,核心是不破坏父类的属性体系,仅在文本绘制环节做省略处理,同时保留父类对图片、边框等属性的绘制逻辑:
[ToolStripItemDesignerAvailability(ToolStripItemDesignerAvailability.StatusStrip)] public class SpringLabel : ToolStripStatusLabel { public SpringLabel() { Spring = true; // 绑定ToolTip到父类Text属性,无需自定义字段 ToolTipText = Text; } // 重写Text属性的setter,同步更新ToolTip和触发重绘 public override string Text { get => base.Text; set { base.Text = value; ToolTipText = value; Invalidate(); } } protected override void OnPaint(PaintEventArgs e) { // 先让父类完成边框、图片等元素的绘制 base.OnPaint(e); // 计算文本绘制的有效区域:排除图片和内边距 var contentRect = GetTextBounds(); if (contentRect.Width <= 0 || string.IsNullOrEmpty(Text)) return; // 使用TextRenderer绘制带省略号的文本,对齐方式与父类保持一致 var textFormatFlags = GetTextFormatFlags(); TextRenderer.DrawText(e.Graphics, Text, Font, contentRect, ForeColor, textFormatFlags); } // 获取文本实际绘制区域,考虑图片、内边距和边框 private Rectangle GetTextBounds() { var bounds = ClientRectangle; // 调整区域以排除图片占用的空间 if (Image != null) { bounds.X += Image.Width + ImageMargin.Horizontal; bounds.Width -= Image.Width + ImageMargin.Horizontal; } // 减去内边距 bounds.X += Padding.Left; bounds.Width -= Padding.Left + Padding.Right; // 减去边框占用的空间 if (BorderSides != ToolStripStatusLabelBorderSides.None) { var borderWidth = SystemInformation.Border3DSize.Width; bounds.X += borderWidth; bounds.Width -= borderWidth * 2; } return bounds; } // 获取与父类一致的文本格式标记,包含省略号设置 private TextFormatFlags GetTextFormatFlags() { var flags = TextFormatFlags.EndEllipsis | TextFormatFlags.VerticalCenter; // 对齐方式与父类TextAlign保持一致 switch (TextAlign) { case ContentAlignment.TopLeft: flags |= TextFormatFlags.Top | TextFormatFlags.Left; break; case ContentAlignment.TopCenter: flags |= TextFormatFlags.Top | TextFormatFlags.HorizontalCenter; break; case ContentAlignment.TopRight: flags |= TextFormatFlags.Top | TextFormatFlags.Right; break; case ContentAlignment.MiddleLeft: flags |= TextFormatFlags.Left; break; case ContentAlignment.MiddleCenter: flags |= TextFormatFlags.HorizontalCenter; break; case ContentAlignment.MiddleRight: flags |= TextFormatFlags.Right; break; case ContentAlignment.BottomLeft: flags |= TextFormatFlags.Bottom | TextFormatFlags.Left; break; case ContentAlignment.BottomCenter: flags |= TextFormatFlags.Bottom | TextFormatFlags.HorizontalCenter; break; case ContentAlignment.BottomRight: flags |= TextFormatFlags.Bottom | TextFormatFlags.Right; break; } return flags; } }
关键改进点
- 复用父类属性体系:不再自定义
_sltext字段,直接重写Text属性的setter,同步更新ToolTipText,保证与父类属性逻辑一致。 - 保留原有绘制逻辑:先调用
base.OnPaint完成边框、图片等元素的绘制,仅在父类绘制基础上覆盖处理后的文本。 - 适配图片与边框:通过
GetTextBounds方法计算排除图片、内边距和边框后的文本区域,确保文本绘制位置正确。 - 对齐方式兼容:通过
GetTextFormatFlags方法匹配父类的TextAlign设置,保持原有对齐行为。
注意事项
Spring属性本身依赖StatusStrip的LayoutStyle为Table,这是ToolStrip控件的原生布局逻辑,无法完全规避。- 若需要支持更多父类属性(如
BorderStyle),可在GetTextBounds或OnPaint中进一步适配父类的属性值。
内容的提问来源于stack exchange,提问作者Steve Stover
相关产品推荐
相关产品推荐

