在TScrollBox中停止并恢复更新?

时间:2017-01-25 13:22:12

标签: delphi flicker delphi-10.1-berlin tscrollbox

由于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中的更新?

2 个答案:

答案 0 :(得分:0)

我已经非常可靠地使用了以下代码(使用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块并捕获/记录错误。这可以进一步了解问题所在......

答案 1 :(得分:-1)

我尝试的第一件事是通过调用WC.Invalidate替换您对RedrawWindow的调用。

我必须假设TWinControl正在做一些其他的东西,除了API重绘,当你直接调用RedrawWindow时,它不能可靠地完成。