none
VBでコントロール配列のハンドルの書き方が分かりません。 RRS feed

  • 質問

  • VBでコントロール配列のハンドルの書き方が分かりません。
    Visual Studio Community 2015
    Visual Basic

    ボタンを配列にして表示したいです。
    表示するところまでは完成しました。

    総数と列数を決めれば、表示できる状態まで作りました。

    押したボタンの処理の書き方が分かりません。


    通常のボタンは、配置したボタンをダブルクリックすると生成してくれます。

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click

    End Sub

    ロジックで書いたボタンは、起動時まで実態が無いので、それを自力で書かないといけないようですが、そこが分かりません。


    いくつかのサイトを参考に見様見真似で書いてみましたがビルドエラーになります。

    デリゲートと AddressOf 演算子
    https://msdn.microsoft.com/ja-jp/library/74wy9422(v=vs.90).aspx

    コントロールの配列を作成する
    https://dobon.net/vb/dotnet/control/buttonarray.html



    AddHandler Button_Test(IntFor).Click, AddressOf Button_Test_Click
    こういう感じで行けるのかと思いましたが下記のようなエラーになります。

    エラーBC30451'Button_Test_Click' は宣言されていません。
    アクセスできない保護レベルになっています。



    Public Class Form2
      Const C_All As Integer = 31 ' 総数
      Const C_Kai As Integer = 16 ' 改列
     
      Private Button_Test() As System.Windows.Forms.Button
     
      Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Const C_Pich_X As Integer = 200 ' 横ピッチ
        Const C_Pich_Y As Integer = 37 ' 縦ピッチ
        
        Dim ColIndex As Integer = 0
        Dim RowIndex As Integer = 0
        Dim PutLocation_X As Integer = 0
        Dim PutLocation_Y As Integer = 0
        
        Me.Button_Test = New System.Windows.Forms.Button(C_All - 1) {}
        
        Me.SuspendLayout()
        
        ' ボタン
        For IntFor As Integer = 0 To C_All - 1
        Dim StartLocation_X As Integer = 10
        Dim StartLocation_Y As Integer = 20
        
        'インスタンス作成
        Me.Button_Test(IntFor) = New System.Windows.Forms.Button
        
        'プロパティ設定
        With Me.Button_Test(IntFor)
        .Name = "Button_Test" & Format(IntFor + 1, "00")
        .Size = New Size(56, 29)
        .Text = "TEST"
        
        ColIndex = Int((IntFor) / C_Kai)
        RowIndex = IntFor - C_Kai * ColIndex
        
        PutLocation_X = StartLocation_X + C_Pich_X * ColIndex
        PutLocation_Y = StartLocation_Y + C_Pich_Y * RowIndex
        
        .Location = New Point(PutLocation_X, PutLocation_Y)
        End With
        
        'イベントハンドラに関連付け
        'AddHandler Button_Test(IntFor).Click, AddressOf Button_Test_Click
         ↑ここがビルドエラー
        
        Next
        
        'フォームにコントロールを追加
        Me.Controls.AddRange(Me.Button_Test)
        For IntFor As Integer = 0 To C_All - 1
        With Me.Controls
        .Add(Me.Button_Test(IntFor))
        End With
        Next
        
        Me.ResumeLayout(False)
      End Sub
    End Class
    2017年4月11日 0:10

回答

  • 上の回答を少し補足します。
    以下のようにTagにボタンを識別する番号を入れるという方法も一般的に行われます。

    With Me.Button_Test(IntFor)
        .Name = "Button_Test" & Format(IntFor + 1, "00")
        .Size = New Size(56, 29)
        .Text = "TEST"
        .Tag = IntFor    'Tagに識別番号を設定
    
        ColIndex = Int((IntFor) / C_Kai)
        RowIndex = IntFor - C_Kai * ColIndex
    
        PutLocation_X = StartLocation_X + C_Pich_X * ColIndex
        PutLocation_Y = StartLocation_Y + C_Pich_Y * RowIndex
    
        .Location = New Point(PutLocation_X, PutLocation_Y)
    End With

    イベントハンドラは例えば以下のような感じでどのボタンが押されたかを判断できます。

    Private Sub Button_Test_Click(sender As Object, e As EventArgs)
    
        Dim btn = CType(sender, Button)
        MessageBox.Show(btn.Tag)
    
    End Sub
    もちろん、CTypeでキャストして押されたButtonコントロールそのものを取得できていますので、そこからそのNameプロパティなどいろいろなButtonに関する情報を得ることができます。


    ★良い回答には回答済みマークを付けよう! MVP - .NET  http://d.hatena.ne.jp/trapemiya/


    2017年4月11日 0:55
    モデレータ

すべての返信

  • 単純に、Button_Test_Clickというイベントハンドラが定義されていないだけに見えます。
    以下のイベントハンドラを追加してみて下さい。

    Private Sub Button_Test_Click(sender As Object, e As EventArgs)
    
    'ここにボタンを押された時の処理を記述。どのボタンが押されたかはsenderで判断できる。
    
    End Sub


    ★良い回答には回答済みマークを付けよう! MVP - .NET  http://d.hatena.ne.jp/trapemiya/

    2017年4月11日 0:46
    モデレータ
  • あ、

    Private Sub Button_Test_Clicked(ByVal sender As Object, ByVal e As EventArgs)
    End Sub

    これを書くとビルドエラーがなくなりました。

    でも、この中でどのボタンを押されたのか判定の仕方が分かりません。

    配列のインデックスを取る方法を教えてください。

    2017年4月11日 0:46
  • 上の回答を少し補足します。
    以下のようにTagにボタンを識別する番号を入れるという方法も一般的に行われます。

    With Me.Button_Test(IntFor)
        .Name = "Button_Test" & Format(IntFor + 1, "00")
        .Size = New Size(56, 29)
        .Text = "TEST"
        .Tag = IntFor    'Tagに識別番号を設定
    
        ColIndex = Int((IntFor) / C_Kai)
        RowIndex = IntFor - C_Kai * ColIndex
    
        PutLocation_X = StartLocation_X + C_Pich_X * ColIndex
        PutLocation_Y = StartLocation_Y + C_Pich_Y * RowIndex
    
        .Location = New Point(PutLocation_X, PutLocation_Y)
    End With

    イベントハンドラは例えば以下のような感じでどのボタンが押されたかを判断できます。

    Private Sub Button_Test_Click(sender As Object, e As EventArgs)
    
        Dim btn = CType(sender, Button)
        MessageBox.Show(btn.Tag)
    
    End Sub
    もちろん、CTypeでキャストして押されたButtonコントロールそのものを取得できていますので、そこからそのNameプロパティなどいろいろなButtonに関する情報を得ることができます。


    ★良い回答には回答済みマークを付けよう! MVP - .NET  http://d.hatena.ne.jp/trapemiya/


    2017年4月11日 0:55
    モデレータ
  • Tagに仕込んでおくのですね。

    TabIndexを利用するあたりまでは辿り着いたのですが、
    他のコントロールとの兼ね合いでTabIndexを使うとややこしくなるので、
    どうしたものかと思っていたところでした。

    助かりました。ありがとうございます。

    2017年4月11日 1:22