【问题标题】:Why I can access btn.Caption when btn is NIL?为什么当 btn 为 NIL 时我可以访问 btn.Caption?
【发布时间】:2018-07-03 18:50:20
【问题描述】:

为什么这段代码不会崩溃? T 为零。如果Tnil,如何访问Caption

procedure Crash;                                                                          
VAR T: TButton;
begin
 T:= NIL;
 T.Caption:= ''; <---------- this works
end;

【问题讨论】:

  • @KenWhite 我也是这么想的,不过我只是测试了一下,不管我通过什么值,它仍然不会崩溃。在内部,它成功地为WM_SETTEXTCM_TEXTCHANGED 发送Windows 消息。
  • 因为它是 Windows 控件的包装器,它使用消息来设置实际值。它有安全防护,可以防止在 nil 控件上发送消息。当然,它也可以工作,因为属性设置器不是虚拟的。
  • @Ken 将标题设置为空字符串肯定会有所作为。

标签: delphi delphi-xe7


【解决方案1】:

TButton 控件是 Win32 Button 控件的包装器。它使用 Windows 消息传递系统对其进行操作。如果Selfnil,则这样做的核心方法TControl.Perform() 具有防止发送消息的内置保护:

function TControl.Perform(Msg: Cardinal; WParam: WPARAM; LParam: LPARAM): LRESULT;
var
  Message: TMessage;
begin
  Message.Msg := Msg;
  Message.WParam := WParam;
  Message.LParam := LParam;
  Message.Result := 0;

  if Self <> nil then // <-- here
    WindowProc(Message); 

  Result := Message.Result;
end;

Caption 是一个属性,其设置器使用非虚拟的 TControl.GetText()TControl.SetText() 方法,可以安全地调用 nil 对象,因为它们的功能依赖于发送各种消息(WM_GETTEXTLEN 和 @ 987654331@) 到控件,只涉及局部变量或传递的参数。所以nil时没有访问到实际的对象,所以没有crash。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-07-11
    • 1970-01-01
    • 2016-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-31
    相关资源
    最近更新 更多