如何为Label创建resize事件(图形控件)

时间:2011-03-10 14:27:24

标签: delphi winapi resize notifications tlabel

我正在尝试创建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 个答案:

答案 0 :(得分:1)

我想不出比WM_WINDOWPOSCHANGED更好的东西:

  

发送到一个大小,位置,   或者在Z顺序中的位置已更改为   调用SetWindowPos的结果   功能或其他窗口管理   功能

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

答案 1 :(得分:1)

我认为您不希望收到TLabel后代已调整大小的通知。 相反,您希望收到通知,说明它缩短了文字。我知道它们看起来是一样的,但它们不是 - 标签可能仍然比文本宽,它可能会WordWrap打开,等等。此外,TCustomLabel后代可以使用几个根据主题/ Vista / Aero发光内容(它们归结为DrawThemeTextExDrawText)绘制文本的不同方法,因此您需要挂钩到该系统以确切知道它所绘制的文本是什么做,包括渲染文本的大小。

如果您使用的是非简化版的Delphi,请查看TCustomLabel中的stdctrls.pas来源。有两种感兴趣的方法:

  • TCustomLabel.AdjustBounds - 这是设置边界矩形的地方,它可以调整自动换行等。它通过调用(如同绘画)其他感兴趣的方法来实现:
  • TCustomLabel.DoDrawText - 这会绘制文本和/或计算文本边界矩形,说明省略号,包装,这种事情。 在内部,它会生成一个更改的字符串,即实际绘制的文本。换句话说,此方法的功能可以告诉您文本是否适合。

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

遗憾的是,

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

答案 2 :(得分:0)

我认为您需要覆盖 AdjustBounds 方法。请尝试以下代码(只需在其上创建一个包含 TButton TLabel 的表单,并使用此代码替换 .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.

答案 3 :(得分:0)

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

if Canvas.TextWidth(Caption) > Width then

TCustomLabel.DoDrawText确定何时绘制省略号的方式不同,因此您可能会得到意外的结果。

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