ユーザーがキーボードから数値を入力するとき、3桁区切りのコンマがリアルタイムに挿入されるようにします。
文字の入力時というと KeyPress
メソッドが思いつきますが、コンマの挿入は Change
メソッドで行います。Change
メソッドであれば、キー入力以外で文字が入力されたとき(たとえばクリップボードから貼り付けが行われたとき)にも対応できます。
Changeメソッドの修正
Changeメソッドを以下のように修正します。
procedure TCustomNumberEdit.Change;
var
NewValue: Extended;
DecimalPos: Integer;
Settings: TFormatSettings;
S: string;
SeparatorCount: Integer;
OldSeparatorCount: Integer;
OldText: string;
CursorPos: Integer;
I: Integer;
begin
NewValue := TextToValue(Text);
// 整数部に3桁ごとのコンマを挿入
if FComma then
begin
Settings := TFormatSettings.Create;
DecimalPos := Pos(Settings.DecimalSeparator, Text);
if DecimalPos = 0 then
begin
// 小数点がない
S := FormatFloat('#,##0', NewValue);
end
else
begin
// 小数点がある: 整数部だけ抜き出してコンマを付ける
S := FormatFloat('#,##0', Int(NewValue));
S := S + Copy(Text, DecimalPos, Length(Text) - DecimalPos + 1);
end;
// カーソル位置の調整
OldText := Text;
OldSeparatorCount := 0;
for I := 1 to SelStart do
if OldText[I] = Settings.ThousandSeparator then Inc(OldSeparatorCount);
SeparatorCount := 0;
for I := 1 to SelStart do
if S[I] = Settings.ThousandSeparator then Inc(SeparatorCount);
CursorPos := SelStart + (SeparatorCount - OldSeparatorCount);
Text := S;
SelStart := CursorPos;
end;
if NewValue <> FValue then
begin
FValue := NewValue;
inherited;
end;
end;
小数部のない数値だとコンマを入れるのは簡単です。小数部がある数値の場合、整数部を抜き出してコンマ付きの文字列にします(74行目)。それから小数点以下の文字列を抜き出して、コンマ付きの整数部と結合します(75行目)。
コンマを入れる処理で大事な部分が、78行目以降のカーソル位置の調整です。途中でコンマが挿入されると、カーソル位置がずれてしまいます。このズレを求めて、カーソル位置(SelStart
)を調整します。
OldSeparatorCount
変数が、表示されている文字列(数値)の先頭から現カーソル位置までのコンマの数です。
SeparatorCount
変数が、新たにコンマを付けた文字列の先頭から、現カーソル位置までのコンマの数です。
この2つの変数の差が、新たに挿入されたコンマ、または削除されたコンマの数となるので、その分だけカーソル位置を移動させます(88行目)。
次回は・・・
クリップボードからの貼り付けというキーワードが今回出たので、次回はクリップボードからの貼り付け処理について記述します。