如何为 TLabel (TGraphicControl) 创建调整大小事件

发布于 2024-10-21 09:06:37 字数 797 浏览 3 评论 0原文

我正在尝试创建 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;

非常感谢:)

I'm trying to create TLabel descendant, which will display hint with the whole caption when the text width exceed label width. I've set the EllipsisPosition property to epEndEllipsis and my caption is automatically shorted by an ellipsis at the end. That's fine.

However I need to be notified, that the text has been shortened to set up the hint. This in my case may happen only when the text is changed (message CM_TEXTCHANGED) and when the component is resized.

And that's my question - how can I be notified, that my TLabel has been resized ? I have the anchors there, so it's resized along with the form, but I would like to wrap it in the separate TLabel descendant.

This code works, but isn't there a better way ? Something like WM_EXITSIZEMOVE, but working for 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;

Thanks a lot :)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

眼角的笑意。 2024-10-28 09:06:37

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

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

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

两者都是动态,在语义上等同于虚拟 - 即,您可以覆盖它们。

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

I don't think you want to be notified that the TLabel descendant has been resized. Instead, you want to be notified that it has shortened the text. I know they seem the same, but they're not - the label might still be wider than the text, it might have WordWrap turned on, etc. In addition, TCustomLabel descendants can use a couple of different methods to draw text, based on theming / Vista / Aero glow stuff (they boil down to DrawThemeTextEx and DrawText), so you need to hook into that system to know exactly what the text it's drawing is doing, including what the size of the rendered text is.

If you're using a non-Starter edition of Delphi, have a look at the TCustomLabel source in stdctrls.pas. There are two methods of interest:

  • TCustomLabel.AdjustBounds - this is where the bounding rectangle is set, and it adjusts for word wrapping etc. It does this by calling (as does painting) the other method of interest:
  • TCustomLabel.DoDrawText - this paints the text and/or calculates the text bounding rectangle accounting for ellipses, wrapping, that kind of thing. Internally, it generates an altered string that is the text that is actually painted. In other words, this method's functionality is what tells you whether the text fits or not.

Both are dynamic, which is semantically equivalent to being virtual - ie, you can override them.

DoDrawText unfortunately doesn't return the final text string it's painting - if it did, you could override it, call the inherited version and compare the painted text with the real text. However, you can override and reimplement it, and do this yourself. Use the VCL code as a guide (you want equivalent functionality, although you should not copy it directly since it's owned by Embarcadero.) Being dynamic, your descendant class's version will be called by AdjustBounds. In your code, when you shorten the text, also set a flag it's been shortened or generate the hint immediately. Voila. You accurately know exactly when it's been shortened :)

无法言说的痛 2024-10-28 09:06:37

我想不出还有什么比 WM_WINDOWPOSCHANGED 更好的了:

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

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

I can't think of anything better than WM_WINDOWPOSCHANGED:

Sent to a window whose size, position,
or place in the Z order has changed as
a result of a call to the SetWindowPos
function or another window-management
function.

That looks ideal. What do you have against using it?

甜味超标? 2024-10-28 09:06:37

我认为您需要重写 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.

I think you need to override the AdjustBounds method. Try the following code (simply create a form with a TButton and TLabel on it and replace the .pas with this code). This example demonstrates detecting a label size change if the text changes. You will need to create your own event though.

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.
掐死时间 2024-10-28 09:06:37

您只需重写 Resize 方法即可。但是,请注意,您的代码

if Canvas.TextWidth(Caption) > Width then

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

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

You can simply override Resize method. However, be aware that your code

if Canvas.TextWidth(Caption) > Width then

is different from how TCustomLabel.DoDrawText determines when to draw ellipses so you may get unexpected results.

Also, the ellipses drawing may also be caused by a font change, a theme setting change, and maybe some other events.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文