DOBON.NET DOBON.NETプログラミング掲示板過去ログ

Formsコレクションについて

分類:[.NET]

環境:Windows2000 SP3 VB.NET

 最近VBを使い始めたはるかと申します。
VBはゼロからのスタートなのでヘルプを見ても全然理解できず、またまわりに
聞いてもVBを知っている人がいなくなってしまったために聞くこともできず、
皆様のお力を是非お借りしたくて書き込みさせていただきました。

 元々VB5.0で作られていたプログラムをVB.NET化するために、VB.NETにある機能で
アップデートを行ったのですが、そこでForms.Countという風に記述されている
箇所で「UPGRADE_ISSUE: Forms コレクション はアップグレードされませんでした」
とコメントが記されています。VB.NETにはFormsコレクションが無いような記述が
されているのですが、Forms.Countと同じような処理をするにはどのようにすれば
良いのか教えていただけないでしょうか?

 まだVBを始めたばかりなのでヘルプを見ても理解できず勉強不足なのに質問
するのはご迷惑をおかけしてるとは思いますが、この先必ず勉強していきます
ので、今回だけはよろしくお願いいたします。m(__)m
>  元々VB5.0で作られていたプログラムをVB.NET化するために、VB.NETにある機能で
> アップデートを行ったのですが、そこでForms.Countという風に記述されている
> 箇所で「UPGRADE_ISSUE: Forms コレクション はアップグレードされませんでした」
> とコメントが記されています。VB.NETにはFormsコレクションが無いような記述が
> されているのですが、Forms.Countと同じような処理をするにはどのようにすれば
> 良いのか教えていただけないでしょうか?

その通りで、VB.NETにFormsコレクションはありません。

[HOW TO] Visual Basic .NET で Forms コレクションを作成する方
http://support.microsoft.com/default.aspx?scid=kb;ja;JP308537

を参考にFormsコレクションを自作されては?
> [HOW TO] Visual Basic .NET で Forms コレクションを作成する方
> http://support.microsoft.com/default.aspx?scid=kb;ja;JP308537
>
> を参考にFormsコレクションを自作されては?

よねKENさん、どうもありがとうございます。

こちらを参考にしてみました。しかし、正しいのかわからないので以下に手順を
記述しますので間違っていたら指摘していただけないでしょうか?
1.プロジェクトメニューのクラスの追加
2.FormsCollectionクラスを作成
3.プロジェクトメニューのモジュールの追加
4.StartHereモジュールを作成
5.Application.Run()に一番最初に呼び出されるフォームを設定
6.Formsが使用されているモジュールのSub New()内にForms.Add(Me)と
  Forms.Remove(Me)を追加

これで良いのでしょうか?
上記のやり方で行うと、Forms.Countの部分についてはエラーがなくなったのですが、
その下の方にForms(1).Captionという処理がありまして、こちらの方は
「クラス 'SPPDEF.FormsCollection'には既定のプロパティがないため、
 インデックス処理ができません。」
と言われてエラーになってしまいます。これを解決する方法も教えていただく
ことはできないでしょうか?

基本的な事を伺っているような感じがして申し訳ないのですがよろしくお願いします。
> その下の方にForms(1).Captionという処理がありまして、こちらの方は

Forms(1).text ではどうでしょうか?はずしてたらすみません。
> Forms(1).text ではどうでしょうか?はずしてたらすみません。

tinaさん、どうもありがとうございます。

tinaさんの指摘のようにCaptionをTextに変更してみたのですが、どうもFormsの
所に青字で下線がついているのでプロパティではなくてFormsそのものに何か
処理が足りないような感じがするのです。Textに変更してもエラーメッセージは
変わっていませんでした。
2003/07/23(Wed) 17:04:28 編集(投稿者)

>>Forms(1).text ではどうでしょうか?はずしてたらすみません。

私もこれでいけるかな?と思ったんですが、だめでしたか。

> tinaさんの指摘のようにCaptionをTextに変更してみたのですが、どうもFormsの
> 所に青字で下線がついているのでプロパティではなくてFormsそのものに何か
> 処理が足りないような感じがするのです。Textに変更してもエラーメッセージは
> 変わっていませんでした。

DirectCast(Forms(1), Form).Text

あるいは、

DirectCast(Forms.Item(1), Form).Text

ではどうですか?
度々ご指摘くださいましてありがとうございます。

> DirectCast(Forms(1), Form).Text

こちらで試してみたのですが、Formsの部分が相変わらず青字下線がついている
状態で、エラーメッセージも変化がありませんでした。


> DirectCast(Forms.Item(1), Form).Text

こちらの方も試してみたのですが、こちらはForms.Itemに青字下線がついて、
「'Item'は'SPPDEF.FormsCollection'のメンバではありません」という
エラーメッセージになりました。


FormsCollectionクラスは以下のように記述しました。
Public Class FormsCollection
Inherits CollectionBase

Public Shadows Function Add(ByVal FormObject As Form) As Form
MyBase.List.Add(FormObject)
Return FormObject
End Function

Public Shadows Sub Remove(ByVal FormObject As Form)
MyBase.List.Remove(FormObject)
End Sub
End Class


StartHereモジュールは以下のように記述しました。
Module StartHere
Public Forms As FormsCollection

Sub Main()
Forms = New FormsCollection()
Application.Run(New Main_Renamed())
End Sub

End Module


よねKENさんから一番最初に指摘を受けたページをそのままコピー&ペーストで
貼り付けて作っただけなのですが、この部分に何かが足りないのでしょうか?
■No215に返信(はるかさんの記事)

横からしゃしゃり出るみたいで、申し訳ありません。

そもそもFormsCollectionクラスの基本クラスがCollectionBaseクラスであるために
分かりにくくなっているのではないでしょうか。
ヘルプを見ると、CollectionBaseクラスにはItemプロパティやインデクサが
実装されていないので、FormsCollectionクラスを次のように作り直す必要が
ありそうです。

Public Class FormsCollection
    Inherits CollectionBase

    'ここを追加
    Default Public Property Item(ByVal index As Integer) As Form
        Get
            Return CType(List(index), Form)
        End Get
        Set(ByVal Value As Form)
            List(index) = Value
        End Set
    End Property

    Public Shadows Function Add(ByVal FormObject As Form) As Form
        MyBase.List.Add(FormObject)
        Return FormObject
    End Function

    Public Shadows Sub Remove(ByVal FormObject As Form)
        MyBase.List.Remove(FormObject)
    End Sub
End Class
管理人さん、どうもありがとうございます。
そして返事が遅れて申し訳ございません。

> ヘルプを見ると、CollectionBaseクラスにはItemプロパティやインデクサが
> 実装されていないので、FormsCollectionクラスを次のように作り直す必要が
> ありそうです。

管理人さんのおっしゃられるように、Forms.の後に自動で表示されるプロパティなどに
Itemプロパティが表示されていなかったので使えないのかな?と思っていたのですが
やはり処理を追加しないといけなかったみたいですね。しかし、まだまだ知識のない
私にはどのような処理を追加すれば良いのかわからず、止まったままでした。


> Public Class FormsCollection
> Inherits CollectionBase
>
> 'ここを追加
> Default Public Property Item(ByVal index As Integer) As Form
> Get
> Return CType(List(index), Form)
> End Get
> Set(ByVal Value As Form)
> List(index) = Value
> End Set
> End Property
>
> Public Shadows Function Add(ByVal FormObject As Form) As Form
> MyBase.List.Add(FormObject)
> Return FormObject
> End Function
>
> Public Shadows Sub Remove(ByVal FormObject As Form)
> MyBase.List.Remove(FormObject)
> End Sub
> End Class

追加する部分をプログラムに追加したところ、今までエラーとなっていた
DirectCast(Forms.Item(1), Form).Text のForms.Itemの部分はエラーが
なくなり正常に戻りました。
実際にビルドして実行してみたところ、VB5.0で行っていたことと同じ動作で
あることも確認できました。


よねKENさん、tinaさん、管理人さん、この度は親切にお答えいただきまして
どうもありがとうございました。教えていただいた事はまだ完全には理解していない
状況なのですが、今後もVBを続けていこうと思っているので完全に理解するように
いたします。
解決済み!
■No220に返信(はるかさんの記事)
> 追加する部分をプログラムに追加したところ、今までエラーとなっていた
> DirectCast(Forms.Item(1), Form).Text のForms.Itemの部分はエラーが
> なくなり正常に戻りました。

Forms.Item(1).Text
または
Forms(1).Text

と普通に書けます。

いまさらこんなことを言うのもなんですが、はるかさんが初心者であるということを考えると、このように自作のクラスを作成するのではなく、素直にArrayListクラスを使うべきだと私は思います。VB.NETだと、"FormsCollection"を"ArrayList"と置き換えるだけで正常に動くのではないでしょうか。

つまり、

Public Forms As ArrayList
Forms = New ArrayList()

という風に。
返事が遅れてしまい申し訳ございません。

> いまさらこんなことを言うのもなんですが、はるかさんが初心者であるということを
> 考えると、このように自作のクラスを作成するのではなく、素直にArrayListクラス
> を使うべきだと私は思います。VB.NETだと、"FormsCollection"を"ArrayList"と
> 置き換えるだけで正常に動くのではないでしょうか。

管理人さんがおっしゃる手順で確認してみたところ正常に動作いたしました。なので、
どちらの使い方でも正常に動く事は確認できたのですが、自作のクラスを作るやり方と
今回管理人さんが勧めてくださったやり方では何か違いというのはあるのでしょうか?

VB.NETのヘルプを見てみても自作のクラスを作るやり方しか記載されておらず、初心者
である私は挫折したので、自作のクラスを作成しなくてもできるやり方があれば、
こちらのやり方を最初からヘルプに載せておいてもくれてもいいのに…。と思うのは
わがままなのでしょうか?(^^;
> 管理人さんがおっしゃる手順で確認してみたところ正常に動作いたしました。なので、
> どちらの使い方でも正常に動く事は確認できたのですが、自作のクラスを作るやり方と
> 今回管理人さんが勧めてくださったやり方では何か違いというのはあるのでしょうか?

自作クラス側のコレクションはForm型のオブジェクトしか扱いません(扱えません)。
そのため、FormsコレクションにForm(及びそれを継承したクラス)以外を
追加してしまうというミスが発生することがありません。
もしFormsコレクションに他のオブジェクトを追加するようなコードを書いても、
コンパイルエラーになり、問題の早期発見になります。

> VB.NETのヘルプを見てみても自作のクラスを作るやり方しか記載されておらず、初心者
> である私は挫折したので、自作のクラスを作成しなくてもできるやり方があれば、
> こちらのやり方を最初からヘルプに載せておいてもくれてもいいのに…。と思うのは
> わがままなのでしょうか?(^^;

ArrayListを使う方法は手抜きな方法なので、あまりサンプルとしては好ましくなく、
また、旧VBとの互換という点でも非互換になるので乗せにくいでしょう。

でもまあ、Formsコレクションの実装としてArrayListを使っても独自のFormsCollectionを使っても、
Formsという名前の変数でフォームを入れる変数ですよとわかるようにしているので、
通常Formsコレクションにフォーム以外を追加してしまうようなミスはしないでしょうから、
ArrayListでもそれほど問題はないでしょうけど。
■No237に返信(よねKENさんの記事)

よねKENさんが書いていただいたので、私の出る幕はなさそうですが、もとは私なので、なんか書いておきます。

まず、ArrayListと自作コレクションの違いですが、よねKENさんがご指摘されたように、自作コレクションでは厳密に型指定がされることや、ArrayListでは余計な機能がくっついているのに対して、自作コレクションでは必要な機能だけを持たせ、コンパクトに出来るという点があげられそうです。

またヘルプにArrayListを使った方法がない点については、もし本当にそうなのであれば、「フォームのコレクション」と銘打った説明では、まさに「フォームのコレクション」を説明しなければならず、ArrayListのような汎用的なコレクションは広く「コレクション」の項で説明するということかもしれません。(普通は「フォームのコレクション」の前に「コレクション」について調べるだろうと考え、ArrayListについては当然知っているだろうということかもしれません。)

さてそれでは.NET Frameworkで用意されていない型のコレクションが必要な時、ArrayListを使うか、わざわざその型専用のコレクションを作るかということになると、ほとんどの場合、ArrayListを使うでしょう(少なくとも私のような初心者は)。ただし、外部に公開したプロパティやメソッドなどでコレクションを使う時は、自作コレクションにすべきというケースが多そうです。

私もまだまだひよっこなので、えらそうなことはかけませんが。
またもや返事が遅くなり申し訳ございません。

自作コレクションとArrayListの大きな違いは、よねKENさんと管理人さんのご指摘にある、
 ・Form型のオブジェクトしか扱えない
 ・他のオブジェクトを追加するようなコードを書いてもコンパイルエラーになり、問題の早期発見になる
 ・旧VBとの互換という点でも非互換になる
 ・ArrayListでは余計な機能がくっついている
 ・自作コレクションでは必要な機能だけを持たせ、コンパクトに出来る

上記のことから、
 ・VBにまだ慣れていない時は自作コレクションを作るのではなくArrayListを
  使用した方が簡単に作成することができる。
 ・慣れてきたら自作コレクションを使用し、無駄な機能を持たせずコンパクトな
  形にし、誤ったコーディングをした場合にコンパイルエラーとなって問題を発見しやすい。
と理解しました。

私はまだまだVB初心者なのでArrayListを使用した方が簡単に作成することができる
のでしょうが、今回に限りましては皆様に自作コレクションの方を先に教えていただく
ことができたので、上記に挙げたメリットを考えると自作コレクションの方がコードと
しては良いコードになると思い、自作コレクションの方で作成していくことにしました。

今回質問をさせていただき、当初の質問の回答だけではなく、自作コレクションのメリットや
ArrayListなどの他の機能などもご教授くださいまして本当にありがとうございました。
今後もVBをもっと理解して皆様のように人に教える事ができるよう頑張っていきたいと
思います。
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板