4

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

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

有没有办法:

  1. 在我的程序完成之前阻止 Application.ProcessMessages,或者

  2. 捕获在我的过程中生成的所有消息,直到过程结束才释放它们。

4

4 回答 4

5

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

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

  • 查看允许子控件将自己绘制成位图的 WM_PRINT(xxx) 消息
  • 尝试LockWindowUpdateWin32 API 方法调用,该方法调用将关闭该控件的所有绘画消息
  • 如果需要,覆盖控件类甚至父类上的WndProc/方法,并为发送的每条消息简单地返回“true”DefaultWndProc
  • 覆盖控件类甚至父级上的特定控件方法(例如“滚动条移动”、“ OnPaint”、“ ”等),如果正在进行缓冲,则什么也不做OnPaintBackground

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

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

于 2009-08-09T16:42:52.620 回答
3

捕获在我的过程中生成的所有消息,直到过程结束才释放它们。

您可以做一个肮脏的黑客攻击(仅当您想不出更好的方法时):

您可以使用Win32 Hooks观察(陷阱)任何消息。
具体来说,使用SetWindowsHookEx和 WH_CALLWNDPROC 作为 idHook 值。
然后,您可以将它们记录在列表/队列中,并在需要时重新发送。

于 2009-08-09T17:05:32.137 回答
1

在迂腐的层面上,你“防止” Application.ProcessMessages 的方式是不调用任何代码

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

如果您编写一个只执行数值计算和文件 I/O 的循环,您的 UI 将被冻结,直到您退出循环,因为没有处理任何消息。

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

于 2010-06-08T23:53:01.653 回答
1

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

于 2009-08-10T08:33:18.103 回答