文本溢出用于DataGridView的自定义单元绘画

时间:2018-07-20 11:49:41

标签: 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;

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

1 个答案:

答案 0 :(得分:2)

通过CellPainting事件,您可以绘制到DataGridView整个可见区域,包括所有标题,仅包括滚动条。

它确实为您提供了Cell矩形中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);

现在,您绘制的所有内容都不会溢出。

注意:

  • 您还可以同时为DrawTextDrawString设置目标矩形,但是使用不同的字体绘制会更加困难。
  • 由于某些原因,剪切的区域似乎不适用于TextRenderer

还请注意:我无法再现下溢到标头中的效果。我可以想象,如果顶部的单元格不是很完全可见,则可能来自单元格的顶部,可能是负值。 (不过,我的DGV只允许我按整数行滚动。)要排除这些情况,您可能需要计算一个更好的剪切矩形,该矩形仅在标题单元格的下方开始。