1

当 Delphi (2006) 进入量子状态时:我有一个看起来既是 TToolBar 又是 TPanel 的“东西”,这取决于你如何观察它。我想了解发生了什么。

以下是如何创建它以及会发生什么:

  1. 在 DFM 中

    • 添加一个名为 bar 的 TToolBar;
    • 在那个 TToolBar 中,放一个 TPanel。
  2. 在代码中和运行时:

    • 面板出现在按钮列表 bar.Buttons[] 中,假设在索引 i
    • bar.Buttons[i],从编译器的角度来看,是一个 TToolButton
    • bar.Buttons[i].ClassName = 'TPanel'
    • (bar.Buttons[i] is TToolButton) = true,但这是编译器优化对“is”的调用;
    • 确实 IsBarButton(bar.Buttons[i]) 对于函数 IsBarButton 是错误的(定义如下);
    • bar.Buttons[i].Name 是我在 DFM 中给 TPanel 起的名字
    • 在调试中检查值 bar.Buttons[i]:
      • 它有一个真正的 TToolButton 没有的属性“Caption”
      • 奇怪的是,它具有 TToolButton 的所有属性,例如 TToolButton.Indeterminate (=true)。

工具按钮:

function IsToolButton(X : TObject) : boolean;
begin
    Result := X is TToolButton;
end;

所以 bar.Buttons[i] 既是又不是 TToolButton... 怎么了?

(底部的故事是我想将我的 TPanel 与真正的 TToolButton 区分开来。我可以用或多或少的黑客方式来做到这一点。我在这里提出这个问题的目的是更全面地了解这里真正发生的事情。)

问题:发生了什么?子问题:将 TPanel 添加到 TToolBar 是否合法?

4

3 回答 3

2

操作系统唯一允许添加到工具栏的是工具按钮。要添加任何其他内容,从技术上讲,您需要创建一个按钮,然后将其他内容放在上面。添加的按钮实际上是一个占位符。它在那里占用空间,因此您添加的下一个内容可以正确定位。

如果您添加的非工具按钮控件是透明的,您有时会看到这一点。然后你可以在下面看到工具栏的分隔符,所以看起来有一条垂直线穿过你的控件中间。

当您将非工具按钮控件添加到工具栏时,该Buttons属性确实取决于控件的类型。您会注意到整个ComCtrls.pas本身TToolBar总是将按钮转换为TControl然后检查它们是否真的从TToolButton. 在工具栏中添加非按钮是完全合法的;这就是表单设计器首先允许它的原因。

I suggest you use the Form Designer to create your tool bar. That way, the IDE will maintain an identifier for you in your form, so you'll always have a direct reference to your panel. You won't have to go hunting for it in the tool bar. Even if you're creating the tool bar manually, it's a good idea to make an extra field to refer to the panel. Even if you move the panel around within the tool bar, it will still be the same object the whole time, so you needn't worry about dangling references.

于 2010-06-21T14:10:48.907 回答
0

当您在工具栏上放置几个按钮和一个面板,并在某处放置一个备忘录时,然后在表单的 onCreate 中运行此代码:

procedure TForm1.FormCreate(Sender: TObject);
  function _IsToolButton(const aObject: TObject): Boolean;
  begin
    Result := aObject is TToolButton;
  end;

  function _IsPanel(const aObject: TObject): Boolean;
  begin
    Result := aObject is TPanel;
  end;
var
  i: Integer;
begin
  for i := 0 to bar.ButtonCount - 1 do begin
    Memo.Lines.Add(Format('bar.Buttons[%d].Name: %s', [i, bar.Buttons[i].Name]));
    Memo.Lines.Add(Format('bar.Buttons[%d].ClassName: %s', [i, bar.Buttons[i].ClassName]));
    Memo.Lines.Add(Format('bar.Buttons[%d] is TToolButton: %s', [i, BoolToStr(_IsToolButton(bar.Buttons[i]), True)]));
    Memo.Lines.Add(Format('bar.Buttons[%d] is TPanel: %s', [i, BoolToStr(_IsPanel(bar.Buttons[i]), True)]));
//    Memo.Lines.Add(Format('bar.Buttons[%d] has Caption property: %s', [i, 'dunno yet']));
    Memo.Lines.Add('');
  end;
end;

你会看到这个面板不是一个 TooButton 并且绝对是一个 TPanel。

显示面板 ToolButton 属性的调试器只是将每个 bar.Buttons[i] 转换为 TToolButton 的调试器。当您右键单击调试检查器的“数据”选项卡时,您可以将其类型转换为 TPanel,您将获得正确的信息。

于 2010-06-21T10:37:41.923 回答
0

“合法吗?” - 好吧,您肯定以工具栏的创建者没有提到要使用它的方式使用工具栏。它会在你脸上炸开吗?谁知道。我想你可以浏览工具栏的源代码并检查它是否安全,但是可能的第三方工具或组件呢?期望在工具栏中找到按钮?

我会看看我是否能找到另一种方法来解决我的问题。聪明的 hack 往往会变得不那么聪明,它肯定会提高你代码的wtf-rate

你必须使用工具栏吗?带有按钮和面板的流程面板怎么样?还是带有工具栏和面板的面板?

于 2010-06-21T11:57:00.027 回答