You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C# WinForms中PictureBox绘制Bitmap时重复绘制问题排查

C# WinForms PictureBox绘制异常问题

我开发了一个包含多个PictureBox的C# WinForms应用程序,绘制图形时起初因控件尺寸问题未发现异常,后续发现图像绘制错误,仿佛绘制方法的调用次数远多于调试器显示的次数。

错误绘制效果

我多次运行代码,开启/禁用Form的DoubleBuffering后问题依旧。通过断点排查发现代码中仅调用一次绘制逻辑,绘制方法如下:

Bitmap bmp = new Bitmap(Resources.<backgroundfile>, 342, 54);
RectangleF rectfLage = new RectangleF(16, 14, 60, 22);
Graphics graphicLageNr = Graphics.FromImage(bmp);
graphicLageNr.SmoothingMode = SmoothingMode.AntiAlias;
graphicLageNr.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphicLageNr.PixelOffsetMode = PixelOffsetMode.HighQuality;
graphicLageNr.DrawString($"{lage}", new Font("Tahoma", 16), Brushes.Black, rectfLage);
graphicLageNr.Flush();

之后我将PictureBox的Background先设为NULL再赋值为Bitmap:

Controls[0].Controls[2].Controls["lagenr"].BackgroundImage = null
Controls[0].Controls[2].Controls["lagenr"].BackgroundImage = bmp  

请问我哪里操作出错了?


问题分析与解决

1. 资源未释放导致的异常

你创建的Graphics、Font和Bitmap对象都没有手动释放,会造成GDI+资源泄漏,系统后续重绘时容易出现图像残留、重复绘制的假象。必须用using语句自动释放非托管资源:

using (Bitmap bmp = new Bitmap(Resources.<backgroundfile>, 342, 54))
using (Font tahomaFont = new Font("Tahoma", 16))
using (Graphics graphicLageNr = Graphics.FromImage(bmp))
{
    RectangleF rectfLage = new RectangleF(16, 14, 60, 22);
    graphicLageNr.SmoothingMode = SmoothingMode.AntiAlias;
    graphicLageNr.InterpolationMode = InterpolationMode.HighQualityBicubic;
    graphicLageNr.PixelOffsetMode = PixelOffsetMode.HighQuality;
    graphicLageNr.DrawString($"{lage}", tahomaFont, Brushes.Black, rectfLage);
    
    // 先获取目标PictureBox引用,避免多次层级查找出错
    PictureBox targetPic = Controls[0].Controls[2].Controls["lagenr"] as PictureBox;
    if(targetPic != null)
    {
        // 释放旧背景图,避免内存泄漏和图像残留
        targetPic.BackgroundImage?.Dispose();
        targetPic.BackgroundImage = (Bitmap)bmp.Clone();
    }
}

2. 控件层级查找的风险

直接通过Controls[0].Controls[2].Controls["lagenr"]查找控件非常脆弱——一旦布局变化(添加/移除控件),索引会失效,可能误修改其他控件的背景图,造成“重复绘制”的错觉。建议直接在设计器中给PictureBox命名,代码里直接使用变量名(比如this.lagenr.BackgroundImage)。

3. PictureBox绘制模式优化

优先使用PictureBox.Image而非BackgroundImage:BackgroundImage会随控件缩放拉伸,容易出现绘制变形;Image可以配合SizeMode(如Zoom/CenterImage)控制显示方式,减少异常。

4. 双缓冲的正确用法

Form的DoubleBuffering对PictureBox背景图绘制影响有限,若要优化PictureBox的绘制,需给控件本身启用双缓冲:

typeof(PictureBox).InvokeMember(
    "DoubleBuffered",
    BindingFlags.SetProperty | BindingFlags.Instance | BindingFlags.NonPublic,
    null,
    targetPic,
    new object[] { true });

内容的提问来源于stack exchange,提问作者Steve

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 08:31:00