【问题标题】:Why TForm.Handle is a getter instead of a field?为什么 TForm.Handle 是一个吸气剂而不是一个字段?
【发布时间】:2016-10-03 12:10:29
【问题描述】:

我最近在调试一个复杂的错误。这是由访问不存在的Form.Handle(垃圾指针)引起的。这个错误以一种让我意想不到的方式暴露出来——访问表单Handle 导致调整大小和重绘。

我希望通过垃圾指针访问Form.Handle 只会返回一些垃圾THandle。期望 Handle 在表单创建时创建一次,并且在表单被销毁之前保持不变。

问题

为什么会这样,TForm.Handle 不是在创建表单时被初始化并通过以下方式访问的字段

property Handle: Integer read FHandle;

,但是是一个吸气剂

property Handle: Integer read GetHandle;

在首次访问时创建句柄甚至窗口 (CreateWnd)?

【问题讨论】:

标签: delphi handle vcl tform


【解决方案1】:

即使底层操作系统 window 不存在,表单 object 也可以存在。在那些时候,Handle 字段将为 0,这对于需要有效窗口句柄的代码没有帮助。为确保每次需要时都能获得有效句柄,您需要在引用 Handle 字段之前调用 HandleNeeded。作为带有getter的属性,该属性可以自动为您调用HandleNeeded,让Handle属性的使用更加方便。

【讨论】:

  • “让它变得更容易”,除了从不同线程访问句柄的时候,现在看来这是一个非常糟糕的主意。
  • 是的。在这些情况下,首先调用HandleAllocated,以猜测Handle 的后续访问是否有效。您无法知道,因为主线程可能会在检查时间和使用时间之间破坏窗口。最终,关于在其他线程中做 UI 的东西。如果另一个线程需要知道一个窗口句柄,让主线程将句柄提供给另一个线程(而不是另一个线程自己获取句柄),同时让主线程承担责任确保提供的句柄在其他线程需要时保持有效。
  • @Kromster,如果您想从线程访问表单句柄以发送/发布消息,最好在主线程中分配带有AllocateHwnd() 的句柄,并让线程将消息发布到此句柄。从那里可以将消息转发到 VCL。
  • 我比@LURD 说得更强烈。规则是您从不在主线程之外使用 VCL 窗口句柄,因为它们需要重新创建。因此,您使用的窗口句柄不是,例如来自 AllocateHWnd 的窗口句柄。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-08-17
  • 1970-01-01
  • 1970-01-01
  • 2017-01-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多