- - PR -
FocusしたらLostFocusが走る?
投稿者 | 投稿内容 | ||||||||
---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2006-12-26 12:08
こんにちは。いつもお世話になっております。
開発環境VB2005.NET DB=Firebird WindowsXPです フォーム上にテキストボックス3つと自作のユーザーコントロールを 貼り付けています。 フォーム上ではEnterキーを押すと次のコントロールへ移動する 処理を行っています。 ですがテキストボックスで↓キーを押されたら自作ユーザーコントロールを 表示させて、このユーザーコントロールにフォーカスを移したいのですが、 いい方法が見つかりません。 なぜか、ユーザーコントロールにFocus()するとそのコントロールの LostFocusにブレークします。 ActiveControlとして設定しても無理でした。 SelectNextControlはTabIndexの次の順番ですので、 その一つ前のコントロールを設定すると動くのですが、他に方法はないでしょうか・・? これでは汎用性がないのです。 ちなみにユーザーコントロールにフォーカスが移れば、 その内部ではきちんとEnterキーで移動できます(コントロール内部で制御) あと、ユーザーコントロールがLostFocusした時点で 取得した値を保存して、Visible=FALSEしていますが、これは制御的には どうなんでしょうか・・ どうぞよろしくお願いいたします。 Private CC As Control '保存用コントロール Private Sub Form1_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles MyBase.KeyDown If e.KeyCode = Keys.Enter Then If Me.ActiveControl.Name = SearchBox2.Name Then Debug.Print("今SEARCHBOX2がACTIVE") Else Me.SelectNextControl(Me.ActiveControl, True, True, True, True) e.Handled = True End If End If End Sub Private Sub TextBox2_KeyDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles TextBox2.KeyDown Select Case e.KeyCode Case Keys.Down Me.SearchBox2.Visible = True 'Me.ActiveControl = SearchBox2 CC = sender '12/26 以下だとlostFocusされてしまう 'SearchBox2.Focus() '12/26 以下だとフォーカスがこない 'SearchBox2.Select() 'SearchBox2はTextBox4の次のTabIndexのため、仕方なく・・ Me.SelectNextControl(TextBox4, True, True, True, True) e.Handled = True End Select End Sub Private Sub SearchBox2_GotFocus(ByVal sender As Object, ByVal e As System.EventArgs) Handles SearchBox2.GotFocus Debug.Print("SEARCHBOX2のGOTFOCUS!!") End Sub Private Sub SearchBox2_LostFocus(ByVal sender As Object, ByVal e As System.EventArgs) Handles SearchBox2.LostFocus Dim mmCODE As Integer Debug.Print(SearchBox2.wCODE) Debug.Print(CC.Name) mmCODE = SearchBox2.wCODE SearchBox2.Visible = False If TypeName(CC) = "TextBox" Then CC.Text = mmCODE End If End Sub | ||||||||
|
投稿日時: 2006-12-26 12:59
想像が容易でないので、間違ったことを書いているかもしれませんが、 まず、1 点目。 "LostFocus にブレークする" とありますが、LostFocus イベントは、低水準のイベントです。 同様に、GotFocus イベントも低水準なイベントです。 予期せぬ状況 (名前にそぐわない状況) でも発生しうるイベントであり、使用しない方が良いでしょう。 LostFocus イベントの代わりに Leave イベントを使用しましょう。 GotFocus イベントの代わりに Enter イベントを使用しましょう。 2 点目。 UserControl に Focus を設定すると、まず UserControl の Enter イベントが起きます。 そして、そこから先は、UserControl 側の仕事です。 UserControl 内のコントロールの面倒は、直属の親である UserControl が面倒を見ます。 これは、Form 側で SelectNextControl メソッドを実行した場合だろうと、何であろうと同じことです。 _________________ C# と VB.NET の入門サイト じゃんぬねっと日誌 | ||||||||
|
投稿日時: 2006-12-26 15:03
じゃんぬねっとさん、ご返信ありがとうございます。
LostFocusをやめてLeaveにし、GotFocusをやめてEnterに しましたところ、Textボックスで↓キー押下により ユーザーコントロールの表示となり、そこにフォーカスが移り あとはユーザーコントロール内部でのEnterキー移動となりました。 ですが、ユーザーコントロール内部で作成した「終了」ボタン (TabIndex最終)を押しても、フォーム側のユーザーコントロールの Leaveイベントが発生しません・・ これは、ユーザーコントロールの「終了」Click時に 自分自身をLeaveさせるとかしないといけないのでしょうか? ユーザーコントロール内部で、データを選択(Enterキー)しても 「終了」ボタンを押しても、ユーザーコントロールの終了ということで それ自身を消して、フォームの次のコントロールへ移動したいのです。 現在、ユーザーコントロール内部でDisposeさせると、 フォーム側で次に呼び出しをしても表示されません。。 フォーム側の処理としては ・テキスト1でEnter押す→テキスト2 ・テキスト1で↓キー押す→ユーザーコントロールの表示でユーザーコントロール 内部の制御 ・ユーザーコントロール内部で「終了」→ユーザーコントロールの非表示→ テキスト2へフォーカス ・テキスト2で↓キー押す→ユーザーコントロール内部の制御 が希望です。 ユーザーコントロールからフォーカスを移動することに困難中です。 何かいい案かもしくはヒントでもないでしょうか? よろしくお願いいたします。 | ||||||||
|
投稿日時: 2006-12-26 15:04
すみません。ユーザーコントロールの「終了」処理です。
'閉じるボタン押下でコントロール終了 Private Sub CloseButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CloseButton.Click, CloseButton.Enter '接続していたら、閉じる If Me.OdbcConnection1.State = ConnectionState.Open Then Me.OdbcConnection1.Close() End If '返す値は0 wCODE = 0 MessageBox.Show("コントロール終了です。選択された値=" & wCODE) 'コントロール終了のため、データ・表示をクリアしておく DataGrd.DataSource = Nothing DataGrd.ClearSelection() DataGrd.Columns.Clear() '↓次回検索結果が出ないからダメ 'DataGrd.Dispose() SearchText.Text = "" CountLabel.Text = 0 '↓次回使用するとき使えない??・・ Me.Dispose() 'RaiseEvents OnLeave(e New System.EventArgs()) '↓これはアプリ開発者側で設定する 'Me.Visible = False End Sub | ||||||||
|
投稿日時: 2006-12-26 16:14
結果的に "フォーカスが離れた" ことにはなるのでしょうけど、 その UserControl は Form から見えなくなってしまっているので、 Leave イベント発動条件としては、微妙なところですね。
とりあえずは、別のコントロールにフォーカスを追い出してしまえば良いと思います。 その前に、UserControl の Leave イベントに拘っている理由がわからないです。 UserControl が見えなくなった時に何かをしたいのであれば、別に手段がありますよね。 _________________ C# と VB.NET の入門サイト じゃんぬねっと日誌 | ||||||||
|
投稿日時: 2006-12-26 16:58
じゃんぬねっとさん、いつもご丁寧にありがとうございます。
ユーザーコントロール側で「終了」ボタンを押下したときに Me.Validate()を追加しました。 フォーム側 Private Sub SearchBox2_Validated(ByVal sender As Object, ByVal e As System.EventArgs) Handles SearchBox2.Validated Debug.Print(Me.ActiveControl.Name) 'e.Handled = True Dim mmCODE As Integer Debug.Print(SearchBox2.wCODE) Debug.Print(CC.Name) mmCODE = SearchBox2.wCODE SearchBox2.Visible = False If TypeName(CC) = "TextBox" Then CC.Text = mmCODE End If Me.SelectNextControl(Me.ActiveControl, True, True, True, True) End Sub でも、結局はユーザーコントロールの終了後、 別のフォーカスに移さないと、コントロールが非表示になりません。 OnLeaveさせると、なぜかLeaveイベントが永遠に走ってました・・ ユーザーコントロール側の制御が「終了」した場合に どうすればいいのか・・・ 自分自身をDisposeしてしまうと、 フォーム側で別のテキストで↓を押しても(Visible=TRUEしても) 表示されません。 >その前に、UserControl の Leave イベントに拘っている理由がわからないです。 >UserControl が見えなくなった時に何かをしたいのであれば、別に手段がありますよね。 拘ってるつもりはなかったのですが・・・ ・テキスト1でEnter押す→テキスト2 ・テキスト1で↓キー押す→ユーザーコントロールの表示でユーザーコントロール 内部の制御 ・ユーザーコントロール内部で「終了」→ユーザーコントロールの非表示→ テキスト2へフォーカス ・テキスト2で↓キー押す→ユーザーコントロール内部の制御 という制御で、Leaveを使わず、かつ非表示はフォーム側で行うということは 可能なのでしょうか? というか、「閉じる」処理で値を返したあと、何かイベントを 発生させないといけないのか、Focusをフォーム側に持っていくには? 処理が分からないです。 フォーム側 Private Sub Form1_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles MyBase.KeyDown If e.KeyCode = Keys.Enter Then If Me.ActiveControl.Name = SearchBox2.Name Then 'SearchBox2の内部でEnter制御中 Debug.Print("今SEARCHBOX2がACTIVE") Else Me.SelectNextControl(Me.ActiveControl, True, True, True, True) e.Handled = True End If End If End Sub ↑この中で、ユーザーコントロールの「閉じる」ボタンが押されたか どうかを判定できるのでしょうか? ご教授のほど、よろしくお願いいたします。 | ||||||||
|
投稿日時: 2006-12-26 17:21
Leave イベントに頼るのではなく 「UserControl が終了した」 ということを Form 側が関知できるようにしましょう。 UserControl に終了したことを示す独自のイベントを定義して、Raise すれば Form 側で関知できます。
考え方を変えて、値は Form 側が勝手に参照するようにしましょう。 終了のタイミングさえ Form 側が関知できれば、UserControl を非表示にして、 フォーカスを設定したいコントロールを決めることも容易です。 _________________ C# と VB.NET の入門サイト じゃんぬねっと日誌 | ||||||||
|
投稿日時: 2006-12-27 09:31
じゃんぬねっとさん、ご返信ありがとうございます。
ご指摘のとおり、ユーザーコントロールにイベントを発生、 フォーム側にそのイベントを記述したら、 上手くいきました! ユーザーコントロール側 '終了関知 宣言 Public Event SearchEnd(ByVal sender As Object, ByVal e As System.EventArgs) '12/27追加 終了時にCALL RaiseEvent SearchEnd(Me, New System.EventArgs()) フォーム側 宣言 'FriendではなくPrivateとします Private WithEvents SearchBox2 As SearchBox.SearchBox Private Sub SearchBox2_SearchEnd(ByVal sender As Object, ByVal e As System.EventArgs) Handles SearchBox2.SearchEnd Dim mmCODE As Integer Debug.Print("ユーザーコントロールで終了が押されました") Debug.Print(Me.ActiveControl.Name) Debug.Print(SearchBox2.wCODE) Debug.Print(CC.Name) mmCODE = SearchBox2.wCODE SearchBox2.Visible = False If TypeName(CC) = "TextBox" Then CC.Text = mmCODE End If '↓以下ではTabIndexで違うコントロールへフォーカスが移ってしまう 'Me.SelectNextControl(Me.ActiveControl, True, True, True, True) Me.SelectNextControl(CC, True, True, True, True) End Sub 終了時の引数をsenderとeにしてますが、いずれ使うかも知れないので、 このままで・・ ユーザーコントロールを初めて作成しましたが、いろいろと勉強になりました。 長々とお付き合いただいて、本当にありがとうございました。 |