【问题标题】:Stop and restore updating in TScrollBox?停止并恢复 TScrollBox 中的更新?
【发布时间】:2017-06-10 16:48:46
【问题描述】:

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

【问题讨论】:

  • 很难说没有复制。
  • 亲爱的大卫,我的问题不是提到的崩溃,而是MyLockWinControl 中是否存在错误,或者是否有更好的方法来停止和恢复TScrollBox 中的更新。
  • 这取决于前提条件。例如,如果从线程调用该函数,那么就会出现问题。是吗?我认为在没有给出任何上下文的情况下询问单个功能是否被孤立是徒劳的。无论如何,如果这是您想问的问题,那很好。但我帮不了你。如果有更好的方法来停止闪烁?几乎可以确定。但是,正如所问的,我不能帮助你。祝你好运。
  • 如果运行良好,则没有错误。如果存在可重现的崩溃,那么某处存在错误 - 但不一定在这里。如果您说崩溃与它无关,那么问题是什么?如果是,那么让我们看看是什么导致了崩溃。
  • 仅供参考,if WC.Handle = 0永远不会为真。 Handle getter 如果没有分配新的 HWND,则分配一个新的 HWND,如果发生错误则引发异常。要测试 HWND 是否已分配而不分配新的,请改用 if WC.HandleAllocated

标签: delphi flicker delphi-10.1-berlin tscrollbox


【解决方案1】:

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

我必须假设 TWinControl 正在做一些事情,除了当你直接调用 RedrawWindow 时没有可靠地完成的 API 重绘。

【讨论】:

    【解决方案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 块并捕获/记录错误。这可能有助于进一步了解问题所在...

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-01-14
      • 1970-01-01
      • 2015-05-03
      • 2021-04-19
      • 1970-01-01
      • 2013-10-17
      • 2013-08-27
      • 1970-01-01
      相关资源
      最近更新 更多