コードからコントロールの生成

解決


アミュ(永遠の初心者)  2009-12-19 21:48:03  No: 143011

VB2008をXPで利用しているものです。

  コントロール、正確にはPictureBoxを16個作りたいのです。コードから

  Dim PictureBox(15) As Label

  として宣言して座標などを指定して

  Me.Controls.Add(PictureBox(15))

  とすると、「NullReferenceExceptionはハンドルされませんでした。」と言うエラーが出てしまいます。内容を読むと、どうやら宣言のときにNewを使わないといけないようですが、配列的に(?)コントロールを生成するときにはNewがなぜか使えません。

  どうすれば、うまく作れるか教えてください。あと、コントロールがうまく出来た後、Private Sub 〜  の形に持っていくにはどうすればよいのでしょうか?


特攻隊長まるるう  2009-12-19 22:14:53  No: 143012

> Dim PictureBox(15) As Label
Label になってますが?あと、変数名に既存のクラス名を使うのも良くないですね。

上記コードはコントロールを格納できるエリアを16個用意しただけです。
実際にコントロールは1個も作成されていません。

配列のそれぞれのエリアにコントロールの実体(インスタンス)を格納するには、
ループを回してそれぞれのエリアに1つ1つ New したコントロールを格納
していってください。


魔界の仮面弁士  2009-12-19 22:32:12  No: 143013

> コントロール、正確にはPictureBoxを16個作りたいのです。コードから
> Dim PictureBox(15) As Label
As Label では、16個の「ラベル」の器が作成されますよ。
Dim PictureBoxes(15) As PictureBox
のように、「As PictureBox」にしておきましょう。

> 配列的に(?)コントロールを生成するときにはNewがなぜか使えません。
例えば、
  Dim c(1) As Control
  c(0) = New TextBox()  'Control そのものではなく、その継承クラスをセット
  c(1) = PictureBox1    '他の場所で生成されたコントロールを代入
のような事があり得るため、それぞれの要素ごとに New する必要があります。

変数宣言と同時に New したいのであれば、
  Private PictureBoxes() As PictureBox = {New PictureBox(), New PictureBox()}
のように記述します。

> Private Sub 〜  の形に持っていくにはどうすればよいのでしょうか?
どういう意味でしょうか?
もし、イベントを受け取りたいという意味であれば、AddHandler を使えば OK です。

たとえば、こんな感じ。

Public Class Form1
    Private PictureBoxes(2) As PictureBox

    Private Sub Form1_Load() Handles Me.Load
        BackgroundImage = Icon.ToBitmap()
        PictureBoxes(0) = New PictureBox()
        PictureBoxes(1) = New PictureBox() With {.Top = 100, .BackColor = Color.CornflowerBlue}
        PictureBoxes(2) = New PictureBox() With {.Left = 100, .BackColor = Color.Yellow}
        Controls.AddRange(PictureBoxes)

        AddHandler PictureBoxes(0).Click, Function() MsgBox("クリックされました")
        AddHandler PictureBoxes(1).DoubleClick, AddressOf Clicked
        AddHandler PictureBoxes(0).MouseMove, AddressOf Moving
        AddHandler PictureBoxes(1).MouseMove, AddressOf Moving
        AddHandler PictureBoxes(2).MouseMove, AddressOf Moving
    End Sub

    Private Sub Clicked()
        MsgBox("ダブルクリック!")
    End Sub

    Private Sub Moving(ByVal o As PictureBox, ByVal e As MouseEventArgs)
        Text = String.Format("{0}, {1}", o.Bounds, e.Location)
    End Sub
End Class


米貴  2009-12-20 01:08:31  No: 143014

コードでコントロールを作る場合は、全部初期設定しとけよ。
暴走するぞwwVBは完璧ではないんで。
と言っても、質問者は入門者だから、もっと基礎をキチントやれば。


アミュ(永遠の初心者)  2009-12-20 04:07:37  No: 143015

お3方ありがとうございました。

For i = 0 To 15
PictureBox(i) = New PictureBox
(中略)
Next

  このようにしてNewにしました。

  Private Sub〜というのは、イベントの受け取り方でした。拙くてすみませんでした。

  僕が質問した件では全面的に解決しましたが、米貴さんの全部初期設定しなければならないというと、プロパティをすべて設定しなくてはならないと言うことでしょうか?


  2009-12-20 04:08:51  No: 143016

魔界の仮面弁士 さんの回答は明解ですね。
恐れ入ります。
この世界の第一人者ではないかと尊敬しております。


アミュ(永遠の初心者)  2009-12-20 04:19:55  No: 143017

そうですね。以前も回答を参考にしたことがあります。今回回答してくださって、驚き、喜びです。


米貴  2009-12-20 04:36:06  No: 143018

アミュさん>いや、プロじゃないんだし、コントロールを1こずつフォームに入れた方が良いと思う。
将来的(長いプログラム)になった時に変数名とかコントルール名が重複したりしてVB自体がエラーを拾えなくなる可能性とかあるしさ。
そんなに沢山コントロールも必要ないでしょ?

とゆうわけです。


アミュ(永遠の初心者)  2009-12-20 05:20:15  No: 143019

いや、必要なんですw

  前回フォームから作成したときとてつもなく長いコードになってしまい、しかも見にくくなったので。

  エラーを拾えなっても、こっちのほうがいいです。

  皆さんありがとうございました。


※返信する前に利用規約をご確認ください。




  


  このエントリーをはてなブックマークに追加