أفضل السبل لمعرفة ما إذا كان يتم قطع تعليق TLABEL (أي رسم باستخدام Ellipsis)؟

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

سؤال

انا املك TLabel مع EllipsisPosition ضبط ل epEndEllipsis وأحتاج إلى أن أكون قادرًا على معرفة ما إذا كان النص قد تم قصه حاليًا أم لا. إلى جانب حساب المنطقة المطلوبة لعرض النص بنفسي ومقارنته بالأبعاد الفعلية للتسمية ، هل توصل أي شخص إلى طريقة أسهل/أكثر أناقة للقيام بذلك؟

في الواقع ، لا يبدو أن حساب المنطقة المطلوبة بطريقة آمنة من الفشل أيضًا مستقيمًا كما يبدو ... على سبيل المثال TCanvas.GetTextHeight لا يأخذ في الاعتبار خطوط الخطوط.

TCustomLabel.DoDrawText يستخدم داخليا سواء DrawTextW أو DrawThemeTextExمع ال DT_CALCRECT العلم لتحديد ما إذا كان ينبغي أن تستخدم القطع الإهليلجي أم لا. هناك الكثير من التعليمات البرمجية المتورطة هناك ، وكلها تم الإعلان عنها private. ببساطة تكرار كل هذا الرمز لن يكون مؤهلاً تمامًا كـ "أنيقة" في كتابي ...

أيه أفكار؟

(أنا أستخدم Delphi 2010 في حال جاء أي شخص بحل خاص بـ Delphi-Version)

تحديث 1: لقد اكتشفت الآن أنه يمكنني ببساطة الاتصال TCustomLabel.DoDrawText(lRect, DT_CALCRECT) مباشرة (والتي تم الإعلان عنها فقط protected) للسماح للتسمية بإجراء حساب الحجم المطلوب دون الحاجة إلى تكرار الكود الخاص به. لا بد لي من التأكد من تعيين إما مؤقتًا EllipsisPosition إلى epNone أو استخدم مثيل تسمية مؤقتة تمامًا. هذا في الواقع ليس بهذا السوء وقد أذهب معه إذا لم يتمكن أي شخص من التفكير في حل أبسط.

تحديث 2: لقد أضفت حولي الآن كإجابة منفصلة. اتضح أنه أكثر استقامة إلى الأمام مما كنت أتوقع ، لذلك ربما لا توجد طريقة أسهل/أفضل للقيام بذلك ، لكنني سأترك هذا السؤال مفتوحًا لفترة قصيرة على أي حال فقط في حالة.

هل كانت مفيدة؟

المحلول

fwiw ، إليك ما توصلت إليه (هذه طريقة للعرف TLabel-تنازلي):

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;

لأن هذا يستخدم الآن نفس المنطق تمامًا TCustomLabel.DoDrawText (خاصة الحشوة الاصطناعية وإعداد WordWrap الصحيح) ، كما أنه يتعامل بشكل صحيح مع نصوص الإدخال متعددة الخطوط والكلمات. لاحظ أن "بشكل صحيح" في هذه الحالة يعني "أنه يعود دائمًا True عندما TLabel يتم رسمها بتعليق مقطوع و False خلاف ذلك".

على الرغم من أن الرمز أعلاه يفعل ما طلبته في الأصل ، فلن أستخدمه على هذا النحو - ولكن هذا يرجع إلى أوجه القصور TLabel نفسها: خاصة مع النص متعدد الخطوط ، غالبًا ما لا يتصرف بالطريقة التي كنت أرغب فيها ، على سبيل المثال ، عندما لا يكون هناك مساحة كافية لخطوط متعددة ، سيتم دائمًا اقتطاع الكلمة الأخيرة من السطر الأول حتى لو كان من الممكن تركيب القطع الناقص.

نصائح أخرى

كنقطة انطلاق ، يمكنك استخدامها

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;

استخدام العينة:

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

لن يكون من الصعب كتابة ملف TExtLabel المكون الذي يحتوي على ملف WasClipped خاصية باستخدام هذه التقنية. في الواقع ، TLabel يعد المكون أحد أبسط المكونات في VCL - وهو يرسم سلسلة فقط.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top