Остановить и восстановить обновление в 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 ответа

Я использовал следующий код довольно надежно (с 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/ кроме и поймать / записать ошибку. Это может дать дополнительное понимание того, в чем заключается проблема...

Первое, что я бы попробовал, это заменить ваш вызов RedrawWindow на вызов WC.Invalidate.

Я должен предположить, что TWinControl делает некоторые вещи в дополнение к перерисовке API, которая не выполняется надежно, когда вы вызываете RedrawWindow напрямую.

Другие вопросы по тегам