【问题标题】:Why is the FormPaint event triggered mutilple times when mouse is moved over a TButton当鼠标移到 TButton 上时,为什么会多次触发 Form Paint 事件
【发布时间】:2015-09-16 07:17:55
【问题描述】:

为什么Form的OnPaint事件在这个应用程序中被触发了这么多次?

  1. 使用两个TButton 控件、一个TMemo 控件和一个TBitBtn 控件创建一个新的VCL 表单应用程序。

  2. 使用此代码:

    procedure TForm1.Button1Click(Sender: TObject);
    begin
      Memo1.Lines.Clear;
    end;
    
    procedure TForm1.FormPaint(Sender: TObject);
    begin
      Memo1.Lines.Add('FormPaint');
    end;
    
  3. 运行应用程序。

当鼠标移到TButton上时,OnPaint事件被触发4次,当鼠标移出TButton时触发4次。

当鼠标移到TBitBtn上时,OnPaint事件被触发3次,当鼠标移出TBitBtn时触发3次。

当“项目/选项/应用程序/外观”中的样式更改为例如“Luna”,我会得到这种行为:

当鼠标移到TButton/TBitBtn时,OnPaint事件被触发1次,当鼠标移出TButton/TBitBtn时触发2次。

为什么不一致?

当鼠标移到TButton 上时是否可以避免OnPaint 事件?

我有 XE8 订阅更新 1(和 Windows 10)。

【问题讨论】:

  • 为什么这对你很重要?如果这是一个问题,那么您可能需要在代码的其他地方修复设计错误。
  • 这是一个简单的应用程序,有一个关于基本 Delphi 功能的直截了当的问题。我对行为和差异感到好奇。这就是为什么它对我很重要。
  • OnPaint 被调用是因为窗体的窗口收到了 WM_PAINT 消息。它收到了,因为窗口的一部分是无效的。为什么给你的窗户涂漆是个问题?这才是真正的问题。 FWIW,没有 VCL 样式的存在,这不是 Delphi 问题。而是一个 winapi 问题。
  • 问题是为什么事件被触发多次,在这种情况下是 4 次,而不是一次。如果它不是德尔福问题,我会得到与例如相同的结果吗? C#?
  • 我的意思是系统正在发送导致OnPaint 事件被触发的Windows 消息。你会在 C# 中得到相同的结果吗?这取决于您使用的 UI 框架,以及该框架如何实现其控件。 WPF 不使用窗口控件,WinForms 不使用 Win32 BUTTON 控件。

标签: delphi windows-10 delphi-xe8


【解决方案1】:

按钮的悬停效果负责您观察到的内容。当您将鼠标悬停在按钮上时,它会改变外观。当您将光标从按钮上移开时,它会恢复其外观。每次外观更改都会触发表单的OnPaint 事件。这就是底层绘画系统的工作原理。为了绘制子控件,将WM_PRINTCLIENT 消息传递给控件的父控件,这反过来会导致表单的OnPaint 事件触发。

您可以通过禁用运行时主题看到这种情况。当您这样做时,将光标移到按钮上不会导致 OnPaint 被触发。

VCL 样式和 Windows 主题导致不同数量的OnPaint 事件被触发的原因仅仅是它们以不同的方式处理绘画。但是 VCL 样式也有悬停效果,它们也会导致OnPaint 事件被触发。

当光标移到按钮上时是否可以避免OnPaint 事件?

在 VCL 样式的应用程序中,您可能会使用没有任何悬停效果的 VCL 样式。在 Windows 主题应用中,您可以禁用按钮的主题。

我怀疑解决您真正问题的方法,即您未提出问题的答案,是停止使用OnPaint 来处理您目前正在使用的任何内容。而是在更合适的地方做任何你在那儿做的事情。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-08-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多