Graphics对象不能new,合法来源仅有三个:Paint事件参数e.Graphics、Graphics.FromImage(bitmap)和control.CreateGraphics();Pen/Brush需Dispose防泄漏;DrawRectangle偏移需查坐标系与DPI;DrawString模糊应设TextRenderingHint.AntiAliasGridFit。

Graphics 对象不能 new,否则直接报错或静默失败——所有绘图必须基于合法来源。
Graphics 从哪来?三个合法入口,别碰 new
new Graphics() 会抛出 NotSupportedException,它不是普通类。合法来源只有三个:
- 窗体或控件的
Paint事件参数:e.Graphics—— 最推荐,自动参与双缓冲、重绘流程 - 位图离屏绘制:
Graphics.FromImage(bitmap)—— 生成图片时用,记得调用graphics.Dispose() -
control.CreateGraphics()—— 仅限调试或瞬时覆盖(比如鼠标跟随预览),窗口一重绘就消失,不持久
常见错误:在 Button_Click 里调用 this.CreateGraphics() 然后画矩形,结果点完就没了。这不是 bug,是设计如此。
Pen 和 Brush 必须 Dispose,但别乱 new
这两个类持有 GDI 句柄,不释放会导致句柄泄漏,跑久了可能触发 OutOfMemoryException 或绘图失效。
- 循环中反复
new Pen(Color.Red, 2)是高危操作;应改用using (var pen = new Pen(...)) { ... } - 静态复用安全:如
static readonly Pen GridPen = new Pen(Color.LightGray, 1);,但注意Pen.Width和Color是只读属性,赋值无效 -
Brushes.Red等系统预定义刷子不用Dispose;但new SolidBrush(...)或new LinearGradientBrush(...)必须手动释放
DrawRectangle 画不出/位置偏移?先查坐标系和 DPI
写 g.DrawRectangle(pen, 10, 10, 100, 50) 却看不见,或框总往右下偏,大概率踩了这三个坑:
- 没确认目标控件的客户区边界:在
PictureBox中绘图,应基于pictureBox.ClientSize计算坐标,而不是硬写像素值 - 启用了高 DPI 缩放(Win10/11 默认开启):
Graphics.DpiX可能是 120 或 144,直接按 96 设计尺寸画会缩放失真;可用g.ScaleTransform(g.DpiX / 96f, g.DpiY / 96f)校正 -
DrawRectangle描边以边线中心为基准,若pen.Width = 3,实际覆盖区域比参数宽高各多出 1.5 像素;填色用FillRectangle则严格按左上+宽高填充内部
DrawString 模糊?TextRenderingHint 是关键开关
小字号文字发虚、边缘毛糙,不是字体问题,而是渲染模式默认太“松”:
- 默认
TextRenderingHint.SystemDefault在非整数缩放或 ClearType 关闭时极易模糊 - 固定写法:在
Paint事件开头加g.TextRenderingHint = TextRenderingHint.AntiAliasGridFit; - 避免用浮点字体大小(如
new Font("Arial", 9.75f)),.NET 会取整但不提示;如需精确控制,优先考虑GraphicsPath + FillPath绘制文字轮廓
真正难处理的是 DPI 缩放 + 多显示器混合场景下的坐标对齐,这时候光靠 ScaleTransform 不够,得配合 Control.LogicalToDeviceUnits 或启用 Per-Monitor DPI Aware 清单声明——这点多数人一开始根本想不到。










