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

テキストボックスをエンターで移動

環境/言語:[Windows2000、XP]
分類:[.NET]

kageです。お世話になります。

フォーム上に配置したテキストボックスに次々と入力していく際、Enterキーで移動するとスムーズな操作ができます。
vb6では以下のようにしていましたが、.netの場合うまくいきません。

'Enterを押して次のテキストボックスに進む
Public Declare Function PostMessage Lib "user32" _
Alias "PostMessageA" _
(ByVal hWnd As Long, _
ByVal wMsg As Long, _
ByVal wParam As Long, _
ByVal lParam As Long) As Long

Public Const WM_KEYDOWN = &H100
Public Const WM_KEYUP = &H101
Public Const VK_TAB = &H9

Private Sub TextBox1_KeyPress(KeyAscii As Integer)
If KeyAscii = vbKeyReturn Then
PostMessage Me.hWnd, WM_KEYDOWN, VK_TAB, 1
PostMessage Me.hWnd, WM_KEYUP, VK_TAB, 1
KeyAscii = 0
End If
End Sub

よろしくお願いします。
PostMessageでのやり方がちょっと自分でも分からなかったので
普段、自分がやっているような方法で実行できるかなと思います。
もっといい方法があるとは思いますけど。
とりあえず、TextBoxの配列を作って、添え字を1づつずらしながらFocusを
あてていく方法です。

Dim arrTxtBox() As TextBox = Nothing
Dim i As Integer = 0

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    'コントロール配列にしちゃう
    Dim arrTxtBoxTmp() As TextBox = {TextBox1, TextBox2, TextBox3}
    arrTxtBox = arrTxtBoxTmp
End Sub

Private Sub TextBox_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles TextBox1.KeyDown, TextBox2.KeyDown, TextBox3.KeyDown
    If e.KeyValue = Keys.Enter Then
        i = i + 1
        i = i Mod 3
        arrTxtBox(i).Focus()
    End If
End Sub
■No5872に返信(kageさんの記事)
> kageです。お世話になります。
>
> フォーム上に配置したテキストボックスに次々と入力していく際、Enterキーで移動するとスムーズな操作ができます。
> vb6では以下のようにしていましたが、.netの場合うまくいきません。
>
> 'Enterを押して次のテキストボックスに進む
> Public Declare Function PostMessage Lib "user32" _
> Alias "PostMessageA" _
> (ByVal hWnd As Long, _
> ByVal wMsg As Long, _
> ByVal wParam As Long, _
> ByVal lParam As Long) As Long
>
> Public Const WM_KEYDOWN = &H100
> Public Const WM_KEYUP = &H101
> Public Const VK_TAB = &H9
>
> Private Sub TextBox1_KeyPress(KeyAscii As Integer)
> If KeyAscii = vbKeyReturn Then
> PostMessage Me.hWnd, WM_KEYDOWN, VK_TAB, 1
> PostMessage Me.hWnd, WM_KEYUP, VK_TAB, 1
> KeyAscii = 0
> End If
> End Sub
>
> よろしくお願いします。

無理にPostMessage()でやる必要もないかと思います。
(ところで、APIでやるにしても、SendInput()やkeyboard_event()でやるべきじゃ...?)

.NETプログラミングでは、WindowsAPIやその言語固有の関数を使うのではなく、
.NET Frameworkなどをなるべく利用するように心がけましょう。
(言語鈍りのないコーディングを心がける)

配列化してFocus()メソッドをチマチマ書くのも何かと面倒ですし、
コントロール数が変わると、ソースを変更しなくてはなりません。
できれば、Formに属するコントロールに変更があっても関係なく動くようにするのが理想です。

となると、

 ・FormのKeyPreviewをTrueにして、FormのKeyDown()イベントでSelectNextControl()を実装する。
 ・ProcessDialogKey()をオーバーライドして、EnterをTabに置き換える。

どちらかを選択すれば良いかと思います。

ただ、ひとつ注意することと言えば、Windowsでの[Enter]キーは、フォーカス遷移ではありません。
Windowsのおけるフォーカス遷移は[Tab]キーであるため、色々面倒なことも出てきます。

例えば、MultiLineなTextBoxなどでは、[Ctrl]+[Enter]で改行を表現することになります。

# オフコンユーザは[Enter]キーでフォーカス遷移したい人が多いので、
# [Enter]でFocus遷移っていうのは、未だに大変多いみたいです...
テラオメガさん、はじめまして。

サンプルコードを試させていただきました。
私のやりたかった通りに動きました。

> PostMessageでのやり方がちょっと自分でも分からなかったので
> 普段、自分がやっているような方法で実行できるかなと思います。
> もっといい方法があるとは思いますけど。

PostMessageはVB6の時に使っていた方法で、.netではまったくこだわっていません。
.netはVB6でAPIを使って実現していたことが、大部分APIなしで実現できるようなのでこれもできるのでは、と考えた次第です。

> とりあえず、TextBoxの配列を作って、添え字を1づつずらしながらFocusを
> あてていく方法です。
>
> Dim arrTxtBox() As TextBox = Nothing
> Dim i As Integer = 0
>
> Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
> 'コントロール配列にしちゃう
> Dim arrTxtBoxTmp() As TextBox = {TextBox1, TextBox2, TextBox3}
> arrTxtBox = arrTxtBoxTmp
> End Sub
>
> Private Sub TextBox_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles TextBox1.KeyDown, TextBox2.KeyDown, TextBox3.KeyDown
> If e.KeyValue = Keys.Enter Then
> i = i + 1
> i = i Mod 3
> arrTxtBox(i).Focus()
> End If
> End Sub

配列の勉強にもなりました。ありがとうございました。
java.lang.Nullpoさん、はじめまして。

> 無理にPostMessage()でやる必要もないかと思います。
> (ところで、APIでやるにしても、SendInput()やkeyboard_event()でやるべきじゃ...?)

入力がvbCrLfだったら、次のコントロールへSetForcusをしていましたが、PostMessageのやり方を教わり、使っていました。

> .NETプログラミングでは、WindowsAPIやその言語固有の関数を使うのではなく、
> .NET Frameworkなどをなるべく利用するように心がけましょう。
> (言語鈍りのないコーディングを心がける)

そのようにしたいと思っております。

> 配列化してFocus()メソッドをチマチマ書くのも何かと面倒ですし、
> コントロール数が変わると、ソースを変更しなくてはなりません。
> できれば、Formに属するコントロールに変更があっても関係なく動くようにするのが理想です。

まさに、その問題が残りますね。

> となると、
>
>  ・FormのKeyPreviewをTrueにして、FormのKeyDown()イベントでSelectNextControl()を実装する。
>  ・ProcessDialogKey()をオーバーライドして、EnterをTabに置き換える。
>
> どちらかを選択すれば良いかと思います。

上のほうがよろしいと思うのですが、SelectNextControlのオプションが良く分かりません。
Private Sub Form1_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles MyBase.KeyDown
Me.KeyPreview = True
Me.SelectNextControl(TextBox1, True, True, False, True)

End Sub
と書いてみましたが、動きません。

> # オフコンユーザは[Enter]キーでフォーカス遷移したい人が多いので、
> # [Enter]でFocus遷移っていうのは、未だに大変多いみたいです...

私はオフコンユーザーではありませんが、Tabキーにはどうしてもなじめません。
プログラムをする時、全くのど素人でも迷わず使えるようにするにはEnterの方が分かりやすいと思います。
もっとも、ど素人さんはすぐにマウスを使いますから、あまり関係ないのかもしれませんが。
kage
2004/09/16(Thu) 15:27:59 編集(投稿者)

■No5901に返信(kageさんの記事)
>>となると、
>>
>> ・FormのKeyPreviewをTrueにして、FormのKeyDown()イベントでSelectNextControl()を実装する。
>> ・ProcessDialogKey()をオーバーライドして、EnterをTabに置き換える。
>>
>>どちらかを選択すれば良いかと思います。
>
> 上のほうがよろしいと思うのですが、SelectNextControlのオプションが良く分かりません。
> Private Sub Form1_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles MyBase.KeyDown
> Me.KeyPreview = True
> Me.SelectNextControl(TextBox1, True, True, False, True)
>
> End Sub
> と書いてみましたが、動きません。

まず、KeyPreviewプロパティは毎回やる必要はないので、Form::Load()イベント内でやります。

  Private Sub FormMain_Load(ByVal sender As System.Object, ByVal e As EventArgs) Handles MyBase.Load
    Me.KeyPreview = True
  End Sub

問題のKeyDown()イベント内ですが、以下のようになります。

  Private Sub FormMain_KeyDown(ByVal sender As Object, ByVal e As KeyEventArgs) Handles MyBase.KeyDown
    If e.KeyCode = Keys.Enter Then
      Me.SelectNextControl(Me.ActiveControl, Not e.Shift, True, True, True)
    End If
  End Sub


■追記

 過去ログを検索してみると、まあたくさん同様な質問があることがわかりました。
 ただ、どれもすべてのコントロールについて解決できておりません。
 SendKeyなどを使う手法など、様々あるのですが言語鈍りのないコーディングのためにも
 ProcessDialogKey()をオーバライドする手法も載せておきます。

  Protected Overrides Function ProcessDialogKey(ByVal iKeyData As Keys) As Boolean
    Select Case iKeyData
      Case Keys.Enter
        iKeyData = Keys.Tab

      Case Keys.Enter Or Keys.Shift
        iKeyData = Keys.Tab Or Keys.Shift
    End Select

    Return MyBase.ProcessDialogKey(iKeyData)
  End Function

ちなみにこのコードを実装しますと、Buttonコントロールでも[Enter]でフォーカス遷移することができます。(Click()イベントは起きません)
Buttonは[Space]キーを押下することで、Click()イベントを起こせますので、
オフコンユーザには持って来いの仕様になるのではないでしょうか。
かくゆう私も現在開発中の物の親クラスに実装させて継承しております。

もし、Buttonコントロールで回避したい場合は、TypeOf ActiveControl Is Buttonで回避できます。
■No5902に返信(java.lang.Nullpoさんの記事)
> 2004/08/30(Mon) 16:32:58 編集(投稿者)
>
> ■No5901に返信(kageさんの記事)
> >>となると、
> >>
> >> ・FormのKeyPreviewをTrueにして、FormのKeyDown()イベントでSelectNextControl()を実装する。
> >> ・ProcessDialogKey()をオーバーライドして、EnterをTabに置き換える。
> >>
> >>どちらかを選択すれば良いかと思います。
>>
>>上のほうがよろしいと思うのですが、SelectNextControlのオプションが良く分かりません。
>> Private Sub Form1_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles MyBase.KeyDown
>> Me.KeyPreview = True
>> Me.SelectNextControl(TextBox1, True, True, False, True)
>>
>> End Sub
>>と書いてみましたが、動きません。
>
> まず、KeyPreviewプロパティは毎回やる必要はないので、Form::Load()イベント内でやります。
>
>   Private Sub FormMain_Load(ByVal sender As System.Object, ByVal e As EventArgs) Handles MyBase.Load
>     Me.KeyPreview = True
>   End Sub
>
> 問題のKeyDown()イベント内ですが、以下のようになります。
>
>   Private Sub FormMain_KeyDown(ByVal sender As Object, ByVal e As KeyEventArgs) Handles MyBase.KeyDown
>     If e.KeyCode = Keys.Enter Then
>       Me.SelectNextControl(Me.ActiveControl, Not e.Shift, True, True, True)
>     End If
>   End Sub
>
>
> ■追記
>
>  過去ログを検索してみると、まあたくさん同様な質問があることがわかりました。
>  ただ、どれもすべてのコントロールについて解決できておりません。
>  SendKeyなどを使う手法など、様々あるのですが言語鈍りのないコーディングのためにも
>  ProcessDialogKey()をオーバライドする手法も載せておきます。
>
>   Protected Overrides Function ProcessDialogKey(ByVal iKeyData As Keys) As Boolean
>     Select Case iKeyData
>       Case Keys.Enter
>         iKeyData = Keys.Tab
>
>       Case Keys.Enter Or Keys.Shift
>         iKeyData = Keys.Tab Or Keys.Shift
>     End Select
>
>     MyBase.ProcessDialogKey(iKeyData)
>   End Function
>
> ちなみにこのコードを実装しますと、Buttonコントロールでも[Enter]でフォーカス遷移することができます。(Click()イベントは起きません)
> Buttonは[Space]キーを押下することで、Click()イベントを起こせますので、
> オフコンユーザには持って来いの仕様になるのではないでしょうか。
> かくゆう私も現在開発中の物の親クラスに実装させて継承しております。
>
> もし、Buttonコントロールで回避したい場合は、TypeOf ActiveControl Is Buttonで回避できます。

ついでの説明ですが、Groupコントロール(panelやGroupBoxなど)も回避の対象にした方がいいでしょうね。
■No5907に返信(ぺがらぼさんの記事)
> ついでの説明ですが、Groupコントロール(panelやGroupBoxなど)も回避の対象にした方がいいでしょうね。

ん? Form::SelectNextControl() メソッドは、
Focus遷移可能なコントロールしか移動しないはずですが?
ProcessDialogKey() でKeyDataを置き換える方法も同様です。

Panelコントロール、GroupBoxコントロールは遷移対象にはなりません。
TabStopプロパティがないのですから当然です。

# GetNextControl() メソッドならそうなりますが。
■No5872に返信(kageさんの記事)

 kageさん、こんばんは。深山と申します。
 もう全然必要ないかとは思いますが、どなたも触れられないようなので一応。

> vb6では以下のようにしていましたが、.netの場合うまくいきません。
> Public Declare Function PostMessage Lib "user32" _
> Alias "PostMessageA" _
> (ByVal hWnd As Long, _
> ByVal wMsg As Long, _
> ByVal wParam As Long, _
> ByVal lParam As Long) As Long

 これは VB6 と VB.NET で型のサイズが変更されたことに起因します。
 前者で Long は 32 ビット符号付き整数でしたが、後者では64 ビット符号付き整数と
なっています。その為、 VB6 のときと同じコードでは動作しません。適切な型に変更する
必要があります。
 VB.NET での 32 ビット符号付き整数は Integer なので、そのように宣言を変更すれば
以前と同様の動作をするようになるのではないかと。

# 因みに、アップグレードウィザードでは微妙に対応してくれるようです。
http://www.microsoft.com/japan/msdn/net/vbtransitionguide/chapter4/chapter4_14.asp

 尤も、 Handle 等は IntPtr 型の使用が推奨されてますけども。
http://www.microsoft.com/japan/msdn/library/default.asp?url=/japan/msdn/library/ja/cpguide/html/cpconplatforminvokedatatypes.asp
たしかに、配列だとボタンが増えたときに、コードの訂正があるのが痛いところですね。


ProcessDialogKey()をオーバライドして、やる方法があるとは、わたしも知りませんでした。

ぺがらぼさんやjava.lang.Nullpoさんの意見を参考に1つ考えたことがあります。
ボタンなどをTypeOf ActiveControl Is Buttonで回避する方法を
TextBoxクラスを継承させて、自作TextBoxクラスを作成して
そこにProcessDialogKey()をオーバライドしてあげると、
その自作TextBoxだけEnter動作になる仕様になるんじゃないかなと思います。
java.lang.Nullpoさん、こんばんは。
台風16号に備えていたら、返事が遅くなりました。

> まず、KeyPreviewプロパティは毎回やる必要はないので、Form::Load()イベント内でやります。
>
>   Private Sub FormMain_Load(ByVal sender As System.Object, ByVal e As EventArgs) Handles MyBase.Load
>     Me.KeyPreview = True
>   End Sub
>
> 問題のKeyDown()イベント内ですが、以下のようになります。
>
>   Private Sub FormMain_KeyDown(ByVal sender As Object, ByVal e As KeyEventArgs) Handles MyBase.KeyDown
>     If e.KeyCode = Keys.Enter Then
>       Me.SelectNextControl(Me.ActiveControl, Not e.Shift, True, True, True)
>     End If
>   End Sub

この方法で完璧ですね。
パラメータのつけ方がいまいち理解できていませんが、このまま使わせていただきます。

> ■追記
>
>  過去ログを検索してみると、まあたくさん同様な質問があることがわかりました。
>  ただ、どれもすべてのコントロールについて解決できておりません。
>  SendKeyなどを使う手法など、様々あるのですが言語鈍りのないコーディングのためにも
>  ProcessDialogKey()をオーバライドする手法も載せておきます。
>
>   Protected Overrides Function ProcessDialogKey(ByVal iKeyData As Keys) As Boolean
>     Select Case iKeyData
>       Case Keys.Enter
>         iKeyData = Keys.Tab
>
>       Case Keys.Enter Or Keys.Shift
>         iKeyData = Keys.Tab Or Keys.Shift
>     End Select
>
>     MyBase.ProcessDialogKey(iKeyData)
>   End Function
>
> ちなみにこのコードを実装しますと、Buttonコントロールでも[Enter]でフォーカス遷移することができます。(Click()イベントは起きません)
> Buttonは[Space]キーを押下することで、Click()イベントを起こせますので、
> オフコンユーザには持って来いの仕様になるのではないでしょうか。
> かくゆう私も現在開発中の物の親クラスに実装させて継承しております。

こちらも動作確認しました。
でも、ボタンコントロールに関してはEnterを認識させたいもので・・

> もし、Buttonコントロールで回避したい場合は、TypeOf ActiveControl Is Buttonで回避できます。

このコードの実装方法がわかりません。
もう少しお付き合いください。よろしく  kage
深山さん、こんばんは。

>  kageさん、こんばんは。深山と申します。
>  もう全然必要ないかとは思いますが、どなたも触れられないようなので一応。

とんでもございません。大歓迎です。

>>vb6では以下のようにしていましたが、.netの場合うまくいきません。
>>Public Declare Function PostMessage Lib "user32" _
>> Alias "PostMessageA" _
>> (ByVal hWnd As Long, _
>> ByVal wMsg As Long, _
>> ByVal wParam As Long, _
>> ByVal lParam As Long) As Long
>
>  これは VB6 と VB.NET で型のサイズが変更されたことに起因します。
>  前者で Long は 32 ビット符号付き整数でしたが、後者では64 ビット符号付き整数と
> なっています。その為、 VB6 のときと同じコードでは動作しません。適切な型に変更する
> 必要があります。
>  VB.NET での 32 ビット符号付き整数は Integer なので、そのように宣言を変更すれば
> 以前と同様の動作をするようになるのではないかと。
>
> # 因みに、アップグレードウィザードでは微妙に対応してくれるようです。

.netのコードにこだわっていましたので、アップグレードを忘れていました。
サンプルを作ってアップグレードしましたところ、簡単に動きました。
以下がアップグレードされたコードです。
Module Module1
'Enterを押して次のテキストボックスに進む
Public Declare Function PostMessage Lib "user32" Alias "PostMessageA"(ByVal hWnd As Integer, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer

Public Const WM_KEYDOWN As Short = &H100s
Public Const WM_KEYUP As Short = &H101s
Public Const VK_TAB As Short = &H9s
End Module

Private Sub Form1_KeyPress(ByVal eventSender As System.Object, ByVal eventArgs As System.Windows.Forms.KeyPressEventArgs) Handles MyBase.KeyPress
Dim KeyAscii As Short = Asc(eventArgs.KeyChar)
If KeyAscii = System.Windows.Forms.Keys.Return Then
PostMessage(Me.Handle.ToInt32, WM_KEYDOWN, VK_TAB, 1)
PostMessage(Me.Handle.ToInt32, WM_KEYUP, VK_TAB, 1)
KeyAscii = 0
End If

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

実は、VB6ではコントロール毎にKey_Pressを書いていました。
FormのKeyPreviewをTrueにして、Form_KeyPressで1個だけ書けばよかったんですね。勉強になりました。
kage
■No5909に返信(java.lang.Nullpoさんの記事)
> ■No5907に返信(ぺがらぼさんの記事)
>>ついでの説明ですが、Groupコントロール(panelやGroupBoxなど)も回避の対象にした方がいいでしょうね。
>
> ん? Form::SelectNextControl() メソッドは、
> Focus遷移可能なコントロールしか移動しないはずですが?
> ProcessDialogKey() でKeyDataを置き換える方法も同様です。
>
> Panelコントロール、GroupBoxコントロールは遷移対象にはなりません。
> TabStopプロパティがないのですから当然です。
>
> # GetNextControl() メソッドならそうなりますが。

ごめん、勘違いしてた。(~_~;)
焦っている時に、掲示板を見ては駄目ですね・・・
ほんとにすいませんでした。
解決済み!
2004/09/16(Thu) 09:58:26 編集(投稿者)

■No5913に返信(テラオメガさんの記事)
> たしかに、配列だとボタンが増えたときに、コードの訂正があるのが痛いところですね。
> ProcessDialogKey()をオーバライドして、やる方法があるとは、わたしも知りませんでした。
> ぺがらぼさんやjava.lang.Nullpoさんの意見を参考に1つ考えたことがあります。
> ボタンなどをTypeOf ActiveControl Is Buttonで回避する方法を
> TextBoxクラスを継承させて、自作TextBoxクラスを作成して
> そこにProcessDialogKey()をオーバライドしてあげると、
> その自作TextBoxだけEnter動作になる仕様になるんじゃないかなと思います。

ただ、私の場合はすべて[Enter]キーで動く仕様なので、
BaseFormに実装して、BaseFormを継承するようにしております。
また、Buttonでの[Enter]は、KeyDownイベントを使う方を選択すれば回避できます。
Type Of Buttonは、ProcessDialogKey()をオーバライドする場合のお話です。
また、1イベントはできる限り、機能別のブロック(メソッド)にしておき、
機能を提供するメソッドは、Overridableとしております。
グループ開発では、窮屈になることを嫌う人もおりますし、
これらはコードの可読性にも寄与します。

もちろん、TextBoxだけに適用する際は、WithEventsによるデコレータクラスを作るなり、
テラオメガさんの言うとおりTextBoxに実装するべきですね。


■No5919に返信(ぺがらぼさんの記事)
> ごめん、勘違いしてた。(~_~;)
> 焦っている時に、掲示板を見ては駄目ですね・・・
> ほんとにすいませんでした。

気にしないでください。
私とぺがらぼさんは同志ではなかったのですか?


■No5914に返信(kageさんの記事)

はい、Win32API(PostMessage)の方は完全に無視していましたが...(おいおい)
深山さまが答えてくださったように、宣言時に型が違うと動いてくれません。
まあ、いずれにせよAPIはなるべく使わない方が良いでしょう。

> こちらも動作確認しました。
> でも、ボタンコントロールに関してはEnterを認識させたいもので・・

>>もし、Buttonコントロールで回避したい場合は、TypeOf ActiveControl Is Buttonで回避できます。

> このコードの実装方法がわかりません。
> もう少しお付き合いください。よろしく。

はい、もし回避したい場合は、Form::KeyDown()イベントで実装する方を選択してください。
ただし、Form::KeyDown()イベントは、ドロップダウンリストではないComboBoxは反応しません。
ですので、(ドロップダウンリストでない)ComboBoxは、
ComboBox毎かComboBoxをデコレータクラス化などして統一しなくてはなりません。
ProcessDialogKey()でキーを置き換えるメリットはすべてのコントロール上で動くことです。
(※ ただし、ProcessDialogKey()はComboBoxでは2重にキーが入るので注意が要ります)

で、肝心のButtonコントロールを回避する方法ですが、以下のようになります。

  Protected Overrides Function ProcessDialogKey(ByVal iKeyData As Keys) As Boolean
    If TypeOf Me.ActiveControl Is Button = False Then
      Select Case iKeyData
        Case Keys.Enter
          iKeyData = Keys.Tab

        Case Keys.Enter Or Keys.Shift
          iKeyData = Keys.Tab Or Keys.Shift
      End Select
    End If

    ' /* MyBase.ProcessDialogKey(iKeyData) */ <- 誤り
    Return MyBase.ProcessDialogKey(iKeyData)
  End Function
java.lang.Nullpoさん、おはようございます。

> はい、もし回避したい場合は、Form::KeyDown()イベントで実装する方を選択してください。
> ただし、Form::KeyDown()イベントは、ドロップダウンリストではないComboBoxは反応しません。
> ですので、(ドロップダウンリストでない)ComboBoxは、
> ComboBox毎かComboBoxをデコレータクラス化などして統一しなくてはなりません。
> ProcessDialogKey()でキーを置き換えるメリットはすべてのコントロール上で動くことです。
> (※ ただし、ProcessDialogKey()はComboBoxでは2重にキーが入るので注意が要ります)
>
> で、肝心のButtonコントロールを回避する方法ですが、以下のようになります。
>
>   Protected Overrides Function ProcessDialogKey(ByVal iKeyData As Keys) As Boolean
>     If TypeOf Me.ActiveControl Is Button = False Then
>       Select Case iKeyData
>         Case Keys.Enter
>           iKeyData = Keys.Tab
>
>         Case Keys.Enter Or Keys.Shift
>           iKeyData = Keys.Tab Or Keys.Shift
>       End Select
>     End If
>
>     MyBase.ProcessDialogKey(iKeyData)
>   End Function

確かに、動作いたしました。
VB6では何かとAPIを使っていましたが、APIを使わないよう努力します。
ありがとうございました。 kage
解決済み!
■No5921に返信(java.lang.Nullpoさんの記事)
> で、肝心のButtonコントロールを回避する方法ですが、以下のようになります。
>
>   Protected Overrides Function ProcessDialogKey(ByVal iKeyData As Keys) As Boolean
>     If TypeOf Me.ActiveControl Is Button = False Then
>       Select Case iKeyData
>         Case Keys.Enter
>           iKeyData = Keys.Tab
>
>         Case Keys.Enter Or Keys.Shift
>           iKeyData = Keys.Tab Or Keys.Shift
>       End Select
>     End If
>
>     MyBase.ProcessDialogKey(iKeyData)
>   End Function

関数の最後の部分 ...

Return MyBase.ProcessDialogKey(iKeyData)

として、ちゃんと戻り値を返すようにしてください。

そうしないと、置換されたTABまたはShift+TABキーを含め、フォーム側で処理されたキーもすべて
子コントロールに渡されてしまいます。

TextBoxは、入力を受け付けないキーに対して、警告音(Windows XPの標準設定では『ポン!』という音)
が鳴るので、戻り値を返さない(常にFalse)と、TextBoxから前後のコントロールにフォーカス移動する際に
警告音が鳴ってしまいます。
2004/09/16(Thu) 09:57:25 編集(投稿者)

■No6206に返信(なんど蟲さんの記事)

> 関数の最後の部分 ...
>
> Return MyBase.ProcessDialogKey(iKeyData)
>
> として、ちゃんと戻り値を返すようにしてください。

ただのカキコミスですが、ご指摘ありがとうございます。

# ■No6054だけでなくこんなところにも残っていたのね...。
# 修正しとこ...。

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