Tlabelのキャプションがクリップされているかどうかをプログラム的に伝えるのが最善です(つまり、Ellipsisを使用して描画されます)?

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

質問

私は持っています TLabelEllipsisPosition に設定 epEndEllipsis そして、テキストが現在切り取られているかどうかを判断できる必要があります。テキストを自分で表示するために必要な領域を計算し、ラベルの実際の寸法と比較することに加えて、誰もがこれを行うより簡単な/よりエレガントな方法を思いつきましたか?

実際、必要な領域をフェイルセーフの方法で計算することも、聞こえるほど簡単ではないようです...たとえば TCanvas.GetTextHeight ラインブレイクを考慮していません。

TCustomLabel.DoDrawText どちらかを内部的に使用します DrawTextW また DrawThemeTextExとともに DT_CALCRECT 楕円を使用するかどうかを判断するためのフラグ。そこにはかなり多くのコードが関係していますが、それらはすべて宣言されています private. 。すべてのコードを単に複製するだけで、私の本の中で「エレガント」として正確に適格ではないでしょう...

何か案は?

(Delphi-version固有のソリューションを思いついた場合に備えて、Delphi 2010を使用しています)

更新1: 私は今、私は単に電話できることを理解しました TCustomLabel.DoDrawText(lRect, DT_CALCRECT) 直接(これは単に宣言されています protected)コードを複製することなく、必要なサイズの計算をラベルに実行させる。一時的に設定するようにする必要があります EllipsisPositionepNone または、一時ラベルインスタンスを完全に使用します。これは実際にはそれほど悪くはありません。さらに簡単な解決策を考えることができないなら、私はそれを使って行くかもしれません。

更新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 (特に人工のパディングと正しいワードラップ設定)また、マルチラインとワードラップの入力テキストを正しく扱います。この場合、「正しく」は「常に戻る」という意味であることに注意してください 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で最も単純なコンポーネントの1つです。文字列を描画するだけです。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top