Delphi Programming / Object Pascal
サイトのトップページへ リンクのページへ ロゴマーク
[掲載 2017年03月16日] [更新 2020年04月10日] Delphi サンプルプログラム集
454_半角の英字や数字だけの入力
動作確認等 Windows 7 U64(SP1) + Delphi XE5(UP2) Pro  VCL-32 + Micorsoft Office IME 2010
454_Half-width_Letter.zip [3,606 KB] 2020年04月10日版 (EXE 同梱)







半角の英数字が入力可能な条件


TEdit 等の入力用コントロールで半角の英数字が入力可能なのは、日本語 IME が OFF の時、または、日本語 IME の [入力モード] が [半角英数] になっている場合です。これは ImeMode プロパティの値が imSAlpha の場合に相当します。

日本語 IME の入力モードが [半角英数] 以外でも、[テンキーからの入力] が [常に半角] であれば半角の数字だけの入力とすることができます。
テンキーからの入力を半角にする機能は、独自に設定可能なアプリもあります。



[備考]
TEdit 等の入力コントロールの OnKeyPress イベントで英数字の半角たけの入力制限しても、クリップボードからの貼り付けでは、全角とししての漢字は入力できます。



図1
日本語 IME の [入力モード]
  • [半角英数] にすると半角の英数字の入力制限が可能
  • Micorsoft Office IME 2010 の例
図2
テンキーからの入力設定
  • [常に半角] にするとテンキーから半角の数字の入力が可能
  • Microsoft Office IME 2010 の例




01_CharInSet を使用した半角の数字だけの入力許可


CharInSet は、第 1 引数の ASCII 文字が、第 2 引数の ASCII 文字のセット存在するかをを判定できます。それを使用したサンプルです。
半角の英数字が入力可能な状態で以下のコードを実行すると、半角の数字だけの入力を許可するようにできます。このコードは、ネット上の記事に多く掲載されています。
アルファベットだけを許可する場合は、文字セットを 'A..z' とします。



procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);
begin
  if (not CharInSet(Key, [Char(VK_BACK), '0'.. '9'])) then begin
    Key := #0;
  end;
end;


次のコードは、日本語 IME が ON の状態でも、テンキーから入力した場合は、全角の数字を半角の数字に変換して、TEdit にセットするサンプルです。
このようにすると、日本語 IME を OFF にする必要がありません。



図3
日本語 IME が ON の状態で入力
図4
[Enter] で確定しても漢字は入力されない

リスト1
半角の数字だけの入力を許可
全角の数字を入力した場合は半角の数字に変換する
//=============================================================================
//  Edit1 の OnKeyPress イベント処理
//  キーボードから数字以外の入力を禁止(数字だけを許可する)
//
//  VK_BACK を含めておかないと [Back] キーが使用できない
//=============================================================================
procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);
begin
  // コードポイント値が全角の数字だったら半角の数字の値に変換
  if (Key >= #$FF10) and (Key <= #$FF19) then begin
    Key := Char(Ord(Key) - $FEE0);
  end else begin
    if (not CharInSet(Key, [Char(VK_BACK), '0'.. '9'])) then begin
      Key := #0;
    end;
  end;
end;


全角で入力しても、半角で入力しても、数字は全て全角の数字として TEdit にセットするのであれは、例えば以下のようなコードで可能です。



procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);
begin
  if (Key >= #$FF10) and (Key <= #$FF19) then begin
    //
  end else begin
    if (not CharInSet(Key, [Char(VK_BACK), '0'.. '9'])) then begin
      Key := #0;
    end else begin
      if (CharInSet(Key, ['0'.. '9'])) then begin
        Key := Char(Ord(Key) + $FEE0);
      end;
    end;
  end;
end;




02_TCharacter.IsNumber を使用した数字だけの入力


TCharacter.IsNumber メソッドを使用すると、引数の値が数字であるを判定できます。この IsNumber メソッドを利用して数字だけを入力可能にするサンプルです。
最初の TEdit では、全角の数字を入力した場合は全角の数字を、半角の数字を入力した場合は半角の数字を TEdit にセットします。



[備考]
TCharacter.IsNumber は単に IsNumber と書いても同じです。少なくとも Delphi XE5 には他に同じ名前のメソッドは実装されていません。



図5
日本語 IME が ON の状態でテンキーから入力
  • [テンキーからの入力] 全角の設定でのテスト
図6
[Enter] で確定すると全角の数字になる
  • 半角で入力した場合は半角の数字となる

2 番目の TEdit では、全角で入力しても、半角で入力しても、数字は半角の数字として TEdit にセットします。



図7
日本語 IME が ON の状態でテンキーから入力
  • [テンキーからの入力] が全角の設定でのテスト
図8
[Enter] で確定すると半角の数字になる

リスト2
TCharacter.IsNumber を使用した数字だけの入力
unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes,
  Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  TForm1 = class(TForm)
    Edit1: TEdit;
    Edit2: TEdit;
    procedure Edit1KeyPress(Sender: TObject; var Key: Char);
    procedure Edit2KeyPress(Sender: TObject; var Key: Char);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

uses
  System.Character;

{$R *.dfm}

//=============================================================================
//  Edit1 の OnKeyPress イベント処理
//  キーボードから数字以外の入力を禁止(数字だけを許可する)
//
//  VK_BACKを含めておかないと [Back] キーが使用できない
//  TCharacter を使用する例
//  uses に System.Character が必要
//=============================================================================
procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);
begin
  if not (TCharacter.IsNumber(Key) or (Key = Char(VK_BACK))) then begin
    Key := #0;
  end;
end;

//=============================================================================
//  Edit2 の OnKeyPress イベント処理
//  キーボードから数字以外の入力を禁止(数字だけを許可する)
//
//  VK_BACK を含めておかないと [Back] キーが使用できない
//  TCharacter を使用する例
//  uses に System.Character が必要
//=============================================================================
procedure TForm1.Edit2KeyPress(Sender: TObject; var Key: Char);
begin
  if not (TCharacter.IsNumber(Key) or (Key = Char(VK_BACK))) then begin
    Key := #0;
  end else begin
    // -コードポイントの値が全角の数字だったら半角の数字の値に変換
    if (Key >= #$FF10) and (Key <= #$FF19) then begin
      Key := Char(Ord(Key) - $FEE0);
    end;
  end;
end;

end.




03_TCharHelper.IsNumber を使用した数字だけの入力


Delphi XE3 以降では TCharacter は非推奨になっています。代わりに TCharHelper が使用できます。TCharHelper は Char 型のヘルパーです。TCharHelper を使用すると、Char 型の変数に対して直接 TCharHelper のメソッドが実行できます。
以下のコードは Delphi XE5 で動作を確認しています。動作は上のサンプルと同じです。



リスト3
TCharHelper を使用した数字だけの入力
unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes,
  Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  TForm1 = class(TForm)
    Edit1: TEdit;
    Edit2: TEdit;
    procedure Edit1KeyPress(Sender: TObject; var Key: Char);
    procedure Edit2KeyPress(Sender: TObject; var Key: Char);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

uses
  System.Character;

{$R *.dfm}

//=============================================================================
//  Edit1 の OnKeyPress イベント処理
//  キーボードから数字以外の入力を禁止(数字だけを許可する)
//
//  VK_BACK を含めておかないと [Back] キーが使用できない
//  TCharHelper の機能を利用する例
//  uses に System.Character が必要
//=============================================================================
procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);
begin
  if not ((Key.IsNumber) or (Key = Char(VK_BACK))) then begin
    Key := #0;
  end;
end;

//=============================================================================
//  Edit2のOnKeyPress イベント処理
//  キーボードから数字以外の入力を禁止(数字だけを許可する)
//
//  VK_BACK を含めておかないと [Back] キーが使用できない
//  TCharHelper の機能を利用する例
//  uses に System.Character が必要
//=============================================================================
procedure TForm1.Edit2KeyPress(Sender: TObject; var Key: Char);
begin
  if not ((Key.IsNumber) or (Key = Char(VK_BACK))) then begin
    Key := #0;
  end else begin
    // コードポイントの値が全角の数字だったら半角の数字の値に変換
    if (Key >= #$FF10) and (Key <= #$FF19) then begin
      Key := Char(Ord(Key) - $FEE0);
    end;
  end;
end;

end.




04_クリップボードからの貼り付けを捕捉


ここまでのサンプルでは、TEdit 等の入力コントロールの OnKeyPress イベントで英数字の半角たけの入力制限の処理をしています。以下のリンクの記事のサンプルのように、OnChange イベントで処理する方法も考えられます。この方法であれば、クリップボードからの貼り付けの操作でも入力した文字の判定や処理が可能です。

クリップボードの文字列だけを処理するには、コンポーネントの継承クラスを作成して、WM_PASTE メッセージを処理します。以下は、TEdit に整数だけを入力する例です。
継承クラスを作成しているので、このサンプルでは、キー入力も継承クラスの KeyPress メソッドを使用していますが、これまでのサンプルのように、イベントで処理しても同じです。



このサンプルでは、継承クラスをコンポーネントとして登録しないで、添付の plChgCompo ユニットを使用して、実行時にコンポーネントを派生クラスに置き換えてテストしています。



図9
クリップボードから貼り付け
図10
整数に変換できない場合
図11
整数に変換できる場合
  • 整数に変換して Text プロパティに代入

リスト4
クリップボードからの貼り付を、継承クラスの WM_PASTE メッセージで捕捉する
unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes,
  Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  TplIntEdit = class(TEdit)
  protected
    procedure WMPaste(var Message: TWMPaste); message WM_PASTE;
    procedure KeyPress(var Key: Char); override;
  end;

  TForm1 = class(TForm)
    Edit1: TEdit;
    procedure FormCreate(Sender: TObject);
  private
    { Private 宣言 }
    plIntEdit1 : TplIntEdit;
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

uses
  System.Character,
  Vcl.Clipbrd,
  plChgCompo;

{$R *.dfm}

//=============================================================================
//  フォーム生成時の処理
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
  // フォーム作成時にコンポーネントの入れ替え
  plIntEdit1 := TplIntEdit(ChangeComponent(Edit1, TplIntEdit));
end;

{ TplIntEdit }

//=============================================================================
//  TEdit の継承クラスの KeyPress メソッド
//  キーボードから数字以外の入力を禁止(数字だけを許可する)
//
//  VK_BACKを含めておかないと[Back]キーが使用できない
//=============================================================================
procedure TplIntEdit.KeyPress(var Key: Char);
begin
  inherited;

  if not ((Key.IsNumber) or (Key = Char(VK_BACK))) then begin
    Key := #0;
  end else begin
    // コードポイントの値が全角の数字だったら半角の数字の値に変換
    if (Key >= #$FF10) and (Key <= #$FF19) then begin
      Key := Char(Ord(Key) - $FEE0);
    end;
  end;//
end;

//=============================================================================
//  TEdit の継承クラスの WM_PASTE メッセージ処理
//  クリップボードの文字列が整値に変換できれば Text プロパティに文字列をセット
//  整数に変換できない時は Text プロパティに空文字をセット
//=============================================================================
procedure TplIntEdit.WMPaste(var Message: TWMPaste);
var
  LClipbrdText : string;
  LInteger     : Integer;
  LMsgText     : string;
begin
  inherited;

  if Clipboard.HasFormat(CF_TEXT) then begin
    LClipbrdText := Clipboard.AsText;

    if TryStrToInt(LClipbrdText, LInteger) then begin
      Text := IntToStr(LInteger);
    end else begin
      Text := '';
      LMsgText := LClipbrdText + sLineBreak + 'は整数に変換できません';
      MessageBox(Handle, PChar(LMsgText), 'クリップボード', MB_ICONWARNING);
      SetFocus;
    end;
  end;
end;

end.


WM_PASTE メッセージの処理で、inherited (継承元の処理) を実行しないと、クリップボードからの貼り付けはできません。inherited は継承という意味です。


procedure TplIntEdit.WMPaste(var Message: TWMPaste);
var
  LMsgText : string;
begin
  if Clipboard.HasFormat(CF_TEXT) then begin
    LMsgText := 'クリップボードからの貼り付けは禁止です。';
    MessageBox(Handle, PChar(LMsgText), '貼り付け禁止', MB_ICONINFORMATION);
    SetFocus;
  end else begin
    inherited;
  end;
end;


コントロールのメッセージは WndProc メソッドでも補足できます。また、サブクラス化という手法を用いると、継承クラスを作成しなくてもコントロールのメッセージが捕捉できます。