如何在 Delphi 中防止 ProcessMessages

发布于 2024-08-01 19:41:57 字数 328 浏览 5 评论 0原文

Application.ProcessMessages 命令是众所周知的,我在长进程中使用它以确保我的程序不会占用计算机。

但我有一组相当快的处理,我将视图缓冲到文件中。 在缓冲过程中,可能会发送一些系统消息(例如重绘或滚动条移动或其他事件)。 我想阻止这些由 ProcessMessages 处理,直到我的缓冲完成。

有没有办法:

  1. 阻止 Application.ProcessMessages 直到我的过程完成,或者

  2. 捕获我的过程期间生成的所有消息,而不释放 捕获我的过程中生成的所有消息,直到过程结束

The Application.ProcessMessages command is well known and I use it in long processes to ensure my program will not tie up the computer.

But I have one fairly quick set of processing, where I am buffering a view into a file. During the buffering procedure, a few system messages may get sent off (e.g. redraw or scrollbar move or other events). I want to prevent these from getting handled by ProcessMessages until my buffering is complete.

Is there any way to either:

  1. Prevent Application.ProcessMessages until my procedure is complete, or

  2. Trap all messages generated during my procedure, and not release them until the end of the procedure.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

傲鸠 2024-08-08 19:41:57

即使 ProcessMessages 发送了您不想要的消息,但允许它继续运行也不应该被视为有问题。 通过一些代码重构,您可以将缓冲方法移至单独的线程中并从那里开始。

如果您尝试将控件的“视觉内容”复制到文件中,

  • 请查看 WM_PRINT(xxx) 消息,该消息允许子控件将自己绘制到位图中,
  • 尝试使用 LockWindowUpdate Win32 API 方法调用,该方法调用将关闭该控件的所有绘制消息,
  • 如果需要,则覆盖控件类甚至父类上的 WndProc/DefaultWndProc 方法,并为每个消息返回“true”发送的消息
  • 会覆盖控件类甚至父级上的特定控件方法(例如“滚动条移动”、“OnPaint”、“OnPaintBackground”等),并且不执行任何操作如果您的缓冲正在进行中

覆盖 WndProcDefaultWndProc 并简单地为每条消息返回 true 本质上“关闭”ProcessMessages but< /em> 这样做并不安全,因为控件可能需要处理一条或多条消息才能正常运行。

关闭 ProcessMessages 是不可能的(如果不重写消息处理的 VCL 代码),因为它是构建 VCL 表单消息循环的一部分。

Allowing the ProcessMessages to continue even if it sends messages you don't want should not be classed as problematic. With a bit of code refactoring, you could move the buffering method into a separate thread and go from there.

If you are attempting to copy the "visual contents" of a control into a file,

  • look at the WM_PRINT(xxx) message which allows child controls to paint themselves into bitmaps
  • try the LockWindowUpdate Win32 API method call which will turn off all painting messages to that control
  • override the WndProc/DefaultWndProc method on your control class or even the parent class if you need to and simply return "true" for each message sent
  • override specific control methods (such as "scroll bar moved", "OnPaint", "OnPaintBackground" etc) on the control class or even the parent and simply do nothing if your buffering is in progress

Overriding the WndProc or DefaultWndProc and simply returning true for each message essentially "turns off" ProcessMessages but it's not safe to do it this way because the control might need to process one or more messages to function correctly.

Turning off ProcessMessages is not possible (without rewriting the VCL code for message processing) because of the fact that it's part of how the VCL form's message loop has been constructed.

成熟稳重的好男人 2024-08-08 19:41:57

捕获我的过程中生成的所有消息,并且不释放它们
直到程序结束。

你可以做一个肮脏的黑客(除非你想不出更好的方法):

您可以使用 Win32 Hooks 来监视(捕获)任何消息。< br>
具体来说,使用 SetWindowsHookEx 并将 WH_CALLWNDPROC 作为 idHook值。
然后,您可以将它们记录到列表/队列中,并在需要时重新发送。

Trap all messages generated during my procedure, and not release them
until the end of the procedure.

There is a dirty hack you can do (only if you can not come up with a better way):

You can watch (trap) any messages by using Win32 Hooks.
Specifically, use SetWindowsHookEx with WH_CALLWNDPROC as the idHook value.
You can then record them in a list/queue and resend them when you want.

寄风 2024-08-08 19:41:57

我早在 Windows 2 中就了解到,Windows 消息有时会在您意想不到的情况下发生。 库的任何部分都可能导致应用程序进行消息处理。 与其阻挡潮流,不如让你的代码在这种情况下保持健壮。 这可能像使用 BeginUpdate/EndUpdate 对一样简单,或更复杂(使用临时并在最后进行最终更新)。

I learned way back in Windows 2 that windows messages will happen at times you don't expect them. Any part of a library can cause your app's message processing to happen. Rather than hold back the tide, make your code robust against the situation. This may be as simple as usinga a BeginUpdate/EndUpdate pair, or more complex (using a temporary and doing the final update at the end).

温柔少女心 2024-08-08 19:41:57

在迂腐的层面上,“阻止”Application.ProcessMessages 的方法是不调用任何

  1. 显示模式对话框的
  2. 代码调用 SendMessage
  3. 运行其自己的本地消息循环
  4. 调用 Application.ProcessMessages(这是本地消息循环)

如果您编写一个循环除了数值计算和文件 I/O 之外什么都不做,你的 UI 将被冻结,直到你退出循环,因为没有消息正在处理。

如果您希望 UI 在未知任意代码(第三方库)的某些长时间运行操作期间做出响应,但您不希望在此期间应用程序中发生某些类型的操作,那么这是一个不同的问题 - 这是关于防止可重入性。 您希望防止在特定活动正在进行时使用代码的某些部分。 例如,模式对话框通过禁用除模式对话框本身之外的所有应用程序顶级窗口来阻止您与对话框下方的应用程序窗口进行交互。

At a pedantic level, the way you "prevent" Application.ProcessMessages is to not call any code that

  1. shows a modal dialog
  2. calls SendMessage
  3. runs its own local message loop
  4. calls Application.ProcessMessages (which is a local message loop)

If you write a loop that does nothing but numerical calculations and file I/O, your UI will be frozen until you exit the loop because no messages are being processed.

If you want your UI to be responsive during some long-running operation of unknown arbitrary code (third party library) but you don't want certain kinds of actions to occur in your app during that time, that's a different problem - that's about preventing reentrancy. You want to prevent some parts of your code from being used while a particular activity is in progress. For example, modal dialogs prevent you from interacting with the app windows underneath the dialog by disabling all the app's top level windows except the modal dialog itself.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文