Как создать событие изменения размера для TLabel (TGraphicControl) - PullRequest
1 голос
/ 10 марта 2011

Я пытаюсь создать потомка 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 ]

1 голос
/ 11 марта 2011

Не думаю, что вы хотите получать уведомление о том, что размер потомка TLabel был изменен. Вместо этого вы хотите получить уведомление о сокращении текста .Я знаю, что они кажутся одинаковыми, но это не так - метка может быть все же шире, чем текст, может быть включена WordWrap и т. Д. Кроме того, потомки TCustomLabel могут использовать несколько разных методов длятекст, основанный на тематике / Vista / Aero, светящиеся вещи (они сводятся к DrawThemeTextEx и DrawText), поэтому вам нужно подключиться к этой системе, чтобы точно знать, чтотекст, который рисует, включая размер отображаемого текста.

Если вы используете не начальную версию Delphi, взгляните на источник TCustomLabel в stdctrls.pas.Есть два метода, представляющих интерес:

  • TCustomLabel.AdjustBounds - это где ограничивающий прямоугольник, и он настраивается для переноса слов и т. Д. Это делается путем вызова (как рисование) другого методаинтерес:
  • TCustomLabel.DoDrawText - это рисует текст и / или вычисляет текст ограничивающего прямоугольника с учетом эллипсов, обтеканий и тому подобное. Внутренне, он генерирует измененную строку, которая является текстом, который фактически нарисован. Другими словами, функциональность этого метода - это то, что говорит вам, подходит ли текст или нет.

Обаdynamic, что семантически эквивалентно virtual - то есть вы можете переопределить их.

DoDrawText к сожалению, не возвращает окончательную текстовую строку, которую рисует - если это так, вы могли бы переопределитьэто, вызовите унаследованную версию и сравните нарисованный текст с реальным текстом.Тем не менее, вы можете переопределить и переопределить его, и сделать это самостоятельно.Используйте код VCL в качестве руководства (вам нужна эквивалентная функциональность, хотя вы не должны копировать его напрямую, поскольку он принадлежит Embarcadero.) Будучи dynamic, версия вашего потомка будет вызываться AdjustBounds.В своем коде, когда вы укорачиваете текст, также устанавливаете флаг, он был укорочен, или немедленно генерируйте подсказку.Вуаля.Вы точно знаете точно, когда оно было сокращено:)

1 голос
/ 10 марта 2011

Я не могу придумать ничего лучше, чем WM_WINDOWPOSCHANGED:

Отправлено в окно, размер, положение или место которого в Z-порядке изменились в результате вызоваФункция SetWindowPos или другая функция управления окнами.

Это выглядит идеально.Что ты имеешь против использования?

0 голосов
/ 10 марта 2011

Вы можете просто переопределить метод Resize. Однако учтите, что ваш код

if Canvas.TextWidth(Caption) > Width then

отличается от того, как TCustomLabel.DoDrawText определяет, когда рисовать эллипсы, чтобы вы могли получить неожиданные результаты.

Кроме того, рисование эллипсов также может быть вызвано изменением шрифта, изменением настроек темы и, возможно, некоторыми другими событиями.

0 голосов
/ 10 марта 2011

Я думаю, вам нужно переопределить метод 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.
...