【问题标题】:TToolbar stops displaying button captions after a while一段时间后,TToolbar 停止显示按钮标题
【发布时间】:2017-11-21 19:17:41
【问题描述】:

知道为什么带有 TToolButtons 的 TToolbar 会在一段时间后停止显示按钮标题吗?这发生在整个应用程序中自动创建的表单上的所有工具栏上。即使出现此问题,动态创建的表单上的工具栏也能正常工作。

我只在一台 Windows 7 笔记本上看到过这种情况。发生这种情况时不会引发任何错误,并且我无法通过命令重现该问题。唯一的解决方案是重新启动应用程序。

TToolbar.ShowCaptions 始终为 True 且从未更改。这在下图中也可见,因为当 ShowCaptions 为 False 时,图标是垂直对齐的。

以前在 Windows 8 PC 上也发生过类似的问题。不过这次的字幕被其他文字取代了。

编辑:

我能够通过在 5-10k 次之间调用 TImageList.Change 来重现该问题。我只有 Delphi 2010,所以我不能说这是 Delphi 还是 Windows 的问题。

单位:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ImgList, ComCtrls, ToolWin, StdCtrls, Gauges;

type
  TImageListHelper = class helper for TImageList
  public
    procedure DoChange;
  end;

  TForm1 = class(TForm)
    ToolBar1: TToolBar;
    ToolButton1: TToolButton;
    ToolButton2: TToolButton;
    ToolButton3: TToolButton;
    ToolButton4: TToolButton;
    ToolButton5: TToolButton;
    ToolButton6: TToolButton;
    ToolButton7: TToolButton;
    ToolButton8: TToolButton;
    ToolButton9: TToolButton;
    ToolButton10: TToolButton;
    ImageList1: TImageList;
    ProgressBar1: TProgressBar;
    procedure ToolButton1Click(Sender: TObject);
  private
  public
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.ToolButton1Click(Sender: TObject);
begin
  repeat
    ImageList1.DoChange;
    ProgressBar1.StepIt;
    Self.Update;
  until ProgressBar1.Position >= ProgressBar1.Max;
end;

procedure TImageListHelper.DoChange;
begin
  Self.Change;
end;

end.

表格:

object Form1: TForm1
  Left = 0
  Top = 0
  Caption = 'Form1'
  ClientHeight = 66
  ClientWidth = 711
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  Position = poScreenCenter
  PixelsPerInch = 96
  TextHeight = 13
  object ToolBar1: TToolBar
    Left = 0
    Top = 0
    Width = 711
    Height = 41
    ButtonHeight = 36
    ButtonWidth = 71
    Caption = 'ToolBar1'
    Images = ImageList1
    ShowCaptions = True
    TabOrder = 0
    ExplicitWidth = 885
    object ToolButton1: TToolButton
      Left = 0
      Top = 0
      Caption = 'ToolButton1'
      ImageIndex = 0
      OnClick = ToolButton1Click
    end
    object ToolButton2: TToolButton
      Left = 71
      Top = 0
      Caption = 'ToolButton2'
      ImageIndex = 0
    end
    object ToolButton3: TToolButton
      Left = 142
      Top = 0
      Caption = 'ToolButton3'
      ImageIndex = 0
    end
    object ToolButton4: TToolButton
      Left = 213
      Top = 0
      Caption = 'ToolButton4'
      ImageIndex = 0
    end
    object ToolButton5: TToolButton
      Left = 284
      Top = 0
      Caption = 'ToolButton5'
      ImageIndex = 0
    end
    object ToolButton6: TToolButton
      Left = 355
      Top = 0
      Caption = 'ToolButton6'
      ImageIndex = 0
    end
    object ToolButton7: TToolButton
      Left = 426
      Top = 0
      Caption = 'ToolButton7'
      ImageIndex = 0
    end
    object ToolButton8: TToolButton
      Left = 497
      Top = 0
      Caption = 'ToolButton8'
      ImageIndex = 0
    end
    object ToolButton9: TToolButton
      Left = 568
      Top = 0
      Caption = 'ToolButton9'
      ImageIndex = 0
    end
    object ToolButton10: TToolButton
      Left = 639
      Top = 0
      Caption = 'ToolButton10'
      ImageIndex = 0
    end
  end
  object ProgressBar1: TProgressBar
    Left = 0
    Top = 49
    Width = 711
    Height = 17
    Align = alBottom
    Max = 10000
    Step = 1
    TabOrder = 1
    ExplicitTop = 48
  end
  object ImageList1: TImageList
    Left = 8
    Top = 16
    Bitmap = {
      494C010101000500040010001000FFFFFFFFFF10FFFFFFFFFFFFFFFF424D3600
      0000000000003600000028000000400000001000000001002000000000000010
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      FF000000FF000000000000000000000000000000000000000000000000000000
      FF000000FF000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      FF000000FF000000000000000000000000000000000000000000000000000000
      FF000000FF000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000FF000000FF0000000000000000000000FF000000FF000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000FF000000FF0000000000000000000000FF000000FF000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      00000000000000000000000000000000FF000000FF0000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      00000000000000000000000000000000FF000000FF0000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000FF000000FF0000000000000000000000FF000000FF000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000FF000000FF0000000000000000000000FF000000FF000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      FF000000FF000000000000000000000000000000000000000000000000000000
      FF000000FF000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      FF000000FF000000000000000000000000000000000000000000000000000000
      FF000000FF000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      0000000000000000000000000000000000000000000000000000000000000000
      000000000000000000000000000000000000424D3E000000000000003E000000
      2800000040000000100000000100010000000000800000000000000000000000
      000000000000000000000000FFFFFF00FFFF000000000000FFFF000000000000
      FFFF000000000000E7E7000000000000E7E7000000000000F99F000000000000
      F99F000000000000FE7F000000000000FE7F000000000000F99F000000000000
      F99F000000000000E7E7000000000000E7E7000000000000FFFF000000000000
      FFFF000000000000FFFF00000000000000000000000000000000000000000000
      000000000000}
  end
end

【问题讨论】:

  • 闻起来像是某种资源泄漏。尝试监控 GDI 对象计数。
  • 最有可能的是,字幕在运行时更改。您可以在工具按钮的 FCaption 属性上定义断点,或者 - 如果确实存在 - 在 SetCaption 方法中。
  • @RenéHoffmann 字幕永远不会改变。即使它们是,这也不应该影响整个应用程序。
  • @DavidHeffernan 我会调查一下,谢谢你的想法。
  • 你使用动作吗?如果您分配一个动作,然后修改按钮标题,然后对该动作进行更改,它将覆盖您为按钮标题放置的任何内容,以成为该动作的标题。

标签: windows delphi toolbar delphi-2010 vcl


【解决方案1】:

这似乎是 Delphi 2010 中的一个错误,位于 function TToolBar.UpdateItem() 末尾的 ComCtrls 单元中。该函数从第 21476 行开始。

在 Delphi XE4 中(它可能在之前已修复,我无法检查)以下注释和代码(Delphi 2010 中缺少)出现在函数末尾:: p>

  // If more than 2^16 strings are TB_ADDSTRING-ed to the tool bar's string
  // pool, the Windows API assumes iString is a pointer to a null terminated
  // string, not an index in the string pool.  Therefore we have to recreate
  // the toolbar to reset the string pool so the strings display propperly.
  if Button.iString >= 65536 then
    RecreateWnd;

将 Delphi 2010 ComCtrls.pas 复制到项目文件夹并添加上述代码,解决了您的测试产生的问题。

【讨论】:

  • 我的回答中展示的解决方案的一个好处是它首先避免了淹没字符串池。使用此处描述的解决方案(顺便说一句),您可以看到进程私有字节在ToolButton1Click 循环执行时稳步增加。使用我的解决方案不会发生。这不是一个重要的数量,但我确实认为避免无缘无故地破坏和重新创建这些按钮是非常有意义的,此外,尽可能避免重新创建窗口必须是一个好政策。我个人会应用两个答案的更改。
  • 回答的时间应该无关紧要。接受您认为自己是最佳答案的原因。
【解决方案2】:

鉴于问题中的再现,我认为问题在于 VCL 工具栏代码删除了所有按钮,然后在修改图像列表时重新创建它们。

我正在查看 Delphi 6 代码,因为我手头没有 Delphi 2010,但代码并没有发生实质性的变化。相关代码在TToolBar.CreateButtons。在这个方法的底部,我们有:

for I := 0 to InternalButtonCount - 1 do Perform(TB_DELETEBUTTON, 0, 0);
UpdateButtons;

循环删除所有按钮,然后UpdateButtons 将它们添加回来。似乎底层控制不喜欢被这种方式对待。我们可以删除所有多余的按钮,而不是删除所有按钮。

var
  Count: Integer;
....
Count := InternalButtonCount;
while Count>FButtons.Count do
begin
  Perform(TB_DELETEBUTTON, Count-1, 0);
  dec(Count);
end;
UpdateButtons;

在您的示例代码和实际应用程序中,您没有更改按钮的数量,因此此版本甚至不会进入循环。

通过此更改,您的程序可以正常运行。

您可以通过执行以下操作在您的应用程序中应用此更改:

  1. 从安装目录的源文件夹中获取 ComCtrls.pas 的副本,并将其保存在项目树中。
  2. 将复制的 ComCtrls 单元添加到您的项目中。
  3. 进行上述修改。

【讨论】:

  • 经过更多测试后,此解决方案会导致其他问题。在运行时更改按钮标题会隐藏所有按钮的标题。
  • 在我的测试中没有......我想知道你是否能给我足够的细节来重现
  • 使用问题中的测试应用程序并修补 ComCtrls。将 ToolButton1Click 替换为 ToolButton1.Caption := 'Button'。单击时,我得到的只是任何按钮上没有标题的图标。
  • 不适合我。再说一次,我在 Delphi 6 上进行测试,也许这就是区别。但我对此表示怀疑。
  • Screenshot 缺少字幕。不仅仅是缺少标题,事件按钮和工具栏也会改变高度。实际上并不奇怪,因为我在 Delphi 2010 中的工具栏总是遇到奇怪的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-23
  • 2019-02-05
  • 2014-05-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多