C# WinForm访问Chart后DataGridView DrawString绘制文字偏淡问题
问题描述
项目中多个DataGridView控件在CellPainting()事件处理方法中调用Graphics.DrawString()为指定列绘制自定义显示值,正常场景下文字渲染无异常。独立WinForm窗体中放置了DataVisualization.Charting.Chart控件用于展示简单折线图,存在如下异常现象:
- 若先打开查看Chart图表,再查看自定义绘制的DataGridView单元格,
DrawString()方法绘制出的文字会明显比正常效果更浅淡,即使手动将FontStyle从Regular修改为Bold,异常场景下绘制出的文字仍为Regular字重,无加粗效果 - 若先查看任意一个自定义绘制的DataGridView,再打开查看Chart图表,所有自定义绘制的单元格文字会始终保持正常显示效果
已完成的排查操作:
- 对比两种测试场景下的Graphics、Font对象,二者属性完全一致
- 尝试创建静态Font对象供
DrawString()调用,问题无任何改善
从现象判断,Chart控件似乎会以某种方式影响后续DrawString()调用时Font使用的FontWeight属性。因业务项目代码体量过大无法直接贴出,可编写简易双窗体应用复现问题,检索公开资料未找到同类问题反馈,现征集排查思路、解决方案或建议。
附:DataGridView CellPainting事件处理代码示例
private void GridView_CellPainting(object sender, DataGridViewCellPaintingEventArgs e) { if (e.ColumnIndex == 3 && e.RowIndex >= 0) { Rectangle cellRect = new Rectangle(e.CellBounds.X + 1, e.CellBounds.Y + 1, e.CellBounds.Width - 2, e.CellBounds.Height - 2); Color rowBackColor = dataGridView.Rows[e.RowIndex].DefaultCellStyle.BackColor; Color rowForeColor = SystemColors.WindowText; if (dataGridView.Rows[e.RowIndex].Selected) { rowBackColor = SystemColors.Highlight; rowForeColor = SystemColors.HighlightText; } using (Brush gridBrush = new SolidBrush(dataGridView.GridColor), foreColorBrush = new SolidBrush(rowForeColor), backColorBrush = new SolidBrush(rowBackColor)) { using (Pen gridLinePen = new Pen(gridBrush)) { // 擦除单元格原有内容 e.Graphics.FillRectangle(backColorBrush, e.CellBounds); // 绘制网格线(仅绘制右侧、底部线条,其余线条由DataGridView自身处理) 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); // 绘制单元格自定义文本内容 if (e.Value != null) { int measureId = Convert.ToInt32(e.Value.ToString()); string displayValue = ConvertToMeasure(measureId); StringFormat stringFormat = new StringFormat(StringFormat.GenericDefault) { Alignment = StringAlignment.Near }; e.Graphics.DrawString(displayValue, e.CellStyle.Font, foreColorBrush, cellRect, stringFormat); } e.Handled = true; } } } }
问题根因与解决方案
该问题是老版本System.Windows.Forms.DataVisualization的已知状态泄漏Bug:Chart控件在GDI+渲染完成后,不会恢复修改过的进程全局GDI+文本渲染默认配置,会把全局默认文本渲染模式改为低质量、无加粗提示的模式;如果先加载渲染DataGridView,GDI+会提前完成字体缓存初始化,后续Chart修改的全局状态不会覆盖已生成的字体缓存,因此显示正常。
可通过以下任意一种方式修复:
- 每次绘制前显式指定Graphics文本渲染参数
在CellPainting事件中调用DrawString前,手动给e.Graphics.TextRenderingHint赋值为高质量渲染模式,强制每次绘制使用指定参数,不受全局状态影响:// 放在DrawString调用之前即可 e.Graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit; - 替换DrawString为TextRenderer.DrawText
WinForm原生控件默认使用GDI实现的TextRenderer渲染文本,和GDI+的DrawString渲染栈完全独立,不会受Chart修改的GDI+全局状态影响,同时渲染效果和DataGridView原生单元格文字完全一致,不会出现字重不匹配、发虚、边距偏差的问题:// 替换原有DrawString调用即可 TextRenderer.DrawText(e.Graphics, displayValue, e.CellStyle.Font, cellRect, rowForeColor, TextFormatFlags.Left | TextFormatFlags.VerticalCenter | TextFormatFlags.NoPrefix); - 升级Chart控件版本
新版本的WinForm Chart控件已经修复了全局GDI+状态泄漏的问题,将项目引用的System.Windows.Forms.DataVisualization升级到最新稳定版即可直接解决。
优先推荐第二种方案,和DataGridView原生文字渲染效果一致性最高,无需额外调整渲染参数。
内容的提问来源于stack exchange,提问作者EigelDan
相关产品推荐
相关产品推荐

