【问题标题】:How do I discard unprocessed event messages in a Delphi application?如何丢弃 Delphi 应用程序中未处理的事件消息?
【发布时间】:2021-02-10 23:37:09
【问题描述】:

我在 Delphi 应用程序中执行一些 HTTP 请求时显示“请稍候”表单。 “请稍候”对话框在关闭时调用 Application.ProcessMessages

这似乎有一些不良后果。例如,如果用户单击“请稍候”对话框后面的表单中的按钮,则这些单击似乎会添加到事件队列中并在执行 Application.ProcessMessages 时进行处理,即使在显示对话框之前禁用按钮并启用也是如此隐藏后再次。

所以我想知道是否有任何方法可以在显示“请稍候”对话框时完全忽略整个应用程序的鼠标单击事件?我发现我可以将整个表单的Enabled 设置为False 以防止在该特定表单上发生鼠标单击事件,但是当Application.ProcessMessages 执行时,其他表单仍会收到鼠标单击事件。

有没有标准的方法来做到这一点?类似(假设的伪代码)Application.Enabled := FALSEApplication.DiscardMessages

修改“请稍候”对话框的行为(删除对Application.ProcessMessages 的调用)是我无法控制的——它是在不同地方使用的标准公司范围的对话框。

【问题讨论】:

  • 为了其他读者的利益:不要使用Application.ProcessMessages。正确的解决方案是在单独的线程中完成慢速任务。既然我已经说过了,让我们专注于您的特定问题。我个人非常喜欢的一种应用程序设计方法是将TActionList 用于应用程序中的所有操作(使用菜单、工具栏按钮、热键或按钮的任意组合访问)。如果使用这样的设计,只需要禁用动作列表即可。
  • 您显然不想完全停止对消息的响应,因为这会使您的应用程序无响应,无法移动/调整大小,并且还会使 Abort 按钮我确定您在“请稍候”对话框中停止工作。
  • 你的对话框窗口是模态窗口吗?
  • 听起来你真正的问题不是你想的那样。您真正的问题似乎是您没有使用正确的模式对话框,该对话框会禁用其他顶级窗口。

标签: delphi


【解决方案1】:

我在 Delphi 应用程序中执行一些 HTTP 请求时显示“请稍候”表单。 “请稍候”对话框在关闭时调用 Application.ProcessMessages。

它不应该那样做。这很好地表明正在使用糟糕的设计。

解决此问题的正确方法是在工作线程中执行 HTTP 请求,并在线程忙于工作时显示对话框模态,从而允许主消息队列仍然处理消息一般。模态对话框阻止用户输入到达对话框之外的窗口。线程完成后,可以关闭对话框,将用户输入恢复到其他窗口。

这似乎有一些不良后果。例如,如果用户单击“请稍候”对话框后面的表单中的按钮,则这些单击似乎被添加到事件队列中并在执行 Application.ProcessMessages 时进行处理,即使在显示对话框之前禁用按钮并启用这些按钮也是如此隐藏后再次。

这意味着对话框在显示时根本不处理任何消息。对于任何对话框来说,这都是错误的设计。

所以我想知道是否有任何方法可以在显示“请稍候”对话框时完全忽略整个应用程序的鼠标单击事件?

是的 - 在对话框运行时正常处理消息,只是不要对它们做任何事情。如果您的对话框以模态方式显示,您将获得此行为免费,因为模态对话框运行自己的消息循环,并禁用其他活动窗口,阻止任何用户到达他们的输入。

我发现我可以将整个表单的 Enabled 设置为 False 以防止在该特定表单上发生鼠标点击事件,但其他表单在 Application.ProcessMessages 执行时仍会收到鼠标点击事件。

更有理由怀疑您没有模态地使用对话框,因为它会为您禁用调用线程中的所有窗口。 p>

有什么标准的方法吗?

是的 - 修复您的设计。正确使用模态对话框。

类似于(假设的伪代码)Application.Enabled := FALSE 或 Application.DiscardMessages?

在 VCL 或 FMX 框架中没有类似的东西。如果你真的需要这样的东西,你必须直接调用 Win32 PeekMessage() 函数(当然只在 Windows 上),例如:

procedure DiscardMouseClicks;
var
  msg: TMsg;
begin
  while PeekMessage(0, msg, MOUSE_FIRST, MOUSE_LAST, PM_REMOVE) do;
end;

不用说,如果你不得不诉诸于此,那你就做错了。

修改“请稍候”对话框的行为(删除对 Application.ProcessMessages 的调用)不在我的控制范围之内 - 这是一个在不同地方使用的标准公司范围的对话框。

那么要么你的公司在其所有应用程序中执行了一个糟糕的设计,要么你只是在滥用对话框。

【讨论】:

    【解决方案2】:

    您的“请稍候”对话框似乎不是模态的,因为模态对话框在其生命周期内阻止对话框外的用户输入。此外,它还会/甚至处理相关或必要的窗口和应用程序消息,因为它在内部已经确实使用了Application.ProcessMessages,之后无需手动调用它。这一切都是设计和免费使用的。

    通过ShowModal 方法显示一个对话框,使其成为模态的。

    由于您当前的对话框是固定的(据了解,它不能被修改),那么一个解决方案可能是创建一个新的单独模式对话框并在其上显示您的“请稍候”对话框。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-13
      • 2021-10-23
      • 2011-05-06
      • 2011-09-07
      • 2018-09-20
      • 1970-01-01
      相关资源
      最近更新 更多