Как предотвратить ProcessMessages в Delphi - PullRequest
4 голосов
/ 09 августа 2009

Команда Application.ProcessMessages хорошо известна, и я использую ее в длительных процессах, чтобы моя программа не связывала компьютер.

Но у меня есть один довольно быстрый набор обработки, где я буферизирую представление в файл. Во время процедуры буферизации могут отправляться несколько системных сообщений (например, перерисовка или перемещение полосы прокрутки или другие события). Я хочу, чтобы они не обрабатывались ProcessMessages до тех пор, пока моя буферизация не будет завершена.

Есть ли способ либо:

  1. Запретить Application.ProcessMessages, пока моя процедура не будет завершена, или

  2. Перехватывайте все сообщения, сгенерированные во время моей процедуры, и не отпускайте их до конца процедуры.

Ответы [ 4 ]

5 голосов
/ 09 августа 2009

Разрешение ProcessMessages продолжить, даже если оно отправляет нежелательные сообщения, не должно рассматриваться как проблематичное. Немного реорганизовав код, вы можете переместить метод буферизации в отдельный поток и перейти оттуда.

Если вы пытаетесь скопировать «визуальное содержимое» элемента управления в файл,

  • посмотрите на сообщение WM_PRINT (xxx), которое позволяет дочерним элементам управления отображать себя в растровые изображения
  • попробуйте LockWindowUpdate вызов метода Win32 API, который отключит все сообщения рисования для этого элемента управления
  • переопределяет метод WndProc / DefaultWndProc в вашем классе управления или даже в родительском классе, если вам нужно, и просто возвращает "true" для каждого отправленного сообщения
  • переопределяет определенные методы управления (такие как "полоса прокрутки перемещена", "OnPaint", "OnPaintBackground" и т. Д.) В классе управления или даже в родительском объекте и просто ничего не делает, если выполняется буферизация

Переопределение WndProc или DefaultWndProc и простое возвращение true для каждого сообщения, по сути, «отключает» ProcessMessages , но это не безопасно, так как элемент управления может обрабатывать одно или более сообщений для правильной работы.

Отключение ProcessMessages невозможно (без переписывания кода VCL для обработки сообщений) из-за того, что это часть того, как был построен цикл сообщений формы VCL.

3 голосов
/ 09 августа 2009

Перехватывать все сообщения, сгенерированные во время моей процедуры, а не выпускать их до конца процедуры.

Есть грязный хак, который вы можете сделать (только если вы не можете придумать лучшего способа):

Вы можете просматривать (перехватывать) любые сообщения, используя Win32 Hooks .
В частности, используйте SetWindowsHookEx с WH_CALLWNDPROC в качестве значения idHook.
Затем вы можете записать их в список / очередь и повторно отправить их, когда захотите.

1 голос
/ 09 июня 2010

На педантичном уровне способ «предотвращения» Application.ProcessMessages состоит в том, чтобы не вызывать код, который

  1. показывает модальное диалоговое окно
  2. вызывает SendMessage
  3. запускает свой собственный локальный цикл сообщений
  4. вызывает Application.ProcessMessages (который является локальным циклом сообщений)

Если вы напишите цикл, который не выполняет ничего, кроме численных расчетов и файлового ввода-вывода, ваш пользовательский интерфейс будет заморожен до тех пор, пока вы не выйдете из цикла, поскольку сообщения не обрабатываются.

Если вы хотите, чтобы ваш пользовательский интерфейс реагировал на некоторые длительные операции с неизвестным произвольным кодом (сторонней библиотекой), но вы не хотите, чтобы в приложении в это время происходили определенные виды действий, это другая проблема - это о предотвращении повторного входа. Вы хотите запретить использование некоторых частей вашего кода во время выполнения определенного действия. Например, модальные диалоги не позволяют вам взаимодействовать с окнами приложения под диалогом, отключая все окна верхнего уровня приложения, кроме самого модального диалога.

1 голос
/ 10 августа 2009

В Windows 2 я узнал, что сообщения Windows будут появляться в те моменты, когда вы их не ожидаете. Любая часть библиотеки может привести к обработке сообщений вашего приложения. Вместо того, чтобы сдерживать поток, сделайте свой код устойчивым к ситуации. Это может быть так же просто, как использование пары BeginUpdate / EndUpdate, или более сложным (использование временного и окончательное обновление в конце).

...