現在、KeyUpイベントを使用して、あるキーが押されたらインプットボックスに
入力させる処理を行っているんですが、入力後のリターンキーをKeyUpイベント
が拾ってしまってうまくいきません。
そこでKeyUpイベントルーチンの先頭でイベントを効かないようにして、抜け出す
ときに効くように戻そうかと思っていますが、そのような機能はあるのでしょか?
どなたか教えていただければたすかります。
>そこでKeyUpイベントルーチンの先頭でイベントを効かないようにして、抜け出す
>ときに効くように戻そうかと思っていますが、そのような機能はあるのでしょか?
質問する時は VisualBasic のバージョンを明記してください。
ご使用の VisualBasic のバージョンによって回答が変わってくる事が
ありますので。
で、とりあえず VB6.0 の場合はそのような機能はなかったと思います。
代案としては
・KeyUp イベント処理中であるフラグを用意して回避する
・(支障がなければ) KeyUp イベントでは Enter キーの入力を無視する
ようにする
あたりが考えられるでしょうか。
Geo=TK3さん 申し訳ありません。
OSはWindows2000、言語はVB.netを使用しております。
とりあえずフラグのオンオフで考えましたがまだ成功していません。
なにとぞ良い解決法が、あればご教授お願いします。
>とりあえずフラグのオンオフで考えましたがまだ成功していません。
普通に考えればそれはプログラムがマズいわけですが、
どんなプログラムを書いてどう上手くいかないのか?
の説明無しにこちらでできる助言はありません。
説明不足ですいません。
キーイベントは下記のようなルーチンで、ESCキーが押されたら番号を入力させて、データ内をその番号で検索してあればその行を表示し、無ければその番号でデータを追加しようと思っております。
しかし、番号入力時のリターンを検知して再度このルーチンに入ってリターンキーの処理をしてしまい、番号入力後の処理が出来ないでいます。
従って、できればフラグではなくこのルーチンに処理が移ったら先頭でキーイベントの禁止を行い、このルーチンから抜けるときに許可を行うことができればよいのですが、そんな都合の良い命令はあるのでしょうか?
Private Sub Form_KeyUp(ByVal sender As Object, _
ByVal e As System.Windows.Forms.KeyEventArgs) Handles MyBase.KeyUp
Dim i, a, F_tuika, F_wari As Integer
Dim result As String
If F_wari = 0 Then
Select Case e.KeyCode
Case vbKeyRET 'RETキー
K_code = vbKeyRET
Case vbKeyTab 'TABキー
K_code = vbKeyTab
Case vbKeyESC 'ESCキー
F_wari = 1
result = InputBox("№を入力してください" _
, "№入力", No '№の入力
№入力後にここからの処理をさせたいが、№入力時のリターンキーで上記の
K_code = vbKeyRETに処理が移ってしまう。
For i = 0 To LinMax
データを入寮した番号で検索
Next
検索で見つからなかったのでデータ追加
F_wari = 0
Case vbKeyF2 'F2キー(終了)
K_code = vbKeyF2
End Select
End If
End Sub
Geo=TK3さん言われる通り、フラグ処理で、
Private Sub Form_KeyUp(・・・・
Static Flg As Boolean
If Flg Then Exit Sub
Flg = True
処理・・・
処理・・・
Flg = False
End Sub
とやれば良いでしょう。
回答ありがとうございます。
早速フラグの処理で試してみましたが、リターンキーの処理に移ることはなくなったのですが、ESCキーの処理の残りの処理をやってくれません。
Private Sub Form_KeyUp(ByVal sender As Object, _
ByVal e As System.Windows.Forms.KeyEventArgs) Handles MyBase.KeyUp
Dim i, a, F_tuika, F_wari As Integer
Dim result As String
Static Flg As Boolean
If Flg Then Exit Sub '禁止フラグオン?
Flg = True
Select Case e.KeyCode
Case vbKeyRET 'RETキー
K_code = vbKeyRET
Case vbKeyTab 'TABキー
K_code = vbKeyTab
Case vbKeyESC 'ESCキー
result = InputBox("№を入力してください" _
, "№入力", No '№の入力
ここからの処理に移ってくれない
For i = 0 To LinMax
データを入寮した番号で検索
Next
検索で見つからなかったのでデータ追加
Flg = False
Case vbKeyF2 'F2キー(終了)
K_code = vbKeyF2
End Select
End Sub
なんで e.KeyCode の Select 文で Keys 列挙体を使わないのだろう(疲)
…あと、こちらでは再現しません。デバッグした限りでは
>しかし、番号入力時のリターンを検知して再度このルーチンに入って
>リターンキーの処理をしてしまい、番号入力後の処理が出来ないでいます。
番号入力後の処理はちゃんと処理されてて、その後リターンでイベントが
走ってるようですが???ちゃんと動きを把握してますか???そっちの
問題を言っているなら質問文が間違ってますよ?。質問どおり
>番号入力後の処理が出来ないでいます。
なら先の御二方と同じくフラグで解決できると思います。
後者の問題なら
InputBox 使わずに別フォームで入力させれば解決しそうな気がしますが。
>早速フラグの処理で試してみましたが、リターンキーの処理に移ることは
>なくなったのですが、ESCキーの処理の残りの処理をやってくれません。
フラグの場所が悪いのでは?
出力結果を教えて下さい。
[VB.NET]
Private Const LinMax As Integer = 1
Private K_code As Keys
Private mEventMusi As Boolean
Private Sub Form_KeyUp(ByVal sender As Object, _
ByVal e As System.Windows.Forms.KeyEventArgs) Handles MyBase.KeyUp
Dim i, a, F_tuika, F_wari As Integer
Dim result As String
If Me.mEventMusi = True Then
Debug.WriteLine("無視")
Exit Sub
End If
If F_wari = 0 Then
Select Case e.KeyCode
Case Keys.Enter 'RETキー
K_code = Keys.Enter
Debug.WriteLine("RET")
Case Keys.Tab 'TABキー
K_code = Keys.Tab
Debug.WriteLine("TAB")
Case Keys.Escape 'ESCキー
Debug.WriteLine("ESC")
Me.mEventMusi = True
F_wari = 1
result = InputBox("№を入力してください" _
, "№入力", "No") '№の入力
For i = 0 To LinMax
'データを入力した番号で検索
Debug.WriteLine("検索" & i.ToString)
Next
'検索で見つからなかったのでデータ追加
F_wari = 0
Me.mEventMusi = False
Case Keys.F2 'F2キー(終了)
K_code = Keys.F2
End Select
End If
End Sub
特攻隊長まるるうさん、回答ありがとうございます。
初心者なのでとんちんかんな質問をしているかもしれませんが申し訳ありません。
早速回答のコードを書き込んで実行しましたが、番号入力後はLinemaxを1にして
いるので表示は2行でしたがその2行がコピーされて4行になりました。そして
Debug.WriteLine("検索" & i.ToString)は実行されず"検索"も表示されませんでした。RET、TAB、ESCはきちんと表示できています。
ご指摘のようにうまくいくはずなんですが・・
もう少しがんばってみます。
>早速回答のコードを書き込んで実行しましたが、番号入力後はLinemaxを1にして
>いるので表示は2行でしたがその2行がコピーされて4行になりました。そして
>Debug.WriteLine("検索" & i.ToString)は実行されず"検索"も表示されませんでした。
んー...
これは特攻隊長まるるうさんが提示してくれたコードをそのまま使った時の
実行結果ですよね?
それとも InputBox と For 〜 の間に何か自前の処理いれてます??
>RET、TAB、ESCはきちんと表示できています。
“無視”というのは表示されていますか?
Geo=TK3さん、ありがとうございます。
InputBox と For 〜 の間には何も入れていません。報告漏れでしたが昨日はESCが表示された後に番号入力をすると“無視”が表示されてその後は何のキーを押しても“無視”の表示のみでしたが、タイミングの問題なのかもしれませんが、先ほどの結果は番号入力後に2行コピーまでは同じですが"検索"が2回表示されました。その後数回試したら“無視”の表示になってしまいました。
とりあえず中間報告をしておきます。引き続きがんばってみます。
うーん。不安定ですねぇ。…そんなに順番変わるものかなぁ…。
KeyUp イベントの先頭で
Debug.WriteLine(e.KeyCode)
して何のキーイベントが起こってどう処理されてるのか確かめる
必要があるかなぁ?
[VB.NET]のバージョンは 2003 ?
OSは?サービスパックは?
それとキーイベント系の処理は他に利用してないよね?
DoEvents も使ってないですよね?
フォームでキーイベントを拾ってるという事は
KeyPreview = True
してると思ったんだけど間違ってる?
新規プロジェクトのフォームにテキストボックスを1つ貼り付けて、
フォームの KeyPreview = True して、ボクの提示したコードだけ
コピペして実行しても同じ結果ですか?
>昨日はESCが表示された後に番号入力をすると“無視”が表示されて
>その後は何のキーを押しても“無視”の表示のみでしたが
変数を Static にしてない?わざわざ変数名まで変えてサンプル示した
んだからコードの意味も理解してからテストしてね?(^^;)
エラー処理も削除してね?質問であげた以外でやってることを
全て削除してテストして下さいね?
特攻隊長まるるうさん、回答ありがとうございます。
[VB.NET]のバージョンは 2003、OSはWindows2000、サービスパック=4です。
キーイベント系の処理は他に利用してません。
DoEventsを使っています。当初これを使用しないとリストビューのデータが
表示できなかったのでヘルプを見て使用しました。
KeyPreview = Trueにしています。
変数を Static に変更していません。
下記にメインルーチンを書きました。
DoEventsが間違っているのでしょうか。
Private Sub Form1_Activated(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles MyBase.Activated
'********************************
'* データ読込 *
'********************************
Mode = 0 'モードを選択中
Call Yoteireed() '予定データ読み込み
Call disp() 'データ表示
'********************************
'* オーダー選択 *
'********************************
P_line = 0 '対象行№を先頭
ListView1.Items(P_line).Selected = True
ListView1.Select() '先頭行をアクティブにする
T_start = TimeString '開始時刻取得
Me.start.Text = T_start
Me.M_Mode.Text = Msg(Mode) 'モードの表示
Do While K_code <> vbKeyRET
For Each si As ListViewItem In ListView1.SelectedItems
P_line = si.Index 'ポインター取得
Next
Me.J_number.Text = JutyuN(P_line) '受注№表示
Me.Now.Text = TimeString '現在時刻取得
If K_code = vbKeyF2 Then GoTo OWARI '終了か?
Application.DoEvents()
Loop
良く考えると、Form_KeyUpイベントでやると上手くいきませんね。
>result = InputBox("№を入力してください" _
> , "№入力", "No") '№の入力
この時『OK』ではなく『Return』を押すと、処理はキーの押下時に
すぐ続行されますので、キーを離した時には既にこのForm_KeyUpイベントは抜け
フラグがリセットされされるので、再び Form_KeyUpイベントが起こり、
Keys.Enterの処理をします。
ブレークをかけたり、キーを叩くようにするとタイミングが変わります。
result = InputBox(... の時Returnキーを押しっぱなしにすると良く判ります。
Form_KeyDownイベントで処理すれば問題ないと思われるのですが、何か別の
問題が有るのでしょうか。
あと気になった事1点。
メインルーチンとして公開したソース、どうやら Form_Activated
イベントハンドラのようですが、これだと InputBox で表示した
ダイアログボックスが消去された時に再度呼び出されたりしませ
んかね??
VB.NET が手元にないので確認出来ないんですけど、VB6.0 の
Form_Activate イベントと同じような動作をするのなら何かヤバい
気が...
色々と(ボク的に)気持ち悪いコードが出てきたのはとりあえずスルーしてw
ねろさんの書き込み見て InputBox のキーイベントが何で Form に流れて
来てるのか疑問に思ってたけどオイラの勘違い?
・InputBox Enter
・Enter KeyDown
・InputBox 消え
・Enter KeyUp → Form が受け取る
…かもしかして?
2つ疑問。
1つ目。ある関数(Form_KeyUp)の処理中に起こったキーボードからの
イベント(Enter KeyUp)ってキューされて溜まるんじゃないのかと思って
たんだけど違った?。(ボクのサンプルでは InputBox の後に Doevents
を入れてないから Debug.WriteLine("検索" & i.ToString) が先に実行
されると思ってた)
2つ目、仮にキーボードからのイベント(Enter KeyUp)が先に処理されたと
して、ボクの示したコードではフラグの変更が組みになってる部分の処理は
必ず通るはず…間に色んなイベント処理が入ったとしても
result = InputBox("…
の後の
Debug.WriteLine("検索" & i.ToString)
が永遠に実行されない理由がボクの知識内では見当付きません。
エラー処理か Goto 文や Exit 系の処理で抜けないと不可能だと
思うんですが…あるんでしょうか?そんな事。
>Form_Activate
>これだと InputBox で表示したダイアログボックスが
>消去された時に再度呼び出されたりしませんかね??
…色んな予期せぬ処理が盛りだくさんな予感。
[VB.NET]ボクのサンプルの修正点のみ
result = InputBox("№を入力してください" _
, "№入力", "No") '№の入力
System.Threading.Thread.Sleep(1000)
For i = 0 To LinMax
System.Threading.Thread.Sleep(1000)
'データを入力した番号で検索
Debug.WriteLine("検索" & i.ToString)
Next
Private Sub Form1_Activated(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Activated
Debug.WriteLine("Form1_Activated")
End Sub
[出力結果]
>ESC
>Form1_Activated
>検索0
>検索1
>RET
Activated ヤバいね。
>[出力結果]
の最後の>RETは?
>の最後の>RETは?
>検索1
までが Escape KeyUp による InputBox の処理。
正常にループを処理して Form_KeyUp 関数を抜けた後、
溜まってた Enter KeyUp が2回目の Form_KeyUp 関数で
>RET
出力
ボクの中の結論としては
Form1_Activated の処理で DoEvents が溜まってた
Enter KeyUp を実行しちゃって誤動作…と思うんだけど、
それでもループの出力が無くなるのは理解できなかったです。
再現もできてません。
DoEventsを外してActivatedをLoadに戻して、メインルーチンのループを止めて
解決しました。うまくいかなくて泥沼にはまっていたみたいです。皆さんの意見
を読みながらプログラムを整理しなおして目からうろこでした。
特攻隊長まるるうさん、Geo=TK3さん、ねろさん本当にありがとうございました。
リストビューが更新されないだけなら
Me.ListView1.Refresh()
てのもあります。
遅くなりましたが特攻隊長まるるうさん、Form_Activated に
関する検証どうもありがとうございました。
>それでもループの出力が無くなるのは理解できなかったです。
>再現もできてません。
これは Form_Activated イベントハンドラの中にあるループが
終わらなくなったんじゃないかなぁ、って気がします。
元の Form_Activated イベントハンドラでは K_code という変数が
vbKeyRET にならないと Do 〜 Loop ループが終わらないけど、単
純に Form_KeyUP を特攻隊長まるるうさんのものに差し替えただけ
でループの終了条件を満たさなくなった、とか (^^;; 。
あーΣ(‾□‾)Form1_Activated のループかー
抜けられないねー(汗)
オイラ頭硬くなってるなー( _)_へたり
InputBox → Activated → ループの虜
の繰り返し?…Sleep もしてないし、内部的に CPU は
すごい頑張ってたのかもー。実行したら重くなかった?
…よく動いてたね、このコード。
ちょっと感心しました、CPU に対してw。
すっきりしましたm(__)m
>Geo=TK3 さん
解決したようですが、
FormにTextBoxを一つ置き、FormのKeyPreviewをTrueにしますよね。
そこで
Private Sub Form_KeyUp(ByVal sender As Object, _
ByVal e As System.Windows.Forms.KeyEventArgs) Handles MyBase.KeyUp
Select Case e.KeyCode
Case Keys.Return
Debug.WriteLine("Return")
Case Keys.Escape
Dim result As String = InputBox("")
End Select
End Sub
これだけのコードを書き、Escapeを押して、InputBoxにReturnを押します、
すると Debug.WriteLineにReturnが書かれます、これは明らかにInputBoxの
ReturnのKyeUpイベントですよね、これを回避するにはどうするかと言う
質問ではないのでしょうか、これはフラグでもSleepでも解決しないと
思うのですが、それともその質問は途中で終わったのか。。。
解決したと言うならそれでもいいのですが・・・
>すると Debug.WriteLineにReturnが書かれます、これは明らかにInputBoxの
>ReturnのKyeUpイベントですよね、これを回避するにはどうするかと言う
>質問ではないのでしょうか、これはフラグでもSleepでも解決しないと
>思うのですが、それともその質問は途中で終わったのか。。。
>解決したと言うならそれでもいいのですが・・・
大元の質問は途中で終わってますね、確かに。
話をそちらに戻すと。
特攻隊長まるるうさんがやったくださった Form_Activated の検証結果から
みても、ねろさんのご推察通り、単純なフラグや Sleep では InputBox の
Return の KeyUp イベントは回避できないと私も思います。
# 公開されているテストコードを使っていて、それで一番最後に RET が出力
# されているのが...
対策として一番簡単なのは、やはりねろさんがおっしゃっていたように
KeyDown イベントで処理するように変える事ですが、あえて KeyUp イベントの
ままでいく方法を考えてみました...が結局
・処理中フラグをクリアするタイミングを KeyUp イベントハンドラの
Return キー処理時のみにする
というかなりトリッキーなものしか思いつきませんでした (^^;; 。
# いっそ Return キーを無視してしまうというのも考えなくもないですが。
んー。オイラは最初から (InputBox の誤動作と勘違いしてたのでw)
InputBox 使わずに自分で動作を制御できる Form で入力させて
そっちのフォームで Enter KeyUp が処理されるまで待ってやれば
いいだけでは?…と思ってましたが。
あ、その手がありましたね (^^;; 。
別にわざわざ InputBox にこだわる必要はないのですし (^^;; 。
何か発想ヨワ〜。>自分
ツイート | ![]() |