вторник, 22 сентября 2015 г.

#1160. Ссылка. Блокировка перерисовки окна на время обновления его дочерних окон

Блокировка перерисовки окна на время обновления его дочерних окон.

(+) Неудачный эффект WM_SETREDRAW.
(+)(+) Существует реализация WM_SETREDRAW по умолчанию, но вы можете сделать и лучше.

В нашем "фреймворке" это достигается несколько иначе:

https://bitbucket.org/lulinalex/mindstream/src/1fab802d0af4a7a2166f7181501dd79b86f989ce/Examples/1160/afwBaseControl.pas?at=B284&fileviewer=file-view-default

https://bitbucket.org/lulinalex/mindstream/src/580b4f9e3aeba03a771bf30bc270037f071c37d9/Examples/1160/vcmBase.pas?at=B284&fileviewer=file-view-default

{$If not defined(NoVCL)}
procedure TafwBaseControl.WndProc(var Message: TMessage);
//#UC START# *47E136A80191_48BD1975029B_var*
var
 PS: TPaintStruct;
//#UC END# *47E136A80191_48BD1975029B_var*
begin
//#UC START# *47E136A80191_48BD1975029B_impl*
 // Два case тут для удобства отладки
 case Message.Msg of
  WM_ERASEBKGND,
  WM_NCPAINT,
  WM_PAINT:
  begin
   case Message.Msg of
    WM_ERASEBKGND:
     if InUpdating then
     begin
      Message.Result := 1;  {don't erase background}
      Exit;
     end;//InUpdating
    WM_NCPAINT:
     if InUpdating then
      Exit;
    WM_PAINT:
     if InUpdating then
     begin
      BeginPaint(Handle, PS);
      EndPaint(Handle, PS);
      Exit;
     end;//InUpdating
   end;//case Message.Msg
   inherited;
  end;//WM_ERASEBKGND
  else
   inherited;
 end;//case Message.Msg
//#UC END# *47E136A80191_48BD1975029B_impl*
end;//TafwBaseControl.WndProc
{$IfEnd} //not NoVCL

function TafwBaseControl.InUpdating: Boolean;
//#UC START# *48C6C421015B_48BD1975029B_var*
//#UC END# *48C6C421015B_48BD1975029B_var*
begin
//#UC START# *48C6C421015B_48BD1975029B_impl*
 Result := HandleAllocated AND Visible AND afw.IsObjectLocked(Self);
 // без проверки на видимость, WM_PAINT'ы приходят невидимым контролам, в результате
 // имеем прогрузку дерева при ненужной отрисовке, например.
//#UC END# *48C6C421015B_48BD1975029B_impl*
end;//TafwBaseControl.InUpdating

...

class function TvcmAFW.IsObjectLocked(aControl : TObject = nil): Boolean;
  //override;
  {-}
begin
 Result := ((g_Dispatcher <> nil) AND g_Dispatcher.FormDispatcher.Locked){ OR
           ((g_MenuManager <> nil) AND g_MenuManager.UnlockInProgress)};
 if Result and (aControl <> nil) then
  g_Dispatcher.FormDispatcher.AddControlForInvalidate(aControl);
end;

...


Цитирую:

    WM_PAINT:
     if InUpdating then
     begin
      BeginPaint(Handle, PS);
      EndPaint(Handle, PS);
      Exit;
     end;//InUpdating

4 комментария:

  1. WM_PAINT:
    if InUpdating then
    begin
    BeginPaint(Handle, PS);
    EndPaint(Handle, PS);
    Exit;

    Это для валидации? А нельзя ли использовать ValidateRect?

    ОтветитьУдалить
    Ответы
    1. bq. Это для валидации? А нельзя ли использовать ValidateRect?

      Ну по-другому мне не удалось заставить Windows не слать WM_PAINT снова. Я вроде ValidateRect пытался использовать. Не помогало. Точно - не помню уже.

      Удалить
  2. А вообще идея понятна. Я как раз тоже дошёл до этого :)
    Ну т.е. глобальные процедуры:
    BeginUpdate(AWinControl)/EndUpdate(AWinControl), которые подменяют WndProc для контрола и сохраняют счётчик (чтобы можно было использовать вложенные вызовы). Пока как черновик, ещё не тестировал..

    ОтветитьУдалить
    Ответы
    1. Ну как-то так :-) Я просто решил поделиться своими наработками. Раз уж тема всплыла.

      Удалить