1

我正在尝试创建 TLabel 后代,当文本宽度超过标签宽度时,它将显示带有整个标题的提示。我已将 EllipsisPosition 属性设置为 epEndEllipsis,并且我的标题在末尾自动被省略号缩短。没关系。

但是需要通知我,文本已被缩短以设置提示。在我的情况下,这可能仅在更改文本(消息 CM_TEXTCHANGED)和调整组件大小时发生。

这就是我的问题 -如何通知我 TLabel 已调整大小?我在那里有锚点,所以它与表单一起调整大小,但我想将它包装在单独的 TLabel 后代中。

此代码有效,但没有更好的方法吗?像 WM_EXITSIZEMOVE 之类的东西,但为 TGraphicControl 工作?

procedure TEllipsisLabel.WMWindowPosChanged(var Message: TWMWindowPosChanged);
begin
  inherited;

  if Assigned(Parent) then
    if Canvas.TextWidth(Caption) > Width then
      begin
        ShowHint := True;
        Hint := Caption;
      end
    else
      begin
        ShowHint := False;
        Hint := '';
      end;
end;

非常感谢 :)

4

4 回答 4

1

我认为您不希望收到TLabel后代已调整大小的通知。 相反,您希望收到它已缩短文本的通知。我知道它们看起来一样,但它们不是——标签可能仍然比文本更宽,它可能已经WordWrap打开等等。此外,TCustomLabel后代可以使用几种不同的方法来绘制文本,基于主题/ Vista / Aero 发光的东西(它们归结为DrawThemeTextExDrawText),因此您需要连接到该系统以准确了解它正在绘制的文本正在做什么,包括渲染文本的大小。

如果您使用的是 Delphi 的非 Starter 版本,请查看TCustomLabel. stdctrls.pas有两种感兴趣的方法:

  • TCustomLabel.AdjustBounds- 这是设置边界矩形的地方,它会针对自动换行等进行调整。它通过调用(与绘画一样)其他感兴趣的方法来做到这一点:
  • TCustomLabel.DoDrawText- 这会绘制文本和/或计算文本边界矩形,以考虑椭圆、环绕等。 在内部,它会生成一个更改后的字符串,即实际绘制的文本。 换句话说,这个方法的功能就是告诉你文本是否合适。

两者都是dynamic,这在语义上等同于存在virtual- 即,您可以覆盖它们。

DoDrawText不幸的是,它不会返回它正在绘制的最终文本字符串 - 如果确实如此,您可以覆盖它,调用继承的版本并将绘制的文本与真实文本进行比较。但是,您可以覆盖并重新实现它,并自己执行此操作。使用 VCL 代码作为指导(您需要等效的功能,尽管您不应该直接复制它,因为它归 Embarcadero 所有。)作为dynamic,您的后代类的版本将由AdjustBounds. 在您的代码中,当您缩短文本时,还要设置一个已缩短的标志或立即生成提示。瞧。您准确地知道它何时被缩短:)

于 2011-03-10T23:14:08.683 回答
1

我想不出比这更好的了WM_WINDOWPOSCHANGED

由于调用 SetWindowPos 函数或另一个窗口管理函数,发送到其大小、位置或 Z 顺序中的位置已更改的窗口。

这看起来很理想。你有什么反对使用它的?

于 2011-03-10T16:17:13.863 回答
0

我认为您需要覆盖AdjustBounds方法。试试下面的代码(只需创建一个带有TButtonTLabel的表单,然后用这段代码替换.pas )。此示例演示了在文本更改时检测标签大小更改。不过,您将需要创建自己的事件。

unit unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TSizeNotifyLabel = class(TLabel)
  public
    procedure AdjustBounds; override;

end;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Label1: TLabel;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }

    SizeNotifyLabel: TSizeNotifyLabel;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation


procedure TSizeNotifyLabel.AdjustBounds;
begin
  inherited;
  form1.label1.caption := 'Width of Label:'+inttostr(form1.SizeNotifyLabel.Width);
end;

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
  SizeNotifyLabel.Caption := SizeNotifyLabel.Caption + ' Change My Size';
end;

procedure TForm1.FormCreate(Sender: TObject);

begin
  SizeNotifyLabel := TSizeNotifyLabel.Create(self);
  with SizeNotifyLabel do begin
    caption := 'Hello World';
    left := 10;
    top := 10;
    autosize := true;
    parent := self;
  end;

end;

end.
于 2011-03-10T16:19:15.033 回答
0

您可以简单地覆盖Resize方法。但是,请注意您的代码

if Canvas.TextWidth(Caption) > Width then

TCustomLabel.DoDrawText与确定何时绘制椭圆的方式不同,因此您可能会得到意想不到的结果。

此外,椭圆绘制也可能是由字体更改、主题设置更改以及其他一些事件引起的。

于 2011-03-10T16:47:59.187 回答