delphi - 在 Delphi 2010 中,尽管相应按钮被禁用,但仍处理 Click 事件

标签 delphi winapi delphi-2010

考虑在给定按钮的 OnClick 事件中执行的以下代码:

procedure TForm1.Button1Click(Sender: TObject);
begin
  button1.enabled := false;    //Line 1  
  application.processmessages; //Line 2  
  Sleep(3000);                 //Line 3
  button1.enabled := True;     //Line 4
  Release;                     //Line 5
end;

在 Delphi 2010 中,如果单击此按钮后您设法执行另一个
在第 3 行执行忙时点击它,随后点击
事件显然会存储在命令队列中,因此当
Release(Line 5) 过程被调用,应用程序将尝试处理
它。因此,点击事件将再次被触发。第二次
周围,​​按钮组件已被销毁,因此引发了“访问冲突”错误。

系统确认第二次点击的整个概念,当相应的
按钮被禁用似乎没有声音。对这种阴暗的行为有什么解释吗?

最佳答案

系统的行为与设计完全一致,但请注意您的代码违反了所有合理的设计原则。具体使用SleepProcessMessages在输入事件处理程序中都是不受欢迎的。

程序以这种方式运行的原因如下:

  • 用户通过单击鼠标生成输入消息。
  • 此输入事件被放置在相应线程的输入队列中。
  • 该线程没有为其输入队列提供服务(它正在休眠),因此输入消息(鼠标按下、鼠标按下组合)就坐在那里。
  • 线程唤醒并启用按钮。
  • 按钮 OnClick处理程序返回并且应用程序的消息循环继续。
  • 在适当的时候,鼠标按下和鼠标按下消息被处理(在 CM_RELEASE 消息之前),所以按钮 OnClick处理程序再次运行。
  • 按钮 OnClick处理程序调用 ProcessMessages然后处理 CM_RELEASE并杀死表格。
  • 繁荣!

  • The whole concept of acknowledging the second click by the system when the respective button is disabled does not seem to be sound.



    关键是在处理输入消息时而不是在生成输入消息时检查按钮的启用状态。必须这样,因为输入消息是非常低级的东西,只有应用程序才能将它们解释为按钮点击之类的东西。

    有很多方法可以修复您的代码,但我不愿意提出任何建议,因为这显然是用于说明的代码。但我会说,所有合理的解决方案都将涉及删除对 Sleep 的调用。和`ProcessMessages。

    关于delphi - 在 Delphi 2010 中,尽管相应按钮被禁用,但仍处理 Click 事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17587284/

    相关文章:

    delphi - 在设计模式下获取TDataModule

    delphi - 高效准确的货币类型到整数的转换

    delphi - 我如何知道使用了哪种 SASL 机制?

    c++ - 如何更改 SysDateTimePick32 或 CDateTimeCtrl 的背景颜色?

    Python win32com : Internet Explorer COM object ?(曾经工作过吗?)

    delphi - 优化 TWebBrowser 的绘制以减少总 CPU 使用率

    Delphi XE4 在访问 'object' 的通用列表项时给出 E2036

    c - 抑制或拦截来自其他 dll 的 CRT 实例的 CRT 检查

    delphi - 使用 delphi 中的 shell 遍历目录中的文件