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

TextBoxの入力文字制限について質問です。

環境/言語:[OS : Windows XP Professional / 言語 : Visual Basic .NET / .NET Framework : 1.1]
分類:[.NET]

【解決したい問題】

TextBoxの入力文字制限について質問です。
入力モードがONでTextBox_KeyPressにてKeyPressEventArgs=trueを設定しても処理がキャンセルされません。
他に設定が必要ですか?

【解決するために何をしたか】

■Moduleクラスにて...
Public Function Entry(ByRef KeyAscii As Integer) As Integer
'バックスペース,数字設定のみを入力許可する
Select Case KeyAscii
Case 8, 48 To 57
Entry = KeyAscii
Case Else
Entry = 0
End Select
End Function

■Formクラスにて...
Private Sub TextBox_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles TextBox.KeyPress
Dim KeyAscii As Integer = Asc(e.KeyChar)

KeyAscii = Entry(KeyAscii)

If KeyAscii = 0 Then
e.Handled = True
End If
End Sub

■上記PGを実行してみると...
Entryからは0が戻ってきており、e.Handled = Trueが設定するルートを通る事は確認できるのですが、実際にはTextBoxにはデータが残ってしまいます。
例)TextBoxにて「あ」を入力→TextBoxに「あ」が表示される
2005/03/15(Tue) 16:58:17 編集(投稿者)

こんにちは、じゃんぬねっと です。

■No9814に返信(松尾さんの記事)
> Entryからは0が戻ってきており、e.Handled = Trueが設定するルートを通る事は確認できるのですが、
> 実際にはTextBoxにはデータが残ってしまいます。
> 例)TextBoxにて「あ」を入力→TextBoxに「あ」が表示される

例を見る限りだと、IME などからの入力のようですね。
その場合は、e.Handle = true; としても WM_CHAR は飛んじゃっています。
入力を防ぐには、TextChanged イベントで非許可文字を削除するか (描画の工夫は必要)
WndProc で WM_CHAR を監視して wParam から非許可文字かどうか判断して、排除してあげてください。
早いレスありがとうございます。松尾です。

■No9815に返信(じゃんぬねっとさんの記事)
> 2005/03/15(Tue) 16:58:17 編集(投稿者)
>
> こんにちは、じゃんぬねっと です。
>
> ■No9814に返信(松尾さんの記事)
>>Entryからは0が戻ってきており、e.Handled = Trueが設定するルートを通る事は確認できるのですが、
>>実際にはTextBoxにはデータが残ってしまいます。
>>例)TextBoxにて「あ」を入力→TextBoxに「あ」が表示される
>
> 例を見る限りだと、IME などからの入力のようですね。
> その場合は、e.Handle = true; としても WM_CHAR は飛んじゃっています。
> 入力を防ぐには、TextChanged イベントで非許可文字を削除するか (描画の工夫は必要)
> WndProc で WM_CHAR を監視して wParam から非許可文字かどうか判断して、排除してあげてください。

<<1.TextChanged イベント使用>>
■Formクラスにて...
Private wkChar As String = ""

Private Sub TextBox_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles TextBox.KeyPress
Dim KeyAscii As Integer = Asc(e.KeyChar)

KeyAscii = Entry(KeyAscii)

If KeyAscii = 0 Then
e.Handled = True
'/// ココで入力モードを取得したい /// <--【※1】
wkChar = wkChar + e.KeyChar
Else
wkChar = ""
End If
End Sub

Private Sub TextBox_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles TextBox.TextChanged
Dim compTextBox As String = ""

If wkChar <> "" Then
If TextBox.Text.Length < 1 Then
compTextBox = TextBox.Text
Else
compTextBox = TextBox.Text.Substring(TextBox.Text.Length - 1, 1)
End If
If compTextBox = wkChar.Substring(0, 1) Then
If wkChar.Length = 1 Then
wkChar = ""
Else
wkChar = wkChar.Substring(1)
End If
If TextBox.Text.Length = 1 Then
TextBox.Text = ""
Else
TextBox.Text = TextBox.Text.Substring(0, TextBox.Text.Length - 1)
End If
TextBox.SelectionStart = TextBox.Text.Length
End If
End If
End Sub

Private Sub TextBox_Enter(ByVal sender As Object, ByVal e As System.EventArgs) Handles TextBox.Enter
wkChar = ""
End Sub

Private Sub TextBox_Leave(ByVal sender As Object, ByVal e As System.EventArgs) Handles TextBox.Leave
wkChar = ""
End Sub

■上記PGにて対応しようとした場合、【※1】の部分にて入力モードが取得できず(wkCharにデータが残る為)、入力モードがOFFの状態で対象外文字を入力後、入力モードをONにして対象外文字を入力すると制御不能になります。
例)「あいう」入力→「あいう」非表示:OK→「abc」入力→「abc」非表示:OK→「あいう」入力→「あいう」表示:NG


<<2.WndProc使用>>
■Formクラスにて...
Protected Overrides Sub WndProc(ByRef m As Message)
Const WM_CHAR As Integer = &H102
Const WM_CLOSE As Integer = &H10

If m.Msg = WM_CLOSE Then
Debug.WriteLine("*** close ***" + Str(m.Msg))
' 閉じる処理をキャンセル
'm.Result = IntPtr.Zero
ElseIf m.Msg = WM_CHAR Then
Debug.WriteLine("*** ime ***" + Str(m.Msg))
wkChar = "test"
End If
MyBase.WndProc(m)
End Sub

■上記PGにては、デバックウィンドウにて動作を確認してみました。Formを閉じたタイミングでWM_CLOSE の場合は出力されるのですが、入力モードを変更(Alt+半角)してもWM_CHARの場合は出力されません。


という結果で、せっかく解決法を教えて頂いたのにうまく活用できません。
少し詳しく教えて頂けないでしょうか?
よろしくお願いします。
<<1.>>入力モードの取得方法がわかりません。
<<2.>>なぜ出力されないのかがわかりません。
こんにちは、じゃんぬ です。

■No9822に返信(松尾さんの記事)
> <<1.>>入力モードの取得方法がわかりません。

TextBox には ImeMode なるプロパティがありますね。
ただ、入力モードの取得が何故必要なのか、私にはわかりませんでした。

> <<2.>>なぜ出力されないのかがわかりません。

Form で WndProc をオーバーライドしてもダメでしょう。
TextBox の WndProc をオーバーライドしないと。

最小限の説明しかしていなくて、申し訳ありませんでした。
おはようございます、松尾です。

■No9826に返信(じゃんぬねっとさんの記事)
> こんにちは、じゃんぬ です。
>
> ■No9822に返信(松尾さんの記事)
>><<1.>>入力モードの取得方法がわかりません。
>
> TextBox には ImeMode なるプロパティがありますね。
> ただ、入力モードの取得が何故必要なのか、私にはわかりませんでした。

すみません、プロパティの設定ミスでした。(TextBox.ImeMode=NoControl)
If TextBox.ImeMode <> ImeMode.Off Then
wkChar = wkChar + e.KeyChar
Else
wkChar = ""
End If
入力モードの取得が何故必要なのかというのは、入力モードがONの場合はKeyPressEventArgs.Handled = Trueにてのキャンセルが無効で、OFFの場合は有効なので、wkCharに不要なデータが残る事を回避する為でした。


>><<2.>>なぜ出力されないのかがわかりません。
>
> Form で WndProc をオーバーライドしてもダメでしょう。
> TextBox の WndProc をオーバーライドしないと。

WndProcを使ったことがないもので、こちらは再勉強してから試してみる事みします。


> 最小限の説明しかしていなくて、申し訳ありませんでした。

とんでもございません。
こちらこそ、質問の仕方等がおぼつかなくてすみません。
VB.NETをはじめたばかりなもので、模索しながら勉強中です。
ちなみに、掲示板も初心者です。
本当に勉強になりました。
ご教授ありがとうございました。
解決済み!

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