我有一个应用程序在启动时恢复窗口,但这会导致每个窗口创建和定位时出现潜在的闪烁。
为了解决这个问题,我将闪屏(拉伸到屏幕的整个尺寸)设置为" 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;
马丁
答案 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;