由于Vcl.Forms.TScrollBox没有BeginUpdate / EndUpdate方法,因此在TScrollBox容器的子级查看器中加载文档时,我使用以下代码来减少闪烁:
procedure MyLockWinControl(const WC: Vcl.Controls.TWinControl; ALock: Boolean);
begin
if (not Assigned(WC)) or (WC.Handle = 0) then EXIT;
if ALock then
WC.Perform(WM_SETREDRAW, 0, 0)
else
begin
WC.Perform(WM_SETREDRAW, 1, 0);
RedrawWindow(WC.Handle, nil, 0, RDW_ERASE or RDW_FRAME or RDW_INVALIDATE or RDW_ALLCHILDREN);
end;
end;
procedure TFormMain.LoadDocFile(const ADocFile: string);
begin
Screen.Cursor := crHourGlass;
try
MyLockWinControl(ScrollBox, True);
try
DoLoadDocFile(ADocFile);
finally
MyLockWinControl(ScrollBox, False);
end;
finally
Screen.Cursor := crDefault;
end;
end;这很好用,除非在极少数情况下,应用程序会在MyLockWinControl(ScrollBox, False);上重现崩溃
因此,我的问题是:MyLockWinControl中是否存在错误,或者是否有更好的方法来停止并恢复TScrollBox中的更新
发布于 2017-02-08 17:06:34
我已经非常可靠地使用了以下代码(使用TScrollBox):
SendMessage(scrollbox.Handle, WM_SETREDRAW, 0, 0);
try
//do some stuff with the scrollbox here
finally
SendMessage(scrollbox.Handle, WM_SETREDRAW, 1, 0);
RedrawWindow(scrollbox.Handle, nil, 0, RDW_ERASE or RDW_INVALIDATE or RDW_FRAME or RDW_ALLCHILDREN);
end;您的代码(通过MyLockWinControl过程)似乎基本上做了同样的事情-除了使用Perform (直接向控件发送消息)而不是SendMessage (使用Windows消息队列)。您还提到,您使用的组件不是TScrollBox,而是一个派生组件-所以问题很可能也存在于此。
我能建议的唯一一件事就是在你的代码周围放置一个try/except块,并捕获/记录错误。这可能会进一步洞察问题的症结所在……
发布于 2017-02-04 05:59:04
我尝试的第一件事是将您对RedrawWindow的调用替换为对WC.Invalidate的调用。
我不得不假设,除了直接调用RedrawWindow时不能可靠地完成的API重绘之外,TWinControl还在做一些事情。
https://stackoverflow.com/questions/41852729
复制相似问题