1

由于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

4

2 回答 2

2

我已经非常可靠地使用了以下代码(使用 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-08T09:06:33.597 回答
-1

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

我必须假设 TWinControl 除了在您直接调用 RedrawWindow 时无法可靠完成的 API 重绘之外还做了一些事情。

于 2017-02-03T21:59:03.943 回答