以下のコードを実行しますと、フォーム上に
「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;
先頭の省略は簡単だけど、中の省略はチョット面倒。
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;
「1234...789」は
Win32API: DrawTextの
dwFormat : DT_PATH_ELLIPSIS
がそれに相当します。
「...3456789」に相当するものはありません
by MSDN
http://msdn.microsoft.com/ja-jp/library/cc428474.aspx
>「...3456789」に相当するものはありません
文字列に \ が含まれないか1個だけだと、DT_PATH_ELLIPSISは先頭を省略する仕様らしい...
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;
中を省略する場合は、'...'が文字列の中央あたりにあった方がイイね。
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;
遅くなりました。ありがとうございます。
先頭の...はばっちりでした。
ですが、途中の省略では、「pB^ := #0;」の部分で
書込み違反が出てしまいます・・・。
問題ないように見えるのですが、わかりませんでした。
もうちょっと調べてみます。
ここを、
> cc := pB^;
> pB^ := #0;
> sLeft := pT;
> fWidth := Canvas.TextWidth(sLeft) + cWidth;
> pB^ := cc;
こう変えてみたらどう?
sLeft := Copy(aStr, 1, pB-pT);
fWidth := Canvas.TextWidth(sLeft) + cWidth;
ありがとうございます!!できました。
Copy関数の中でのPCharの引き算など、
何故こういうことができるのか、まださっぱりですので、
ちょっと勉強しようと思います。
ツイート | ![]() |