サブフォームのTab移動について

このQ&Aのポイント
  • VB2005で開発を行っております。とあるサイトでMDIとは別の方法でフォーム内にフォームを貼り付けることができることを知りました。
  • Form1とForm2があり、Tabキーによるフォーカス移動を行うと、Form1のコントロールからForm2のコントロールへの移動は行えるのですが、その後はForm2のコントロール内のみフォーカス移動が行われてしまいます。
  • Form2がGroupBoxやPanelコントロールのように動作するようにしたいのですが、どのようにすればよいでしょうか?
回答を見る
  • ベストアンサー

サブフォームのTab移動について

VB2005で開発を行っております。 とあるサイトでMDIとは別の方法でフォーム内にフォームを貼り付けることができることを知りました。 以下がその簡単なコードです。 Public Class Form1 Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Dim f As New Form2() f.TopLevel = False Me.Controls.Add(f) f.Show() f.BringToFront() End Sub End Class ここでそれぞれのフォームにTextBoxなどのコントロールを貼り付け、Tabキーによるフォーカス移動を行うと、Form1のコントロールからForm2のコントロールへの移動は行えるのですが、その後はForm2のコントロール内のみフォーカス移動が行われてしまいます。 できればForm2がGroupBoxやPanelコントロールのように動作してほしいのですが、どのようにすればよいでしょうか?

質問者が選んだベストアンサー

  • ベストアンサー
回答No.1

こんなのはどうでしょう? form2に2つのtextboxを用意します。(フォーカスを持てるコントロールなら何でもいいんだけど) 名前をdummy0,dummy1とします。 見えないように、BorderStyle=none,ReadOnly=trueにします。 dummy0のtabindexを0,dummy1のtabindexをform2の最大tabindex+1にします。 これでform2の最初のtabストップがdummy0,最後がdummy1になります。 各々のgotfocusを以下にします。 以上で、たぶん希望の動きをすると思いますが・・・ Private Sub dummy0_GotFocus(ByVal sender As Object, ByVal e As System.EventArgs) Handles dummy0.GotFocus If Control.ModifierKeys And Keys.Shift = Keys.Shift Then 'shiftキーが押されている? Me.Parent.SelectNextControl(Me, False, True, True, True) '親の前へ Else Me.SelectNextControl(Me.ActiveControl, True, True, True, True) '次へ End If End Sub Private Sub dummy1_GotFocus(ByVal sender As Object, ByVal e As System.EventArgs) Handles dummy1.GotFocus If Control.ModifierKeys And Keys.Shift = Keys.Shift Then 'shiftキーが押されている? Me.SelectNextControl(Me.ActiveControl, False, True, True, True) '前へ Else Me.Parent.SelectNextControl(Me, True, True, True, True) '親の次へ End If End Sub

TheLock
質問者

お礼

上手くいきました! 希望通りの動作をしてくれて満足しています。 ありがとうございました。 ただ、回答してくださったコードをGotFocusイベントではなく、 Enterイベントに記述しても上手くいかないのはなぜなのでしょうか? .NETからはGotFocusイベントはEnterイベントに変更されたと思い込んでいたので、 少し気になります。 (そもそもGotFocusとEnterの違いがわかっていない…)

その他の回答 (2)

回答No.3

>>ただ、回答してくださったコードをGotFocusイベントではなく、 >>Enterイベントに記述しても上手くいかないのはなぜなのでしょうか? >Form2のDummy1にFocusが来た場合、VBはDummy1のEnterとGotFocusの処理を行います。 >Enterの時点でForm1の方にFocusを移動しても、GotFocusの処理中にFocusが戻されるようです。 >まず、私のコードをEnterイベントに記述して、何もしないGotFocusを用意します。 >次に、Form1の選ばれるはずのControlにEnterとGotFocusを用意します。 >各々のイベントの最初にブレークポイントを設定します。 >Dummy1にFocusが移った場合、どの順番でイベントが発生するかを見ればわかると思います。 自分で書いたのですが、よく考えたら同じフォーム内ではFocusが移動するんだから・・・ やっぱりよくわかりません。

TheLock
質問者

お礼

私のほうでもいろいろ調べてみましたが、いまいちよくわかりませんでした。 できればEnterイベントで実装してみたかったのですが、 現状、希望通りの動作をしているので、回答していただいたコードを実装することにします。 ありがとうございました。

回答No.2

>.NETからはGotFocusイベントはEnterイベントに変更されたと思い込んでいたので、 >少し気になります。 知らなかった・・・ 何も考えずにやったら動いたので回答したんです、すみません。 確かに今googleしてみたら、Enterの方を使うのがいいようですね。 GotFocusは、なくなったのではなく低水準のなので使うべきではないということみたいですね。 >(そもそもGotFocusとEnterの違いがわかっていない…) 私もよくわかりませんが「ちゃんと正規のコマンドがあるのに、やたらとWindowsAPI使うな」みたいな事でしょうか。 >ただ、回答してくださったコードをGotFocusイベントではなく、 >Enterイベントに記述しても上手くいかないのはなぜなのでしょうか? Form2のDummy1にFocusが来た場合、VBはDummy1のEnterとGotFocusの処理を行います。 Enterの時点でForm1の方にFocusを移動しても、GotFocusの処理中にFocusが戻されるようです。 まず、私のコードをEnterイベントに記述して、何もしないGotFocusを用意します。 次に、Form1の選ばれるはずのControlにEnterとGotFocusを用意します。 各々のイベントの最初にブレークポイントを設定します。 Dummy1にFocusが移った場合、どの順番でイベントが発生するかを見ればわかると思います。 解決法は・・・、すみません、わからないです。

関連するQ&A

  • ↓Downキーでフォーカスの移動ができません。

    ご多忙中申し訳ありません。 TextBoxが複数ありまして、↓キーを使用してフォーカスの移動をタブインデックスに従って変更したいのですが、Enterキーなら順番に移動しますが、Downキーですと何も変化がありません。 Downキーの場合は何か、コードの追加が必要でしょうか? あと、できれば←や↑ →なども使用してフォーカスの移動をしたいとおもいますが アドバイスをお願いします。 Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Me.KeyPreview = True End Sub Private Sub Form1_KeyPress(ByVal sender As System.Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles MyBase.KeyPress If e.KeyChar = Chr(Keys.Down) Then  '←ここの部分がEnterキーならフォーカスの移動ができます。 Me.SelectNextControl(Me.ActiveControl, True, True, True, True) e.Handled = True End If End Sub 申し訳ありません。宜しくお願いします。

  • focusメソッドを使ってもカーソルが点滅しない

    フォームをロードし、下記のようにしてもカーソルが点滅しません。その解決方法を教えてください。 Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load TextBox1.Focus() End Sub

  • フォームを画面のど真ん中に表示させたいのですが

    フォームを画面のど真ん中に表示させたいのですが、 http://dobon.net/vb/dotnet/form/startposition.html を見たのですがコードの書き方がよくわかりません。 Public Class Form1 Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load Dim f As New Form1() 'フォームを画面の真ん中に表示する f.StartPosition = FormStartPosition.CenterScreenf.Show() End Sub End Class こうすると、「FormStartPosition.CenterScreenf」の部分に波線がひかれます。 Public Class Form1 Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load Me.StartPosition = FormStartPosition.Manual Me.Location = New Point(0, 0) End Sub End Class これで左は時に表示する事は出来るのですが、真ん中に表示させるにはどうすればいいでしょうか?

  • VB2010でMDI親フォームから子フォームを表示

    VB2010でソフトを作っております。 MDI親フォームから子フォームを表示させたいのですが…。 過去に少しだけVB6を使っていたことがありますが、クラスという概念に苦労しております インスタンスや初期化といったところをうまく扱えばとは思うのですが、よろしくご指導お願いいたします。 1.MDI親フォーム(Form1)のボタンを押し、子フォーム(Form2)を表示させる 2.子フォームが表示されていなかったら表示させる 3.子フォームが表示されていたら何もしない これだけの事ですがずいぶん悩んでおります。 全コードがこれです。 Public Class Form1 Private f2 As New Form2 Private Sub Form1(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Me.IsMdiContainer = True End Sub Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim fChild As Form() = Me.MdiChildren For Each f As Form In fChild If f.Text = "Form2" Then Exit Sub End If Next f2 = New Form2 f2.MdiParent = Me f2.Show() f2.Activate() End Sub Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click If f2 Is Nothing OrElse f2.IsDisposed Then f2 = New Form2 f2.MdiParent = Me End If f2.Show() f2.Activate() End Sub End Class ボタン1でもボタン2でも、期待する動作はするのですが、 ボタン1ではアクティブになっているフォームの名前を力技で取得している気がして… ボタン2では子フォーム(Form2)をすでに表示している状態でもさらにShowをしているのが気に入らなくて… もっとスマートな方法がありましたら、ご指導お願いします。

  • 「Me」を「Form1」にするとエラーになる理由

    VB2008です。 Public Class Form1 Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Me.Text = "a" Form1.Text = "a" ’←「Form1.Text」に波線ができる。 End Sub End Class というように、 「Me」を「Form1」にすると 「既定のインスタンスからそれ自体を参照できません。'Me' を使用してください。」 となります。 VBAなら「Me」を「Form1」にしてもエラーにならないのに、 どうしてVBだとエラーになるのでしょうか?

  • SerialPort処理でInvokeメソッドを使用するとエラーが発生。

    はじめまして。こんばんわ。 同一プロジェクトの複数のフォームから、RS232C接続処理を行っております。 まったく同じ処理内容なので、クラスを使用しようとしております。 しかし、データ受信時、Invokeメソッドを使用して、各フォームのイベントをCALLしますと、『InvalidOperationException』が発生し、『ウィンドウ ハンドルが作成される前、コントロールで Invoke または BeginInvoke を呼び出せません。』というエラーメッセージが表示されてしまいます。 ソースを下記に記載いたします。どなたか、原因・対処方法がわかる方がいらっしゃいましたら、御手数をおかけいたしますが、ご教示の程、よろしくお願い申し上げます。 ============================== 呼び出し元フォーム ============================== Public Class Form1   Private cls232CIns As cls232C   Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click     cls232CIns.openport()   End Sub   Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load     cls232CIns = New cls232C()   End Sub   Public Sub DispData(ByVal data As String)     TextBox1.Text = data   End Sub End Class ============================== SerialPort通信クラス ============================== Imports System.IO.Ports Public Class cls232C   WithEvents SP1 As SerialPort   Delegate Sub RecvDataDisp(ByVal dataR As String)   Public Sub New()     SP1 = New SerialPort("COM6", 9600)   End Sub   Public Sub openport()     SP1.Open()   End Sub   Public Sub closeport()     SP1.Close()   End Sub   Public Sub ReceiveData(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SP1.DataReceived     Dim getdata As String     getdata = SP1.ReadLine     Form1.Invoke(New RecvDataDisp(AddressOf Form1.DispData), getdata) ←ここでエラー発生   End Sub End Class  

  • form2がボタンを押すと消えてしまう

    vb2010で、作成しています。form1から、form2を呼び出し、okボタンまたは、cancelボタンを押すと、無条件でform2が消えてしまいます。私がしたいのは、form2(パスワード入力ウィンドウ)でテキストボックスにパスワードを入力してokボタンを押して、それが正しい(1234)ときのみform2を消去することです。現在のところ、入力したパスワードが間違っていてもokボタンを押すと、form2は消えてしまいます。 form1側のコードとform2側のコードは以下です。お手数ですが御教示いただけると幸いです。 /////////Form1 Public Class Form1 Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim f As New Form2() f.TextBox1.PasswordChar = "*"c '//入力文字をマスクする If f.ShowDialog(Me) = DialogResult.OK Then If f.TextBox1.Text = "1234" Then f.Dispose() End If End If End Sub End Class /////////Form2 Public Class Form2 Private Sub btnOK_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnOK.Click Dim f As Form1 f = Me.Owner Me.DialogResult = DialogResult.OK End Sub Private Sub btncancel_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btncancel.Click Dim f As Form1 f = Me.Owner Me.DialogResult = DialogResult.Cancel End Sub End Class

  • 特定のフォームだけ別フォームからの参照がされません

    VB 2005,Framework2.0を使用しています。 現在、サブフォームからダイアログフォームを表示し、ダイアログフォーム内の入力値等をサブフォームに渡す処理を行っています。 サブフォームは複数作成しており、特定のサブフォームだけダイアログフォームの入力値がサブフォームに渡されず原因が分からなくて困っています。 コードは以下のような形で書いています。 'サブフォーム Public Class Form1 Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim f As New Dialog1 f.StartPosition = FormStartPosition.CenterParent f.ShowDialog() End Sub End Class 'ダイアログフォーム Public Class Dialog1 Private Sub OK_Button_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles OK_Button.Click Form1.Label1.Text = Textbox1.text Me.Close() End Sub End Class 2005では、別フォームからの参照はVB6と同じようにインスタンスを作成しなくても参照できる様になったと聞いていますので、上記のコードでも参照方法として問題はないと思うのですが、うまく動作しない原因が分かる方が居られましたら宜しくお願いします。

  • Form間のデータ渡しについて

    申し訳ありません。VB.NET初心者です。 Form1から、ボタンAをクリックするとForm2がオープンします。 Form1から、ボタンBをクリックするとForm3がオープンします。 Form1では、Form2またはForm3で設定した値をそれぞれ演算に使おうとしています。 MicrosoftのHPからパクってForm1 - Form2間のデータの引渡しを行うことはできたの ですが、新規でForm3を作成して、Form1 - Form3間のデータの引渡しを行おうとする とForm3の立ち上がり時に "NullReferenceException はハンドルされませんでした"となり、 困ってしまいました。 使われている方から見ると簡単かもしれず 申し訳ありませんが、どなたか教えていただけないでしょうか。 ==================== Form1.vb ======================= Form1には、Label1、Label2、Button1、Button2があります。 Public Class Form1 Inherits System.Windows.Forms.Form Private m_form2 As Form2 Private m_form3 As Form3 Public Property LabelText() As String Get Return Label1.Text End Get Set(ByVal Value As String) Label1.Text = Value End Set End Property Public Property LabelText2() As String Get Return Label2.Text End Get Set(ByVal Value As String) Label2.Text = Value End Set End Property Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ScaleYokusou.Click m_form2 = New Form2(Me) m_form2.ShowDialog() m_form2.Dispose() End Sub Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ScaleHikito.Click m_form3 = New Form3() m_form3.ShowDialog() m_form3.Dispose() End Sub End Class ==================== Form2.vb ======================= Form2には、TextBox1、Button1があります。 Public Class Form2 Inherits System.Windows.Forms.Form Private m_form1 As Form1 Private Sub TextBox1_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles TextBox1.TextChanged If m_form1 Is Nothing = False Then m_form1.LabelText = Me.TextBox1.Text End If End Sub Private Sub Form2_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load If m_form1 Is Nothing = False Then Me.TextBox1.Text = m_form1.LabelText End If End Sub Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Me.Close() End Sub End Class ==================== Form3.vb ======================= Form3には、TextBox1、Button1があります。 Public Class Form3 Inherits System.Windows.Forms.Form Private m_form1 As Form1 Private Sub TextBox1_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TextBox1.TextChanged If m_form1 Is Nothing = False Then m_form1.LabelText2 = Me.TextBox1.Text End If End Sub Private Sub Form3_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Me.TextBox1.Text = m_form1.LabelText2 End Sub Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Me.Close() End Sub End Class

  • 新規レコードへ移動しない

    Access2010を使用しています。 サブフォームからメインフォームの「登録」ボタンプロシージャをCallした時、メイン・サブフォーム共に新規レコードへ移動しなくて困っています。 具体的には、サブフォームにフォーカスがある時に「F12」を押すと画面の入力項目の内容刃そのままでメインフォームの「注文番号」テキストボックスにフォーカスが移動します。 メインフォームにフォーカスがあるか、マウスで「F12」をクリックすると画面の入力項目がクリアされて新規レコードへ移動します。 コードは以下の内容が記述してあります。 ーーーーーサブフォーム----- Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer) Select Case KeyCode Case 123 Call Me.Parent.Form_KeyDown(KeyCode, Shift) KeyCode = 0 End Select End Sub -----メインフォーム----- Public Sub Form_KeyDown(KeyCode As Integer, Shift As Integer) Select Case KeyCode Case 123 Call 登録_Click KeyCode = 0 End Select End Sub Private Sub 登録_Click() DoCmd.GoToRecord , , acNewRec Me.注文番号.SetFocus End Sub

専門家に質問してみよう