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

如何实现带滚动字幕效果的C# WinForms DataGridViewTextBoxCell?

DataGridView单元格跑马灯效果实现方案

该需求完全可行,以下是具体实现思路和代码示例,解决你之前遇到的卡顿、无法部分绘制字符的问题:

核心实现思路

  1. 自定义DataGridViewTextBoxCell,维护滚动偏移量与定时器,通过定时器逐像素调整偏移量实现平滑滚动
  2. 重写Paint方法,利用文本裁剪绘制实现部分文本显示,替代逐字符修改formattedValue的方案
  3. 仅当文本长度超出单元格宽度时启动定时器,减少不必要的性能消耗

代码实现

自定义跑马灯单元格类

public class MarqueeDataGridViewTextBoxCell : DataGridViewTextBoxCell
{
    private int _scrollOffset;
    private Timer _scrollTimer;
    private int _textWidth;
    private string _currentText;

    public MarqueeDataGridViewTextBoxCell()
    {
        // 设置50ms间隔,实现平滑滚动
        _scrollTimer = new Timer { Interval = 50 };
        _scrollTimer.Tick += ScrollTimer_Tick;
    }

    private void ScrollTimer_Tick(object sender, EventArgs e)
    {
        if (OwningColumn == null || OwningRow == null) return;

        // 更新当前文本与宽度,避免文本变化时偏移混乱
        var formattedText = GetFormattedValue(Value, OwningRow.Index, ref Style, null, null, DataGridViewDataErrorContexts.Display)?.ToString() ?? string.Empty;
        if (formattedText != _currentText)
        {
            _currentText = formattedText;
            _textWidth = TextRenderer.MeasureText(formattedText, Style.Font).Width;
            _scrollOffset = 0;
        }

        // 文本未超出宽度时停止滚动
        if (_textWidth <= ContentBounds.Width)
        {
            _scrollTimer.Stop();
            return;
        }

        // 逐像素调整偏移量,超出文本宽度后重置
        _scrollOffset += 1;
        if (_scrollOffset > _textWidth)
        {
            _scrollOffset = -ContentBounds.Width;
        }

        // 重绘当前单元格
        OwningRow.Cells[ColumnIndex].Invalidate();
    }

    protected override void Paint(Graphics graphics, Rectangle clipBounds, Rectangle cellBounds, int rowIndex, DataGridViewElementStates cellState, object value, object formattedValue, string errorText, DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts)
    {
        // 调用基类绘制但跳过文本内容,避免重复绘制
        base.Paint(graphics, clipBounds, cellBounds, rowIndex, cellState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts & ~DataGridViewPaintParts.ContentForeground);

        var text = formattedValue?.ToString() ?? string.Empty;
        var contentBounds = cellStyle.Padding.ApplyPadding(cellBounds);
        _textWidth = TextRenderer.MeasureText(text, cellStyle.Font).Width;

        // 文本未超出宽度时正常绘制
        if (_textWidth <= contentBounds.Width)
        {
            TextRenderer.DrawText(graphics, text, cellStyle.Font, contentBounds, cellStyle.ForeColor, TextFormatFlags.Left | TextFormatFlags.VerticalCenter);
            _scrollTimer.Stop();
            return;
        }

        // 启动定时器(仅未启动时)
        if (!_scrollTimer.Enabled)
        {
            _scrollTimer.Start();
        }

        // 计算绘制区域,通过裁剪实现部分文本显示
        var drawRect = new Rectangle(contentBounds.X - _scrollOffset, contentBounds.Y, _textWidth, contentBounds.Height);
        using (var clipRegion = new Region(contentBounds))
        {
            graphics.Clip = clipRegion;
            TextRenderer.DrawText(graphics, text, cellStyle.Font, drawRect, cellStyle.ForeColor, TextFormatFlags.Left | TextFormatFlags.VerticalCenter);
            graphics.ResetClip();
        }
    }

    // 释放定时器资源,防止内存泄漏
    protected override void Dispose(bool disposing)
    {
        if (disposing)
        {
            _scrollTimer?.Dispose();
        }
        base.Dispose(disposing);
    }
}

自定义列类(方便在设计器中使用)

public class MarqueeDataGridViewTextBoxColumn : DataGridViewTextBoxColumn
{
    public MarqueeDataGridViewTextBoxColumn()
    {
        CellTemplate = new MarqueeDataGridViewTextBoxCell();
    }
}

关键说明

  • 使用TextRenderer替代Graphics.DrawString,确保文本绘制精度,避免字符截断问题
  • 定时器间隔设为50ms、滚动步长1像素,实现接近原生的平滑滚动效果,解决逐字符滚动的卡顿感
  • 仅在文本超出单元格宽度时启动定时器,单元格不可见或文本长度不足时自动停止,优化性能
  • 通过Region裁剪绘制区域,实现文本的部分显示,无需修改formattedValue

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 15:45:19