偶尔卡住闪屏(win 7嵌入式)

时间:2017-07-10 04:24:21

标签: delphi vcl delphi-10.1-berlin

我有一个应用程序在启动时恢复窗口,但这会导致每个窗口创建和定位时出现潜在的闪烁。

为了解决这个问题,我将闪屏(拉伸到屏幕的整个尺寸)设置为" StayOnTop"并使用TTask在OnShow事件后关闭它。问题是偶尔闪屏会卡住。如果单击按钮应该在哪里重绘并正确显示。 我试图"无效"所有WinControls但这个问题仍然出现。 我从未在调试器中看到过这个问题。

是否有任何其他人可以建议强制完全重新绘制屏幕?

这是关闭启动的代码 - 这是主窗体的OnShow。

aTask := TTask.Create(procedure()
  begin
    Sleep(800);
    TThread.Synchronize(nil, procedure()
      begin
        fSplash.Close;
        FreeAndNil(fSplash);
        DoInvalidate(self);
      end);
  end);
aTask.Start;

这是我尝试使一切无效......

Procedure DoInvalidate( aWinControl: TWInControl );
var
  i: Integer;
  ctrl: TControl;
begin
  for i:= 0 to aWinControl.Controlcount-1 do
  begin
    ctrl:= aWinControl.Controls[i];
    if ctrl Is TWinControl then
      DoInvalidate( TWincontrol( ctrl ));
  end;
  aWinControl.Invalidate;
end;

马丁

1 个答案:

答案 0 :(得分:1)

您不需要以递归方式使所有内容无效,只需使表单无效即可。

如果您升级到10.2东京,现在可以在TThread.ForceQueue()中使用TThread.Synchronize()代替TTask

procedure TMainForm.FormShow(Sender: TObject);
begin
  TThread.ForceQueue(nil, procedure
    begin
      FreeAndNil(fSplash);
      Application.MainForm.Invalidate;
    end
  );
end;

如果坚持使用TTask,则至少应使用TThread.Queue()代替:

procedure TMainForm.FormShow(Sender: TObject);
begin
  TTask.Create(procedure
    begin
      TThread.Queue(nil, procedure
      begin
        FreeAndNil(fSplash);
        Application.MainForm.Invalidate;
      end;
    end
  ).Start;
end;

或者,您可以使用简短TTimer,例如zdzichs建议:

procedure TMainForm.FormShow(Sender: TObject);
begin
  Timer1.Enabled := True;
end;

procedure TMainForm.Timer1Timer(Sender: TObject);
begin
  Timer1.Enabled := False;
  FreeAndNil(fSplash);
  Invalidate;
end;

或者,您可以为启动窗体分配OnClose事件处理程序以使MainForm无效,然后将PostMessage() WM_CLOSE消息分配给启动窗体:

procedure TMainForm.FormCreate(Sender: TObject);
begin
  fSplash := TSplashForm.Create(nil);
  fSplash.OnClose := SplashClosed;
  fSplash.Show;
end;

procedure TMainForm.FormShow(Sender: TObject);
begin
  if fSplash <> nil then
    PostMessage(fSplash.Handle, WM_CLOSE, 0, 0);
end;

procedure TMainForm.SplashClosed(Sender: TObject; var Action: TCloseAction);
begin
  fSplash := nil;
  Action := caFree;
  Invalidate;
end;

或者,请改为使用OnDestroy事件:

procedure TMainForm.FormCreate(Sender: TObject);
begin
  fSplash := TSplashForm.Create(nil);
  fSplash.OnDestroy := SplashDestroyed;
  fSplash.Show;
end;

procedure TMainForm.FormShow(Sender: TObject);
begin
  if fSplash <> nil then
    fSplash.Release; // <-- delayed free
end;

procedure TMainForm.SplashDestroyed(Sender: TObject);
begin
  fSplash := nil;
  Invalidate;
end;