【问题标题】:Text overflows for custom cell painting of DataGridViewDataGridView 的自定义单元格绘制的文本溢出
【发布时间】:2018-07-23 17:32:55
【问题描述】:

这是我的细胞画法

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 中的第一个单元格部分可见,则文本将呈现在行标题中。同样,对于行中的最后一个单元格,文本会从其中流出。任何建议/解决方案表示赞赏。

【问题讨论】:

  • 尝试使用 DrawString 的重载或推荐的 (!) DrawText 与目标矩形。当然,如果文本不适合矩形,现在将被截断..
  • @TaW 我已经尝试过 DrawString 但对于多行文本不能正常工作。我没有明白你的意思“带有目标矩形的DrawText”你能解释一下吗?只是为了让你知道我写这篇文章是为了突出显示 datagridview 单元格中的某一行文本。
  • @ArunPratap 您提到的问题是在两个单元格之间绘制更粗的线,这与我的问题相去甚远。就我而言,我有一个文本溢出问题。您至少应该先完成这两个问题。

标签: c# visual-studio winforms


【解决方案1】:

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

它确实在e.CellBounds 矩形中为您提供了Cell 的区域,但它仍然可以让您在它之外绘制。

要将您的绘图限制为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 只允许我按整行滚动。)要排除这些情况,您可能需要计算一个更好的剪切矩形,该矩形仅从标题单元格的正下方开始..

【讨论】:

  • 行标题发生下溢,而不是列标题。事实上,DGV 只允许整行滚动,但列的情况并非如此。因此,当单元格的某些内容位于行标题下并且您将鼠标悬停在其上方时,只会重新绘制单元格而不是标题(或其他方式),并且标题下的文本变得可见。我可以使用 e.ClipBounds 但问题是我找不到我需要从哪个字符开始我的字符串。
  • 啊,明白了。我已经更新了答案以防止溢出。如果发现剪裁工作正常,即文本被剪裁到左边。
  • 在旁注中,CombineMode.Union 的效果要好于 Replace 在我的情况下我真的不明白为什么。
  • 嗯,这听起来不对。如果它有效,那很好,但它真的不应该改变剪辑区域,因为单元格边界已经包含在旧的 ClipRegion 中。 - 另外:你所说的“效果更好”是什么意思?
  • 我怀疑 TextRenderer 不遵循的事实是 b/c GDI 兼容模式。:docs.microsoft.com/en-us/dotnet/api/…
猜你喜欢
  • 1970-01-01
  • 2011-08-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-05
相关资源
最近更新 更多