Блокировка перерисовки окна на время обновления его дочерних окон.
(+) Неудачный эффект 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
Цитирую:
(+) Неудачный эффект 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
WM_PAINT:
ОтветитьУдалитьif InUpdating then
begin
BeginPaint(Handle, PS);
EndPaint(Handle, PS);
Exit;
Это для валидации? А нельзя ли использовать ValidateRect?
bq. Это для валидации? А нельзя ли использовать ValidateRect?
УдалитьНу по-другому мне не удалось заставить Windows не слать WM_PAINT снова. Я вроде ValidateRect пытался использовать. Не помогало. Точно - не помню уже.
А вообще идея понятна. Я как раз тоже дошёл до этого :)
ОтветитьУдалитьНу т.е. глобальные процедуры:
BeginUpdate(AWinControl)/EndUpdate(AWinControl), которые подменяют WndProc для контрола и сохраняют счётчик (чтобы можно было использовать вложенные вызовы). Пока как черновик, ещё не тестировал..
Ну как-то так :-) Я просто решил поделиться своими наработками. Раз уж тема всплыла.
Удалить