コンボボックスのテキストからフォームを表示

タグの編集
投稿者 おち  () 投稿日時 2008/9/27 07:03:39
いつも勉強させてもらっています。 
VBAでプログラムに興味をもって、最近VB2008を始めました。 
目次と、その他のフォームからなるプログラムを作ろうとしています。 
combobox1にフォーム名が表示させ、button2をクリックすると 
そのnameを持ったフォームが表示されるようにしたいのですが、それ以前に 
「showはstringのメンバではありません」と 
エラーになります。VBAならこれで動くと思うのですが・・・・ 
根本的に違うのでしょうか? 

Private Sub Button2_Click(ByVal sender As System.ObjectByVal e As System.EventArgs) Handles Button2.Click 
    Dim hyouji As String 
    hyouji = ComboBox1.Text 
    hyouji.show() 
End Sub 


投稿者 るきお  (社会人) 投稿日時 2008/9/27 07:05:09
こんにちは。 

あまり一般的ではない要件だと思います。要件を再考することをおすすめしますが、技術的には以下のようにして可能です。 

   
Dim hyouji As String 
hyouji = Me.GetType.Namespace & "." & ComboBox1.Text 

Dim f As Form 
f = Activator.CreateInstanceFrom(Me.GetType.Assembly.Location, hyouji).Unwrap() 
f.Show()


ただし、制限がいくつかあります。呼び出しもとのフォームをForm1とすると、Form1と対象のフォームが同じ名前空間で同じプロジェクト上にある必要があります。 
(もっとも上述のプログラムを多少変えればこの制限もとりはらえます) 

>「showはstringのメンバではありません」と 
VBからみればComboBox1.TextはあくまでもString型なのでこのようになります。 

>VBAならこれで動くと思うのですが・・・・ 
そうでしたっけ?VBAでもVB6でもこの手法では無理なように記憶しています。他の手法でもかなり厳しいです。VB6では不可能といってもいいくらいです。 

>根本的に違うのでしょうか? 
VBAとVB2008は根本的に違う面もありますが、今回の質問の範囲内では根本的な違いはありません。
投稿者 おち  () 投稿日時 2008/9/27 07:05:47
ありがとうございます。 

VBAで試したところ、出来ませんでした。勘違いでした。 

余り一般的ではないようなので、分相応にもっと簡単な方法は無いでしょうか? 
単純にフォームの数だけボタンかラベルを配置する事くらいなら組めるのですが、「目次」自体は出来るだけコンパクトにしたいのと、今後も数が増える予定なので出来ればコンボボックスかリストでいくのがコンパクトにいけるのではないかと考えています。 
たとえば、フォームに番号を割り振って、リストでその番号を選んで表示するなど・・・
投稿者 あにす  () 投稿日時 2008/9/27 07:06:16
求められている仕様がいまいちよくわからないのですが、こんなのはどうでしょうか? 
これなら簡単だし、フォームを増やすのも楽だと思います。 

Option Strict Off 

Public Class Form1 
    Private Sub Form1_Load(ByVal sender As System.ObjectByVal e As System.EventArgs) Handles MyBase.Load 
        Me.ComboBox1.DisplayMember = "Text" 
        Me.ComboBox1.Items.Add(New Form2()) 
    End Sub 

    Private Sub Button1_Click(ByVal sender As ObjectByVal e As System.EventArgs) Handles Button1.Click 
        Dim selectedForm As Form = Me.ComboBox1.SelectedItem 
        selectedForm.Show() 
    End Sub 
End Class 

Public Class Form2 
    Inherits Form 

    Public Sub New() 
        Me.Text = "Form2" 
    End Sub 

    Private Sub Form2_FormClosing(ByVal sender As ObjectByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing 
        e.Cancel = True 
        Me.Hide() 
    End Sub 
End Class 


フォームが増えた場合は 
Me.ComboBox1.Items.Add(New Form3()) 
と追加していくだけです。 

このままだと閉じたフォームを再度開こうとしたときにエラーが出るので少し工夫が要りますけどね。 

投稿者 あにす  () 投稿日時 2008/9/27 07:06:49
>このままだと閉じたフォームを再度開こうとしたときにエラーが出るので少し工夫が要りますけどね。 

挙げたコードは上記の問題については修正済みのコードでした。
投稿者 魔界の仮面弁士  () 投稿日時 2008/9/27 07:07:11
>>1 
> VBAでもVB6でもこの手法では無理なように記憶しています。 
ちょっと違いますが、このような書き方はできますね。 

《VBA》 
UserForms.Add("UserForm2").Show 

《VB6》 
Forms.Add("Form2").Show 

《VB2008》 
CallByName(My.Forms, "Form2", CallType.Get).Show()
投稿者 るきお  (社会人) 投稿日時 2008/9/27 07:07:42
魔界の仮面弁士さん、すばらしいです。 
勉強になりました。Myの他の機能にも応用できそうです。 
それにC#だと無理というところが、VB中学校の管理者としてちょっとうれしいポイントです。 

あにすさんの手法も面白いと思いましたが、ComboBoxに項目を追加するために項目ごとにフォームのインスタンスを作らないといけない点が難点ですかね。
投稿者 おち  () 投稿日時 2008/9/27 07:08:24
あにすさん 魔界の仮面弁士 ありがとうございます。 
あにすさんのコードでイメージ通りのものが出来ました。 

前半は理解できるのですが、後半が良く分かりませんでした。
 
Public Class Form2 
    Inherits Form 

    Public Sub New() 
        Me.Text = "Form2" 
    End Sub 

    Private Sub Form2_FormClosing(ByVal sender As ObjectByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing 
        e.Cancel = True 
        Me.Hide() 
    End Sub 
End Class 


二度目に表示させる為に、格納された名前を一度クリアしているのだと解釈したのですが・・・ 
少し自分で理解してみます。ありがとうございました。
投稿者 あにす  () 投稿日時 2008/9/27 07:08:53
>>7 
コンボボックスに入れているのはForm2のインスタンスそのものなので、×ボタン等でフォームを閉じてしまうと、 
再度Button1を押してフォームを開こうとしても、インスタンスが無くなっているのでエラーが出るんです。 

そこで、フォームが閉じられようとしたとき(Form2_FormClosingメソッド)に、閉じる動作をキャンセル(e.Cancel = True)して非表示(Me.Hide())にしています。再度開こうとしたときには、非表示にしたForm2がそのまま表示されます。
投稿者 あにす  () 投稿日時 2008/9/27 07:09:13
いっそのことプラグインにしちゃうってのも面白いと思います。 

http://dobon.net/vb/dotnet/programing/plugin.html 

サンプルをC#で>1の仕様に合わせて修正してみたら上手くいったので、VBでも問題ないと思います。