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

如何解决在窗体或图像上快速绘制、移动控件时出现的闪烁问题?

VCL窗体/控件绘制闪烁解决方案

触发原因

该闪烁由VCL默认重绘逻辑导致:修改控件位置、触发自定义绘制时,系统默认会先清空对应区域的背景,再绘制新的内容,两个操作的时间差就会表现为肉眼可见的闪烁。

可用修复方案

  • 方案1:开启双缓冲
    直接在窗体属性面板设置DoubleBuffered为True,或在窗体初始化代码中添加:
    Form1.DoubleBuffered := True;
    // 涉及到的子控件也可同步开启双缓冲
    Image1.DoubleBuffered := True;
    
    双缓冲机制会先在内存中完成所有绘制计算,再一次性输出到屏幕,消除擦除和绘制的时间差。
  • 方案2:禁用不必要的背景擦除
    重写窗体的WM_ERASEBKGND消息,阻止系统自动擦除背景:
    type
      TForm1 = class(TForm)
        // 原有控件声明省略
      private
        procedure WMEraseBkgnd(var Message: TWMEraseBkgnd); message WM_ERASEBKGND;
        // 其他私有声明省略
      public
        // 共有声明省略
      end;
    
    implementation
    
    procedure TForm1.WMEraseBkgnd(var Message: TWMEraseBkgnd);
    begin
      // 直接返回已处理标记,跳过系统默认擦除背景操作
      Message.Result := 1;
    end;
    
  • 方案3:修改控件属性时临时挂起重绘
    频繁修改控件位置/外观时,可以先暂停控件重绘,全部修改完成后再一次性刷新:
    你提供的Timer移动Image的代码可修改为:
    procedure TForm1.Timer1Timer(Sender: TObject);
    begin
      Image1.Perform(WM_SETREDRAW, WPARAM(False), 0);
      Image1.Left := Image1.Left + 1;
      Image1.Perform(WM_SETREDRAW, WPARAM(True), 0);
      Image1.Invalidate;
    end;
    
  • 方案4:全局开启应用合成缓冲
    如果你开发的所有应用都存在该问题,可以直接在工程入口处添加系统级合成缓冲配置,一次性解决所有窗体的闪烁问题:
    打开工程的dpr文件,在Application.Initialize后添加以下代码:
    Application.Initialize;
    // 添加下面这行
    SetWindowLong(Application.Handle, GWL_EXSTYLE, GetWindowLong(Application.Handle, GWL_EXSTYLE) or WS_EX_COMPOSITED);
    Application.MainFormOnTaskbar := True;
    Application.CreateForm(TForm1, Form1);
    Application.Run;
    

你给出的示例代码使用方案1或方案2即可完全解决Image移动时的闪烁问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 12:15:08