跳转到主内容
新派编程网 - 新潮编程理念,全新技术课堂!

C#怎么操作GDI绘图 C#如何用Graphics对象在窗体和图片上绘制图形和文字【图像】

DrawRectangle 画不出边框需确保 Pen 实例有效且 Width ≥ 1f;避免使用 CreateGraphics(),应响应 Paint 事件绘制;DrawString 模糊需设 PageUnit 为 Pixel 并用 TextRenderer.MeasureText;保存 PNG 要指定 Format32bppPArgb 并 Clear(Color.Transparent)。 Graphics.DrawRectangle 画不出边框?检查 Pen 是否为空或宽度为 0 常见错误是传入
null
的
Pen
,或者用
new Pen(Color.Black, 0)
—— GDI 里线宽为 0 表示“最细可显示线”,但某些 DPI 缩放或高分屏下会直接不可见。实际绘制必须确保
Pen
实例有效且
Width >= 1f
。 用
new Pen(Color.Black, 1f)
替代
0
,尤其在 .NET 6+ WinForms 高 DPI 模式下更稳定 避免复用已调用过
Dispose()
的
Pen
,否则可能静默失败或抛
ObjectDisposedException
若从
Control.CreateGraphics()
获取
Graphics
,记得手动
Dispose()
,否则 Pen 关联的 GDI 句柄可能泄漏 在 PictureBox 中绘图后不刷新?别直接用 CreateGraphics()
CreateGraphics()
返回的是临时设备上下文,绘图内容不会持久化,窗体最小化再还原、被其他窗口遮挡后重绘时就没了。正确做法是响应控件的
Paint
事件,在
PaintEventArgs.Graphics
上绘制。 订阅
pictureBox1.Paint += (s, e) => { e.Graphics.DrawEllipse(...); };
触发重绘用
pictureBox1.Invalidate()
(标记区域需重绘),不是
Refresh()
(强制同步重绘,易卡顿) 如果只是临时标注(比如鼠标圈选),可在内存 Bitmap 上绘制,再赋给
pictureBox1.Image
,但注意频繁赋值会引发 GC 压力 DrawString 文字模糊或位置偏移?优先用 GraphicsUnit.Pixel + 精确测量 默认
DrawString
使用字体逻辑单位,受
Graphics.PageUnit
和
PageScale
影响,容易导致文字错位或模糊。Windows 渲染文本最稳的方式是统一设为像素单位,并用
Graphics.MeasureString
或更准的
TextRenderer.MeasureText
测量尺寸。 C知道 CSDN推出的一款AI技术问答工具 下载 开头加
g.PageUnit = GraphicsUnit.Pixel;
用
TextRenderer.MeasureText("text", font)
替代
MeasureString
,它更贴近 GDI+ 实际渲染行为,尤其对中文和等宽字体 避免把
DrawString
的
PointF
坐标直接设为整数,小数点后一位(如
10.5f
)能减少亚像素渲染抖动 保存绘图到 PNG 却出现黑底或透明丢失?Bitmap 构造时指定 PixelFormat 用
new Bitmap(width, height)
默认创建
PixelFormat.Format32bppArgb
,看似支持透明,但若后续用
Graphics.FromImage()
绘制时未清空背景,或保存为 PNG 前没设置好 Alpha 通道,就会变黑底或丢透明。 明确初始化:
var bmp = new Bitmap(200, 100, PixelFormat.Format32bppPArgb);
(PArgb 更快,适合绘图) 绘制前先清空:
using var g = Graphics.FromImage(bmp); g.Clear(Color.Transparent);
保存时确保目标格式支持 Alpha:
bmp.Save("out.png", ImageFormat.Png);
,不要用
Jpeg
真正麻烦的是跨线程操作 Graphics —— 它不是线程安全的,所有绘制必须在 UI 线程做。哪怕你用
Invoke
包了一层,也得确认
Graphics
对象本身没在别的线程里被缓存或复用。

相关文章