DataGridView 的自定义单元格绘制的文本溢出

Ani*_*nil 5 c# visual-studio winforms

这是我的细胞绘画方法。

DataGridView grid = (DataGridView)sender;

if ( e.RowIndex == -1 || e.ColumnIndex == -1 )
{ return; }
if ( ( grid.Rows [ e.RowIndex ].Cells [ e.ColumnIndex ].Value == null ) )
    return;

Brush gridBrush = new SolidBrush(GridList[0].GridColor),backColorBrush = new SolidBrush(e.CellStyle.BackColor);
Pen gridLinePen = new Pen(gridBrush);

// Erase the cell.
e.Graphics.FillRectangle ( backColorBrush, e.CellBounds );

// Draw the grid lines (only the right and bottom lines;
// DataGridView takes care of the others).
e.Graphics.DrawLine ( gridLinePen, e.CellBounds.Left, e.CellBounds.Bottom - 1, e.CellBounds.Right - 1, e.CellBounds.Bottom - 1 );
e.Graphics.DrawLine ( gridLinePen, e.CellBounds.Right - 1, e.CellBounds.Top, e.CellBounds.Right - 1, e.CellBounds.Bottom );

// Draw the text content of the cell, ignoring alignment.
if ( e.Value != null )
{
    Brush brush = new SolidBrush(Color.Red);
    Brush brush1 = new SolidBrush(Color.Black);
    String s = (String)e.Value;

    System.Drawing.Rectangle rect = e.CellBounds;
    List<int> pos = null;
    if ( grid.Rows [ e.RowIndex ].Cells [ e.ColumnIndex ].Tag != null )
    {
        pos = ( List<int> ) grid.Rows [ e.RowIndex ].Cells [ e.ColumnIndex ].Tag;
    }

    String[] arr = s.Split('\n');
    SizeF stringSize = TextRenderer.MeasureText(e.Graphics, arr[0], e.CellStyle.Font, e.CellBounds.Size);

    float wid = stringSize.Height;
    int X,Y;

    for ( int i = 0; i < arr.Length; i++ )
    {
        if ( pos == null || pos.IndexOf ( i ) == -1 )
        {
            X = ( e.CellBounds.X );
            Y = ( e.CellBounds.Y + i * ( ( int ) stringSize.Height ) );
            TextRenderer.DrawText ( e.Graphics, arr [ i ], e.CellStyle.Font, new Point ( X, Y ), SystemColors.ControlText );
            //e.Graphics.DrawString(arr[i], e.CellStyle.Font, brush1, new PointF(X, Y), StringFormat.GenericDefault);
        }
        else
        {
            X = ( e.CellBounds.X );
            Y = ( e.CellBounds.Y + i * ( int ) stringSize.Height );
            Brush brushForBox = new SolidBrush(Color.FromArgb(100, 120, 50,0));
            e.Graphics.FillRectangle ( brushForBox, X, Y, e.CellBounds.Width, ( int ) stringSize.Height );
            TextRenderer.DrawText ( e.Graphics, arr [ i ], e.CellStyle.Font, new Point ( X, Y ), SystemColors.ControlText );
            //e.Graphics.DrawString(arr[i], e.CellStyle.Font, brush, new PointF(X, Y), StringFormat.GenericDefault);
        }
    }
}
//grid.InvalidateCell(-1, e.RowIndex);
e.Handled = true;
Run Code Online (Sandbox Code Playgroud)

现在它工作正常,但第一个和最后一个单元格的文本溢出。例如,如果第一个单元格dataGridView部分可见,则文本将呈现在行标题中。同样,对于行中的最后一个单元格,文本从其中流出。任何建议/解决方案表示赞赏。

TaW*_*TaW 3

该事件将允许您在的整个可见区域CellPainting上绘图,包括所有标题,仅不包括滚动条。DataGridView

它确实为您提供了矩形Cell中的 s 区域e.CellBounds,但它仍然允许您在其外部进行绘制。

将绘图限制为Cell最简单的方法是将 更改e.Graphics.ClipBounds为单元格的边界矩形;为了确保不会发生溢出到行标题的情况,我们将其限制为仅从行标题的左侧开始,可能如下所示:

int rhw = grid.RowHeadersWidth;
Rectangle clip = e.CellBounds;
if (e.CellBounds.X < rhw)
    clip = new Rectangle(rhw, clip.Y, clip.Width - rhw, clip.Height);
e.Graphics.SetClip(clip, CombineMode.Replace);
Run Code Online (Sandbox Code Playgroud)

现在你绘制的任何东西都不会溢出。

笔记:

  • 您还可以为DrawTextDrawString设置目标矩形,但使用不同的字体绘制会使这变得有点困难。
  • 由于某种原因,剪切区域似乎不适用于TextRenderer.

另请注意:我无法重现下溢到标题中的效果。我可以想象,如果顶部电池不太完全可见,它可能来自位于负极的电池顶部罐。(不过,我的 DGV 只允许我滚动整行。)要排除这些情况,您可能需要计算一个更好的剪切矩形,该矩形仅从标题单元格正下方开始。