Wie man am besten programmatisch sagen, ob ein TLabel Caption abgeschnitten wird (das heißt Auslassungs drawn verwendet wird)?

StackOverflow https://stackoverflow.com/questions/4313607

Frage

Ich habe einen TLabel mit EllipsisPosition Set epEndEllipsis und ich muß in der Lage sein zu sagen, ob der Text zur Zeit abgeschnitten wird oder nicht. Neben den Bereich Berechnung erforderlich, um den Text selbst anzuzeigen und mit den tatsächlichen Abmessungen des Etiketts zu vergleichen, hat jemand kommt mit einer einfacheren / eleganten Art und Weise, dies zu tun?

Eigentlich in einem der erforderlichen Flächenberechnung ausfallsicher auch erscheint nicht so geradlinig zu sein, wie es klingt ... Zum Beispiel TCanvas.GetTextHeight nehmen nicht berücksichtigt Zeilenumbrüchen.

TCustomLabel.DoDrawText intern verwendet entweder DrawTextW oder DrawThemeTextExwith den DT_CALCRECT Flag, um zu bestimmen, ob es auf die Ellipsen oder nicht verwenden sollte. Es gibt eine ganze Menge Code dort beteiligt, von denen alle private deklariert wird. Einfach alle Duplizierung dieser Code nicht genau als "elegant" in meinem Buch qualifizieren würde ...

Irgendwelche Ideen?

(Ich verwende Delphi 2010, falls jemand kommt mit einer Delphi-Version spezifischen Lösung nach oben)

Update 1: ich jetzt herausgefunden, dass ich einfach TCustomLabel.DoDrawText(lRect, DT_CALCRECT) direkt anrufen kann (was lediglich protected deklariert ist) das Etikett lassen Sie die gewünschten Größe Berechnung durchführen, ohne seinen Code zu duplizieren. Ich muss nur sicher vorübergehend Satz EllipsisPosition zu epNone entweder machen oder eine temporäre Etikett Instanz zusammen zu verwenden. Dies ist eigentlich nicht so schlimm, und ich könnte nur mit ihm gehen, wenn niemand von einer noch einfacheren Lösung denken kann.

Update 2: Ich habe nun meine Lösung als separate Antwort gegeben. Es erwies sich als eher geradlinig, als ich so da zu erwarten ist wahrscheinlich nicht leichter / besseren Weg, es zu tun, aber ich werde diese Frage offen für ein wenig verlassen, während länger ohnehin nur für den Fall.

War es hilfreich?

Lösung

FWIW, hier ist, was ich kam mit (dies ist eine Methode eines benutzerdefinierten TLabel-Abkömmling):

function TMyLabel.IsTextClipped: Boolean;
const
  EllipsisStr = '...';
var
  lEllipBup: TEllipsisPosition;
  lRect: TRect;
begin
  lRect := ClientRect;
  Dec(lRect.Right, Canvas.TextWidth(EllipsisStr));

  lEllipBup := EllipsisPosition;
  EllipsisPosition := epNone;
  try
    DoDrawText(lRect, DT_CALCRECT or IfThen(WordWrap, DT_WORDBREAK));
  finally
    EllipsisPosition := lEllipBup;
  end;
  Result := ((lRect.Right - lRect.Left) > ClientWidth)
         or ((lRect.Bottom - lRect.Top) > ClientHeight);
end;

Da dies nun verwendet genau die gleiche Logik wie TCustomLabel.DoDrawText (vor allem die künstliche Polsterung und die richtige Einstellung WordWrap) es beschäftigt sich auch korrekt mit mehreren Leitungen und Wort-wrapped Eingabetexte. Beachten Sie, dass „richtig“ bedeutet in diesem Fall „es True immer zurückkehrt, wenn der TLabel mit einem beschnittenen caption und False gezogen wird anders“.

Während der obige Code tut, was ich ursprünglich gebeten, denn ich werde es wahrscheinlich nicht auf diese Weise nutzen - aber das ist mehr wegen Mängel der TLabel selbst: Gerade bei mehrzeiligen Text es oft nicht die Art und Weise verhält ich gewollt hätte es zB wenn es nicht genug Platz für mehrere Zeilen, so wird das letzte Wort der ersten Zeile immer noch abgeschnitten, wenn die gesamte Linie und die Auslassungs würde ausgerüstet haben.

Andere Tipps

Als Ausgangspunkt könnten Sie verwenden

function DrawStringEllipsis(const DC: HDC; const ARect: TRect; const AStr: string): boolean;
var
  r: TRect;
  s: PChar;
begin
  r := ARect;
  GetMem(s, length(AStr)*sizeof(char) + 8);
  StrCopy(s, PChar(AStr));
  DrawText(DC, PChar(s), length(AStr), r, DT_LEFT or DT_END_ELLIPSIS or DT_MODIFYSTRING);
  result := not SameStr(AStr, s);
  FreeMem(s);
end;

Verwendungsbeispiel:

procedure TForm1.FormClick(Sender: TObject);
begin
  Caption := 'Clipped ' + BoolToStr(DrawStringEllipsis(Canvas.Handle, Rect(10, 100, 50, 50), 'This is a text.'), true);
end;

Es wäre nicht schwierig sein, eine TExtLabel Komponente zu schreiben, die eine WasClipped Eigenschaft mit dieser Technik hat. Tatsächlich ist die TLabel Komponente eine der einfachsten Komponenten in der VCL -. Zieht es nur eine Zeichenfolge

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top