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

自定义OwnerDraw ToolTip控件尺寸异常问题

解决自定义OwnerDraw ToolTip文本截断问题

我之前开发WinForms自定义控件时也碰到过几乎一模一样的问题——OwnerDraw模式下的ToolTip文本过长时末尾字符莫名丢失,而且截断情况还和文本长度挂钩。给你几个实际排查和解决的思路,应该能帮你定位问题:

1. 重点检查MeasureItem事件的尺寸计算逻辑

OwnerDraw控件的大小完全由这个事件里的计算结果决定,90%的文本截断问题都出在这里。你需要确保:

  • 使用和系统绘制一致的文本测量方法:优先用TextRenderer.MeasureText,而不是Graphics.MeasureString——后者的测量结果和实际绘制的文本尺寸经常有偏差,尤其是处理不同字体、字号的时候。
  • 记得加上ToolTip默认的内边距:原生ToolTip的内边距是左右各5px、上下各2px,如果你没加这个,计算出来的宽度会比实际需要的窄,导致文本被截断。

示例代码参考:

protected override void OnMeasureItem(MeasureItemEventArgs e)
{
    // 测量文本的实际尺寸
    Size textSize = TextRenderer.MeasureText(this.Text, this.Font);
    
    // 加上内边距,得到控件的最终尺寸
    e.ItemWidth = textSize.Width + 10; // 左右各5px,总共加10
    e.ItemHeight = textSize.Height + 4; // 上下各2px,总共加4
    
    base.OnMeasureItem(e);
}

2. 确认DrawItem事件的绘制范围没有裁剪文本

就算尺寸计算对了,绘制时的矩形范围设置错误也会导致文本截断。绘制文本时要基于MeasureItem确定的尺寸,减去内边距后再绘制,同时避免使用会强制裁剪的文本格式:

protected override void OnDrawItem(DrawItemEventArgs e)
{
    e.DrawBackground();
    
    // 计算文本绘制的矩形(减去内边距)
    Rectangle textDrawRect = new Rectangle(
        e.Bounds.X + 5, 
        e.Bounds.Y + 2, 
        e.Bounds.Width - 10, 
        e.Bounds.Height - 4
    );
    
    // 使用TextRenderer绘制,指定合适的格式(比如允许自动换行)
    TextRenderer.DrawText(
        e.Graphics, 
        this.Text, 
        this.Font, 
        textDrawRect, 
        this.ForeColor, 
        TextFormatFlags.WordBreak | TextFormatFlags.Left
    );
    
    e.DrawFocusRectangle();
    base.OnDrawItem(e);
}

如果你的需求是单行显示,不要用TextFormatFlags.SingleLine搭配固定宽度,而是确保MeasureItem计算的宽度足够容纳单行文本。

3. 排查高DPI缩放的影响

如果你的程序运行在高DPI显示器上,没有处理DPI缩放的话,测量的尺寸会和实际显示的尺寸不匹配,导致文本被截断。可以通过Graphics对象的DPI属性来调整测量结果:

protected override void OnMeasureItem(MeasureItemEventArgs e)
{
    float dpiScale = e.Graphics.DpiX / 96f; // 96是标准DPI
    Size textSize = TextRenderer.MeasureText(this.Text, this.Font);
    
    // 按DPI比例缩放尺寸
    int scaledWidth = (int)(textSize.Width * dpiScale);
    int scaledHeight = (int)(textSize.Height * dpiScale);
    
    e.ItemWidth = scaledWidth + 10;
    e.ItemHeight = scaledHeight + 4;
    
    base.OnMeasureItem(e);
}

另外,确保你的窗体或控件的AutoScaleMode设置为AutoScaleMode.Dpi,让WinForms自动处理基础的缩放逻辑。

4. 检查自定义Text属性的重写逻辑

如果你重写了ToolTip的Text属性,有没有可能在赋值时不小心截断了文本?比如做了长度限制或者字符串处理,这也会导致末尾字符丢失。

如果上面的方法都试过还是没解决问题,建议把你的MeasureItem和DrawItem的完整代码贴出来,这样更容易精准定位问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 08:08:04