文字列省略時の...の位置

解決


Manbon  2008-11-27 14:33:09  No: 32736  IP: 192.*.*.*

以下のコードを実行しますと、フォーム上に
「1234567...」
と表示されます。これを、
「...3456789」
というふうに、また、
「1234...789」
というふうに表示させたいのですが、何か方法はあるでしょうか?

var
  R: TRect;
begin
  R.Top := 0;
  R.Left := 0;
  R.Right := 50;
  R.Bottom := 20;
  DrawText(Canvas.Handle, PChar('123456789'), -1, R, DT_END_ELLIPSIS);
end;

編集 削除
とりあえず  2008-11-27 16:45:41  No: 32737  IP: 192.*.*.*

先頭の省略は簡単だけど、中の省略はチョット面倒。

function MinimizeString(const aStr: string; Canvas: TCanvas; MaxLen: Integer): string;
const
  MINIMIZESTR = '...';
var
  cLen: Integer;
  p: PChar;  
begin
  result := aStr;
  if (Canvas.TextWidth(aStr) < MaxLen) then exit;
  p := PChar(aStr);
  cLen := Canvas.TextWidth(MINIMIZESTR);
  while (Canvas.TextWidth(p) + cLen > MaxLen) do begin
   if IsDBCSLeadByte(Byte(p^)) then inc(p, 2) else inc(p);
  end;
  result := MINIMIZESTR + p;
end;

編集 削除
monaa  2008-11-27 17:00:55  No: 32738  IP: 192.*.*.*

「1234...789」は
Win32API: DrawTextの
dwFormat : DT_PATH_ELLIPSIS
がそれに相当します。
「...3456789」に相当するものはありません
by MSDN
http://msdn.microsoft.com/ja-jp/library/cc428474.aspx

編集 削除
おや?  2008-11-27 17:29:29  No: 32739  IP: 192.*.*.*

>「...3456789」に相当するものはありません
文字列に \ が含まれないか1個だけだと、DT_PATH_ELLIPSISは先頭を省略する仕様らしい...

編集 削除
やっぱり  2008-11-28 18:59:51  No: 32740  IP: 192.*.*.*

DT_PATH_ELLIPSISは、ファイルPATHでない普通の文字列の省略には
むかないね。

function MinimizeString(const aStr: string; Canvas: TCanvas; MaxWidth: Integer;
 isMiddle: Boolean=True; LeftLen: Integer=3): string;
const
  MINIMIZESTR = '...';
var
  i, cWidth, fWidth: Integer;
  pT, pL, pB: PChar;
  cc: Char;
  sLeft: string;
begin
  result := aStr;
  if (Canvas.TextWidth(aStr) < MaxWidth) then exit;
  pT := PChar(aStr);
  cWidth := Canvas.TextWidth(MINIMIZESTR);
  if not isMiddle then begin
   while (Canvas.TextWidth(pT) + cWidth > MaxWidth) do begin
    if IsDBCSLeadByte(Byte(pT^)) then inc(pT, 2) else inc(pT);
   end;
   result := MINIMIZESTR + pT;
  end else begin
   pL := pT + Length(aStr);
   pB := pT;
   for i:=1 to LeftLen do begin
    if IsDBCSLeadByte(Byte(pB^)) then inc(pB, 2) else inc(pB);
   end;
   cc := pB^;
   pB^ := #0;
   sLeft := pT;
   fWidth := Canvas.TextWidth(sLeft) + cWidth;
   pB^ := cc;
   while (Canvas.TextWidth(pB) > MaxWidth - fWidth) do begin
    if pB > pL then break;
    if IsDBCSLeadByte(Byte(pB^)) then inc(pB, 2) else inc(pB);
   end;
   result := sLeft + MINIMIZESTR + pB;
  end;
end;

編集 削除
う〜ん...やはり  2008-11-28 23:22:35  No: 32741  IP: 192.*.*.*

中を省略する場合は、'...'が文字列の中央あたりにあった方がイイね。

function MinimizeString(const aStr: string; Canvas: TCanvas; MaxWidth: Integer;
 isMiddle: Boolean=True): string;
const
  MINIMIZESTR = '...';
var
  i, cWidth, fWidth: Integer;
  pT, pL, pB: PChar;
  cc: Char;
  sLeft: string;
begin
  result := aStr;
  if (Canvas.TextWidth(aStr) < MaxWidth) then exit;
  pT := PChar(aStr);
  cWidth := Canvas.TextWidth(MINIMIZESTR);
  if not isMiddle then begin
   while (Canvas.TextWidth(pT) + cWidth > MaxWidth) do begin
    if IsDBCSLeadByte(Byte(pT^)) then inc(pT, 2) else inc(pT);
   end;
   result := MINIMIZESTR + pT;
  end else begin
   pL := pT + Length(aStr);
   pB := pT;
   repeat
    if IsDBCSLeadByte(Byte(pB^)) then inc(pB, 2) else inc(pB);
    cc := pB^;
    pB^ := #0;
    sLeft := pT;
    fWidth := Canvas.TextWidth(sLeft) + cWidth;
    pB^ := cc;
   until fWidth > (MaxWidth div 2);
   while (Canvas.TextWidth(pB) > MaxWidth - fWidth) do begin
    if pB > pL then break;
    if IsDBCSLeadByte(Byte(pB^)) then inc(pB, 2) else inc(pB);
   end;
   result := sLeft + MINIMIZESTR + pB;
  end;
end;

編集 削除
Manbon  2008-12-02 11:24:46  No: 32742  IP: 192.*.*.*

遅くなりました。ありがとうございます。
先頭の...はばっちりでした。
ですが、途中の省略では、「pB^ := #0;」の部分で
書込み違反が出てしまいます・・・。
問題ないように見えるのですが、わかりませんでした。
もうちょっと調べてみます。

編集 削除
そう...だったら  2008-12-02 13:20:18  No: 32743  IP: 192.*.*.*

ここを、
>   cc := pB^;
>   pB^ := #0;
>   sLeft := pT;
>   fWidth := Canvas.TextWidth(sLeft) + cWidth;
>   pB^ := cc;

こう変えてみたらどう?
    sLeft := Copy(aStr, 1, pB-pT);
    fWidth := Canvas.TextWidth(sLeft) + cWidth;

編集 削除
Manbon  2008-12-02 14:24:15  No: 32744  IP: 192.*.*.*

ありがとうございます!!できました。
Copy関数の中でのPCharの引き算など、
何故こういうことができるのか、まださっぱりですので、
ちょっと勉強しようと思います。

編集 削除