OK, теперь когда мы знаем для каких операций предполагалось использовать функцию
LockWindowUpdate
, мы можем посмотреть на разные (неправильные) способы, которыми люди её используют.Люди видят поведение "заблокированное вами окно не будет перерисовываться" функции
LockWindowUpdate
и используют его вместо сообщения WM_SETREDRAW
. Хотя отправка WM_SETREDRAW
не намного сложнее вызова LockWindowUpdate
. Это всего лишь длиннее на двадцать символов - или вполновину меньше, если использовать оболочку SetWindowRedraw
.Вместо | LockWindowUpdate(Wnd) |
---|---|
Используйте | SendMessage(Wnd, WM_SETREDRAW, 0, 0) илиSetWindowRedraw(Wnd, False) |
Вместо | LockWindowUpdate(0) |
---|---|
Используйте | SendMessage(Wnd, WM_SETREDRAW, 1, 0) илиSetWindowRedraw(Wnd, True) |
Как мы заметили ранее, только одно окно в системе может быть заблокировано в конкретный момент времени. Если вы вызываете
LockWindowUpdate
только для того, чтобы запретить окну перерисовываться (скажем, потому что вы обновляете окно и не хотите, чтобы окно постоянно перерисовывало себя, пока вы не закончите процесс обновления), то просто отключите перерисовку у этого окна отправкой WM_SETREDRAW
. Если вы используете LockWindowUpdate
, то у вас появляется множество неявных проблем.Во-первых, если какая-то другая программа ошибочно использует
LockWindowUpdate
по тем же причинам, что и вы, то кто-то из вас обязательно проиграет. Кто вызовет LockWindowUpdate
первым, тот и получит блокировку. Второй вызов будет неудачен. Что теперь будете делать? Ваше окно теперь не заблокировано.Во-вторых, если вы заблокировали окно и пользователь переключается на другую программу и пытается выполнить операцию перетаскивания (к примеру, просто переместить окно!), то попытка вызова
LockWindowUpdate
во время этой операции будет неудачна, а пользователь окажется в ситуации, когда операция перемещения перестала работать на пустом месте, по каким-то загадочным причинам. А затем, секунды спустя, всё снова работает. "Глупая багнутая Windows" - пробормочет пользователь.И наоборот: если вы вызовите
LockWindowUpdate
во время операции перетаскивания, то у вас ничего не сработает.Это только один пример более общей ошибки программирования - использование глобального состояния для управления локальным условием. Когда вы хотите отключить перерисовку в одном из ваших окон, вы не хотите, чтобы это влияло на все окна в системе; это локальное условие. Но для этого вы используете глобальное состояние (блокировку окна).
Я уже могу предвидеть, как кто-то скажет: "Ну, оконный менеджер не должен всяким-разным вызывать
LockWindowUpdate
, если они не собираются делать операцию по перетаскиванию". Но как он узнает? Менеджер окон увидит, что сделан вызов LockWindowUpdate
, но он не знает почему. Программа вызывает LockWindowUpdate
, потому что она слишком ленива, чтобы вызывать вместо неё WM_SETREDRAW
? Или она делает это в ответ на ввод пользователя, от которого запускается операция перетаскивания? Заметьте, что вы не можете просто сказать: "Ну, кнопка мыши должна быть нажата", потому что пользователь может выполнять эту операцию с клавиатуры (к примеру, изменение размера окна стрелочками) - это полный эквивалент обычной операции перетаскивания. Поэтому ответ на этот вопрос потребует телепатических способностей - чего-то, чем современные компьютеры пока не обладают.В следующий раз - завершающие заметки по
LockWindowUpdate
.
> Программа вызывает LockWindowUpdate, потому что она слишком ленива, чтобы вызывать вместо неё WM_SETREDRAW?
ОтветитьУдалитьПотому что найти в документации LockWindowUpdate проще, чем WM_SETREDRAW. :)
> Поэтому ответ на этот вопрос потребует телепатических способностей - чего-то, чем современные компьютеры пока не обладают.
Да, у Microsoft ещё долго будут проблемы, пока их разработчики не научатся собирать libastral под Windows. :)
По идее, надо было не поскупиться и назвать функцию LockOnlyOneWindowUpdateAtWholeSysytem. :) По крайней мере в этом случае разработчики задумались бы и, возможно, полезли бы на форумы, спрашивая - а почему только одно на всю систему, что нельзя было больше. И тогда бы нашёлся кто-нибудь, кто рассказал бы про WM_SETREDRAW и этот ответ цитировали бы по всем интернетам. :)
ОтветитьУдалить