如何在 Delphi 中防止 ProcessMessages
Application.ProcessMessages 命令是众所周知的,我在长进程中使用它以确保我的程序不会占用计算机。
但我有一组相当快的处理,我将视图缓冲到文件中。 在缓冲过程中,可能会发送一些系统消息(例如重绘或滚动条移动或其他事件)。 我想阻止这些由 ProcessMessages 处理,直到我的缓冲完成。
有没有办法:
阻止 Application.ProcessMessages 直到我的过程完成,或者
捕获我的过程期间生成的所有消息,而不释放 捕获我的过程中生成的所有消息,直到过程结束
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:
Prevent Application.ProcessMessages until my procedure is complete, or
Trap all messages generated during my procedure, and not release them until the end of the procedure.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
即使
ProcessMessages
发送了您不想要的消息,但允许它继续运行也不应该被视为有问题。 通过一些代码重构,您可以将缓冲方法移至单独的线程中并从那里开始。如果您尝试将控件的“视觉内容”复制到文件中,
LockWindowUpdate
Win32 API 方法调用,该方法调用将关闭该控件的所有绘制消息,WndProc
/DefaultWndProc
方法,并为每个消息返回“true”发送的消息OnPaint
”、“OnPaintBackground
”等),并且不执行任何操作如果您的缓冲正在进行中覆盖
WndProc
或DefaultWndProc
并简单地为每条消息返回 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,
LockWindowUpdate
Win32 API method call which will turn off all painting messages to that controlWndProc
/DefaultWndProc
method on your control class or even the parent class if you need to and simply return "true" for each message sentOnPaint
", "OnPaintBackground
" etc) on the control class or even the parent and simply do nothing if your buffering is in progressOverriding the
WndProc
orDefaultWndProc
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.你可以做一个肮脏的黑客(除非你想不出更好的方法):
您可以使用 Win32 Hooks 来监视(捕获)任何消息。< br>
具体来说,使用 SetWindowsHookEx 并将 WH_CALLWNDPROC 作为 idHook值。
然后,您可以将它们记录到列表/队列中,并在需要时重新发送。
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.
我早在 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).
在迂腐的层面上,“阻止”Application.ProcessMessages 的方法是不调用任何
如果您编写一个循环除了数值计算和文件 I/O 之外什么都不做,你的 UI 将被冻结,直到你退出循环,因为没有消息正在处理。
如果您希望 UI 在未知任意代码(第三方库)的某些长时间运行操作期间做出响应,但您不希望在此期间应用程序中发生某些类型的操作,那么这是一个不同的问题 - 这是关于防止可重入性。 您希望防止在特定活动正在进行时使用代码的某些部分。 例如,模式对话框通过禁用除模式对话框本身之外的所有应用程序顶级窗口来阻止您与对话框下方的应用程序窗口进行交互。
At a pedantic level, the way you "prevent" Application.ProcessMessages is to not call any code that
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.