C#中GDI+绘图应优先在Paint事件中使用e.Graphics绘制,确保重绘机制正常;离线绘图则用Graphics.FromImage配合using管理资源;避免CreateGraphics和手动释放遗漏。

在C#中用GDI+绘图,核心是获取Graphics对象,然后调用它的绘图方法——不是直接“画”,而是“告诉Graphics去画”。关键在于时机和资源管理:必须在合适的地方(如Paint事件)获取Graphics,并避免手动创建后忘记释放。
在窗体上实时绘制图形
最常用也最稳妥的方式是在窗体的Paint事件中绘图。系统每次需要重绘(比如窗口被遮挡后恢复、调整大小)时,都会自动触发该事件,并传入已准备好的Graphics对象。
- 双击窗体进入
Form1_Load前,先在设计器中选中窗体 → 属性面板 → 事件(闪电图标)→ 找到Paint→ 双击生成事件处理方法 - 在生成的
Form1_Paint方法里,使用参数e.Graphics进行绘制,例如:e.Graphics.DrawRectangle(Pens.Red, 50, 50, 100, 80);e.Graphics.FillEllipse(Brushes.Blue, 200, 60, 80, 60); - 不要在
Paint里调用Refresh()或Invalidate(),否则可能引发无限重绘循环
在Bitmap图片上离线绘制
如果想把图形画到内存中的图片(比如生成验证码、导出图表),就创建Bitmap,再用Graphics.FromImage()获得对应的Graphics对象。
- 先创建位图:
Bitmap bmp = new Bitmap(400, 300); - 获取绘图表面:
using (Graphics g = Graphics.FromImage(bmp)) { ... }
⚠️ 必须用using确保释放资源,否则容易内存泄漏 - 绘制完成后,可保存为文件:
bmp.Save("output.png", ImageFormat.Png);
或赋给PictureBox.Image显示出来
基础绘图元素怎么写
GDI+绘图分“描边”和“填充”两类,对应不同方法和参数:
-
画线/矩形/椭圆轮廓:用
DrawXXX系列,传Pen对象(决定颜色、粗细、线型)
例:g.DrawLine(Pens.Green, 10, 10, 100, 50); -
填充区域:用
FillXXX系列,传Brush对象(纯色用SolidBrush,渐变用LinearGradientBrush等)
例:g.FillRectangle(Brushes.Yellow, 0, 0, 200, 100); -
文字:
DrawString,需指定字体、画刷、位置(左上角坐标)
例:g.DrawString("Hello", new Font("Arial", 12), Brushes.Black, 10, 10);
常见坑和建议
新手容易卡在这几个地方:
- 在
Form_Load或构造函数里直接用CreateGraphics()绘图 → 图形一闪就消失,因为没走重绘机制 - 自己new了
Graphics但没dispose → 程序跑一会儿就卡顿甚至崩溃 - 用
Control.CreateGraphics()获得的Graphics不推荐用于常规绘图,它绕过Paint流程,不可靠 - 需要动态更新画面(如动画)时,用
this.Invalidate()触发重绘,再在Paint里画新状态,别硬刷
基本上就这些。GDI+不复杂,但资源管理和绘图时机容易忽略。抓住“Paint事件 + e.Graphics”这个主线,多数需求都能稳稳实现。










