DOBON.NET DOBON.NETプログラミング掲示板過去ログ

数値入力専用テキストボックス

環境/言語:[WinXP, VB.NET2003, CompactFramework1.0]
分類:[.NET]

はじめて投稿いたします。

VB.NET2003と.NET CompactFrameworkを使用して、PDA端末
ようの数値入力専用テキストボックスを自作しようとしています。
クラスは、System.Windows.Forms.TextBoxから派生させています。
キー入力があった際、文字コードをチェックして数値以外であれば
入力されないようにしたいのです。

そこで、OnKeyDownを使って、数字以外であれば、KeyEventArgs
のHandledをTrueに設定して、KeyDownイベントが発生しないように
しようとしましたが、うまくいきません。
数字かどうかのチェックはできていますが、数字以外の文字でもテキスト
ボックスには表示されてしまいます。

KeyDownイベントをキャンセルする方法、もしくは数字以外の文字を
テキストボックスには表示させない方法がありましたご教示ください。
チャコさんこんにちは。そんと申します。

> キー入力があった際、文字コードをチェックして数値以外であれば
> 入力されないようにしたいのです。
>
> そこで、OnKeyDownを使って、数字以外であれば、KeyEventArgs
> のHandledをTrueに設定して、KeyDownイベントが発生しないように
> しようとしましたが、うまくいきません。

KeyPressイベントを使って数字以外の文字ならばイベントをキャンセルするように
するとうまくいくと思います。
「どうしてもKeyDownイベントで」と仰るならお役に立てませんが。。。

Private Sub TextBox1_KeyPress(ByVal sender As Object, ByVal e As
System.Windows.Forms.KeyPressEventArgs) Handles TextBox1.KeyPress

If Char.IsNumber(e.KeyChar) = False Then
e.Handled = True
End If
End Sub
先ほどのソースでは、数字以外のBackspaceも効かなくなってしまいますね。
うっかりしていました。すみません。

> If Char.IsNumber(e.KeyChar) = False Then
ではなく、

If Char.IsNumber(e.KeyChar) = False And e.KeyChar <> vbBack Then

に変更してください。
他にも小数点の入力を許可したい場合など適宜変更して下さい。
2004/09/09(Thu) 12:22:35 編集(投稿者)

こんにちは、そんさん。

■No6068に返信(そんさんの記事)
> 先ほどのソースでは、数字以外のBackspaceも効かなくなってしまいますね。
> うっかりしていました。すみません。
>
>> If Char.IsNumber(e.KeyChar) = False Then
> ではなく、
>
> If Char.IsNumber(e.KeyChar) = False And e.KeyChar <> vbBack Then
>
> に変更してください。
> 他にも小数点の入力を許可したい場合など適宜変更して下さい。

Char.IsNumber(e.KeyChar) = False でやると、
Keys.Back のみならず、[Ctrl]+[C]とか便利なショートカットキーも利かなくなりませんか?

■追記

 # 逆に、コンテキストメニューから「貼り付け」を選べば、数字以外も入力できてしまうので、
 # TextChangedイベントで削る処理も含めた方がいいでしょう。
こんにちは、java.lang.Nullpoさん

> Char.IsNumber(e.KeyChar) = False でやると、
> Keys.Back のみならず、[Ctrl]+[C]とか便利なショートカットキーも利かなくなりませんか?
>
> ■追記
>  # 逆に、コンテキストメニューから「貼り付け」を選べば、数字以外も入力できてしまうので、
>  # TextChangedイベントで削る処理も含めた方がいいでしょう。

確かにその通りですね。考えが浅かったです。
(全角文字も入力されてしまうようですし。。。)
初心者の自分でも役に立てるかもと深く考えずに回答したのですが
勇み足だったみたいです。

ご指摘ありがとうございます。勉強になりました。
2004/09/09(Thu) 16:28:25 編集(投稿者)

■No6081に返信(そんさんの記事)
> こんにちは、java.lang.Nullpoさん
こんにちは、そんさん。

> 確かにその通りですね。考えが浅かったです。
> (全角文字も入力されてしまうようですし。。。)
全角文字"自体"をKeyPressで捉えることはムリですからね。
自分も↓で発言しておきながら忘れていたのですが...(^^;

http://dobon.net/cgi-bin/vbbbs/srch.cgi?no=0&word=5210&andor=and&logs=1.txt&PAGE=20&ALL=1

> 初心者の自分でも役に立てるかもと深く考えずに回答したのですが
> 勇み足だったみたいです。
いえ、でしゃばったマネをして申し訳ありません。
私なんて、フツーに間違ってることをカキコすることが多いです...(^^;



■No6058に返信(チャコさんの記事)
> はじめて投稿いたします。
はじめまして。java.lang.Nullpoと申します。

> VB.NET2003と.NET CompactFrameworkを使用して、PDA端末
> ようの数値入力専用テキストボックスを自作しようとしています。
> クラスは、System.Windows.Forms.TextBoxから派生させています。
> キー入力があった際、文字コードをチェックして数値以外であれば
> 入力されないようにしたいのです。

CompactFrameworkでも、その辺りの"制限"はないはずですので、

> そこで、OnKeyDownを使って、数字以外であれば、KeyEventArgs
> のHandledをTrueに設定して、KeyDownイベントが発生しないように
> しようとしましたが、うまくいきません。
> 数字かどうかのチェックはできていますが、数字以外の文字でもテキスト
> ボックスには表示されてしまいます。

そんさんの補足になりますが、KeyPress()イベントと、TextChanged()イベントで
同様の文字を弾く実装が(ロジックは当然違います)必要になります。

どちらのイベントも、許可する文字は同じですので(って当たり前か...)
私の場合は、カスタムコントロールのプロパティで許可文字を設定できるようにしています。
その許可文字を参照すれば "数字" に関わらず、好きな文字を、
KeyPress()イベント及び、TextChanged()イベントで回避することができます。

> クラスは、System.Windows.Forms.TextBoxから派生させています。

から察するに、チャコさんはカスタムコントロールを作っているようですので、
数字に関わらず設定できる、プロパティを作成すると理想なのではないでしょうか?

「いや、そんな必要はない!」ってことでしたら、
KeyPress()イベントはそんさんのを参考に、TextChanged()イベントは、

  While (iPlace <> nText.Length)
    If nPerm.IndexOf(nText.Chars(iPlace)) < 0 Then
      nText = nText.Substring(0, iPlace) & nText.Substring(iPlace + 1)
    Else
      iPlace += 1
    End If
  End While

のような感じにして弾けば(削れば)いいと思います。
そんさん、 java.lang.Nullpoさん、ありがとうございます。
早速教えていただいたようにやってみたいと思います。
さっそくやってみたのですが、問題が出ました。
textChangedイベントへ実装し、英数字を含む文字をCTRL+Vでペースト
した際、テキストボックス内に一瞬だけ文字が表示され、
その後消えます。また、カーソル位置も左端に戻ってしまいます。

ペーストした際も、テキストボックス内へ文字を表示する前に
文字をはじく方法はありませんか?
ちなみに、TextChangedのコードは以下のようにしました。

Protected Overrides Sub OnTextChanged(ByVal e As System.EventArgs)
Dim szBase, szTar As String

szBase = Me.Text
szTar = GetDeleteString(szBase)
If szBase.Equals(szTar) = False Then
Me.Text = szTar
End If
End Sub

なお、GetDeleteStringは、java.lang.Nullpoさんに教えていただいた
http://dobon.net/cgi-bin/vbbbs/srch.cgi?no=0&word=5210&andor=and&logs=1.txt&PAGE=20&ALL=1

に記載されていたコードを簡単化のために数値専用に特化しました。
よろしくお願いします。
おはようございます、チャコさん。

■No6121に返信(チャコさんの記事)
> さっそくやってみたのですが、問題が出ました。
> textChangedイベントへ実装し、英数字を含む文字をCTRL+Vでペースト
> した際、テキストボックス内に一瞬だけ文字が表示され、
> その後消えます。また、カーソル位置も左端に戻ってしまいます。
>
> ペーストした際も、テキストボックス内へ文字を表示する前に
> 文字をはじく方法はありませんか?
> ちなみに、TextChangedのコードは以下のようにしました。
>
> なお、GetDeleteStringは、java.lang.Nullpoさんに教えていただいた
> に記載されていたコードを簡単化のために数値専用に特化しました。
> よろしくお願いします。

まあ、最低限の実装しか載せてませんから、そこから先は工夫になってしまいますね。
私が解決した方法を詳細に書いてみますね。


> ペーストした際も、テキストボックス内へ文字を表示する前に
> 文字をはじく方法はありませんか?

[Ctrl]+[V]の貼り付けを、TextChanged()イベントより前の段階
つまり、KeyDownとかProcessDialogKey()などで読み取っておき、
クリップボードから、貼り付けられる部分を持ってくる(または削除する手もある)
また、[Ctrl]+[V]やコンテキストメニューからの[貼り付け]を認識したら、
描画を無効にしておいて、その間に不許可文字を削る手もあるでしょう。

しかし、
> テキストボックス内へ文字を表示する前に文字をはじく方法
となると前者になるでしょうか(どちらも軽くするために、色々工夫は要りますが...)


> また、カーソル位置も左端に戻ってしまいます。

次に、カーソル位置ですが、これもTextChanged()より前の段階で、
カーソル位置(SelectionStart)を記憶しておき、
で、追加または削除される前と後での文字数とを比較すれば、
そんなに難しくなく、自然の位置に復元できます。

DOBON.NET | プログラミング道 | プログラミング掲示板