当我将TPanel添加到ToolBar时,我是否会获得Panel或ToolButton?

时间:2010-06-21 09:59:53

标签: delphi vcl delphi-2006

当Delphi(2006)走向量子时:我有一些似乎是TToolBar和TPanel的“东西”,取决于你如何观察它。我想了解发生了什么。

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

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

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

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

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

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

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

3 个答案:

答案 0 :(得分:2)

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

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

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

我建议您使用表单设计器来创建工具栏。这样,IDE将在您的表单中为您维护一个标识符,因此您将始终直接引用您的面板。您不必在工具栏中寻找它。即使您手动创建工具栏,最好还是创建一个额外的字段来引用该面板。即使您在工具栏中移动面板,它仍然是整个时间内的同一个对象,因此您无需担心悬空参考。

答案 1 :(得分:0)

当您在工具栏上放置几个按钮和一个面板,并在某个地方放置一个Memo时,然后在表单的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”,您将获得正确的信息。

答案 2 :(得分:0)

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

我会看是否能找到解决问题的另一种方法。聪明的黑客毕竟不会那么聪明,而且肯定会使代码的wtf-rate更高。

你必须使用工具栏吗?那么带按钮和面板的流动面板呢?或者带有工具栏和面板的面板?