Wie man am besten programmatisch sagen, ob ein TLabel Caption abgeschnitten wird (das heißt Auslassungs drawn verwendet wird)?
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 DrawThemeTextEx
with 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.
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