連載:アップグレード・ウィザードに学ぶVB 6→VB 2005

第3回 ココが違う! VB 6と.NETのコントロール・コレクション

グレープシティ株式会社 八巻 雄哉
2007/03/16
Page1 Page2


Back Issue
1
AppオブジェクトからMyオブジェクトへ
2
ClipboardオブジェクトとMy.Computer.Clipboardオブジェクト

 今回変換するVisual Basic 6.0(以下VB 6)の特殊オブジェクトは「Controlsコレクション」です。コレクションという名前が付いていますが、Collectionクラスのメンバというわけではなくフォーム(Form)のControlsプロパティによってのみ提供され、インスタンス化することはできない立派なVB 6の特殊オブジェクトです。このControlsコレクションを利用して、フォーム上のすべてのコントロールに変更を加える、実行時に動的にコントロールに追加する、といったことがVB 6ではできました。

 それでは今回も、変換する前のVB 6のサンプル・プロジェクトから見ていきます。サンプル・プロジェクトのコードがリスト1、その実行画面が図1になります。

Dim WithEvents TextBoxObject As VB.TextBox

Private Sub CommandAdd_Click()

  ' Frameコントロール内にTextBoxコントロールを動的に追加します。
  Set TextBoxObject = Me.Controls.Add("VB.TextBox", "Text1", Frame1)
  TextBoxObject.Visible = True
  TextBoxObject.Top = 500
  TextBoxObject.Left = 500

  ' [追加]ボタンを無効に、[削除]ボタンを有効にします。
  CommandAdd.Enabled = False
  CommandRemove.Enabled = True

End Sub

Private Sub CommandRemove_Click()

  ' Text1をFrameコントロールから削除します。
  Me.Controls.Remove "Text1"

  ' [削除]ボタンを無効に、[追加]ボタンを有効にします。
  CommandAdd.Enabled = True
  CommandRemove.Enabled = False

End Sub

Private Sub CommandWhite_Click()

  ' Controlsコレクションから各コントロールを取り出し、
  ' CommandButtonオブジェクトのみ背景色を白に設定します。
  Dim controlObject As Control
  For Each controlObject In Me.Controls
    If TypeOf controlObject Is CommandButton Then
      controlObject.BackColor = vbWhite
    End If
  Next

End Sub
リスト1 Controlsコレクションを使ったVB 6のサンプル・プロジェクトのコード


図1 リスト1の実行画面(VB 6アプリケーション)
4つのCommandButtonコントロールとFrameコントロールを使用している。この画面では[追加]ボタンを押して、Frameコントロール内にTextBoxコントロールを動的に追加している。また[全部白いボタン]ボタンを押し、すべてのCommandButtonコントロールの背景色を白に変更している。
※ボタンの背景色を変更するため、CommandButtonのStyleプロパティの値をデフォルトの「0 - 標準」から「1 - グラフィックス」に変更しておく必要があることに注意。

 このサンプル・プロジェクトは、以下の機能を持っています。

  • [追加]ボタンを押すことでFrameコントロール内にTextBoxコントロールを動的に追加し、[追加]ボタンを無効に、[削除]ボタンを有効にする。
  • [削除]ボタンを押すことでFrameコントロール内に追加されたTextBoxコントロールを削除し、[削除]ボタンを無効に、[追加]ボタンを有効にする。
  • [全部白いボタン]ボタンを押すことで、フォーム上に配置されているすべてのCommandButtonコントロールの背景色を白に変更する。

 では、アップグレード・ウィザードを使ってこのプロジェクトをVisual Basic 2005(以下VB 2005)のコードに変換してみましょう。リスト1のコードを変換した結果が次のリスト2です。

Dim WithEvents TextBoxObject As System.Windows.Forms.TextBox

Private Sub CommandAdd_Click(ByVal eventSender As System.Object, ByVal eventArgs As System.EventArgs) Handles CommandAdd.Click

  ' Frameコントロール内にTextBoxコントロールを動的に追加します。
  'UPGRADE_ISSUE: Controls メソッド Controls.Add はアップグレードされませんでした。 詳細については、'ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?keyword="CC4C7EC0-C903-48FC-ACCC-81861D12DA4A"' をクリックしてください。
  TextBoxObject = Me.Controls.Add("VB.TextBox", "Text1", Frame1)
  TextBoxObject.Visible = True
  TextBoxObject.Top = VB6.TwipsToPixelsY(500)
  TextBoxObject.Left = VB6.TwipsToPixelsX(500)

  ' [追加]ボタンを無効に、[削除]ボタンを有効にします。
  CommandAdd.Enabled = False
  CommandRemove.Enabled = True

End Sub

Private Sub CommandRemove_Click(ByVal eventSender As System.Object, ByVal eventArgs As System.EventArgs) Handles CommandRemove.Click

  ' Text1をFrameコントロールから削除します。
  Me.Controls.RemoveAt("Text1")

  ' [削除]ボタンを無効に、[追加]ボタンを有効にします。
  CommandAdd.Enabled = True
  CommandRemove.Enabled = False

End Sub

Private Sub CommandWhite_Click(ByVal eventSender As System.Object, ByVal eventArgs As System.EventArgs) Handles CommandWhite.Click
    Dim controlObject As System.Windows.Forms.Control

  ' Controlsコレクションから各コントロールを取り出し、
  ' CommandButtonオブジェクトのみ背景色を白に設定します。
  Dim controlObject As System.Windows.Forms.Control
  For Each controlObject In Me.Controls
    'UPGRADE_WARNING: TypeOf に新しい動作が指定されています。 詳細については、'ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?keyword="9B7D5ADD-D8FE-4819-A36C-6DEDAF088CC7"' をクリックしてください。
    If TypeOf controlObject Is System.Windows.Forms.Button Then
      controlObject.BackColor = System.Drawing.Color.White
    End If
  Next controlObject

End Sub
リスト2 アップグレード・ウィザードで変換したVB 2005のコード

 アップグレード・ウィザードではうまく変換できなかった個所、変換はされたもののそのままでは期待した動作とならない個所と、今回は3つのプロシージャとも修正しなければならない部分があります。修正が必要な個所ごとに、問題の詳細とその修正方法について説明していきます。

コントロールを動的に追加する部分

 FrameコントロールにTextBoxコントロールを動的に追加する部分がうまく変換されませんでしたが、この部分の修正方法を説明する前に、まずはフォーム上に配置されたコントロールの親子関係がVB 6とVB 2005では異なるということについて説明しなければなりません。


図2 フォーム上のコントロールの親子関係の違いを表した概念図
VB 6ではFormオブジェクトにのみあるControlsプロパティに、すべての子コントロールを追加する。VB 2005ではすべてのコントロールにControlsプロパティがあり、親となるコントロールのControlsプロパティに子コントロールを追加する。VB 2005では、「Button4」は「GroupBox1」の子でなければならない(図右下)。

 VB 6ではControlsというプロパティは、FormオブジェクトやMDIFormオブジェクトといったフォームとなるオブジェクトにのみ存在し、そこに配置されたコントロールはすべてこのControlsプロパティから取得することができます。

 つまり、概念的にはすべてのコントロールがFormオブジェクトの子要素として同列に存在しているととらえることができます。そのため、Frameコントロール上にCommandButtonコントロールを追加するなど、Formオブジェクト以外のコンテナにコントロールを追加する場合には、ControlsコレクションのAddメソッドの第3パラメータに追加先のコントロールを指定するという方法になります。

Set TextBoxObject = Me.Controls.Add("VB.TextBox", "Text1", Frame1)
「Frame1」にTextBoxコントロールを追加(リスト1より抜粋)

 一方、VB 2005ではフォームもコントロールの1つとなり、すべてのコントロールがControlsプロパティを持っています。そのため、例えばフォーム上にコントロールを追加する場合には、FormオブジェクトのControlsプロパティを使ってControlCollectionオブジェクトを参照し、そのAddメソッドを実行します

 同様に、GroupBoxコントロール(VB 6のFrameコントロールに該当)上にコントロールを追加する場合には、GroupBoxオブジェクトのControlsプロパティを使って、Addメソッドを実行します。

Me.Frame1.Controls.Add(TextBoxObject)
「Frame1」にTextBoxコントロールを追加(リスト3より抜粋)

 すべてのコントロールがFormオブジェクトの子要素として同列に存在しているわけではなく、Formオブジェクトの子要素としてGroupBoxオブジェクトが存在し、その子要素としてButtonオブジェクトが存在しているといった概念になります。

■VB 2005でコントロールを動的に追加

 それでは、修正したコードを見ていきましょう。リスト3がTextBoxコントロールを動的に追加する部分の修正済みのコードになります。

' GropuBoxコントロール(Frame1)内にTextBoxコントロールを動的に追加します。
TextBoxObject = New TextBox()
Me.Frame1.Controls.Add(TextBoxObject)
TextBoxObject.Name = "TextBox1"
'TextBoxObject.Visible = True
TextBoxObject.Top = VB6.TwipsToPixelsY(500)
TextBoxObject.Left = VB6.TwipsToPixelsX(500)
リスト3 VB 2005でコントロールを動的に追加する場合

 まず、VB 6では見られなかったコードとして、Newキーワードを使ってTextBoxクラスのオブジェクト・インスタンスを生成する部分があります。

 VB 6のControlsコレクションに用意されているAddメソッドでは、第1パラメータに追加したいコントロールを識別する文字列(ProgID)を指定するという方法になっていました。

 VB 2005のControlCollectionクラスに用意されているAddメソッドでは、追加したいコントロールのオブジェクトをパラメータとして渡すようになっています。そのため、Addメソッドを実行する前に、あらかじめTextBoxオブジェクト(オブジェクト・インスタンス)を生成しておく必要があります。それから、VB 6ではAddメソッドの第2パラメータで追加するコントロールの名前(Nameプロパティ)を設定していましたが、VB 2005ではTextBoxオブジェクトに直接Nameプロパティを設定する必要があります。

 また、VB 6では動的に追加したコントロールのVisibleプロパティのデフォルト値はFalseとなっているため、そのコントロールを表示させるにはVisibleプロパティをTrueに設定する必要がありました。VB 2005では生成したコントロールのVisibleプロパティのデフォルト値はTrueとなっているため、明示的にTrueに設定する必要はありません。

■VB 6のTwipsとVB 2005のピクセルとの変換

 さらに、VB 6のコントロールのサイズや位置を表す数値の単位は、デフォルトでは「Twips」ですが、VB 2005では「ピクセル」になります。そのため、アップグレード・ウィザードで変換されたコードは、VisualBasic.Compatibility名前空間の「TwipsToPixelsX」と「TwipsToPixelsY」という関数を使ってTwips値をピクセル値に変換しています。

 なお、変換するVB 6のフォームのScaleModeプロパティが「1 - Twips」以外に設定されている場合には、アップグレード・ウィザードによる変換はうまくいきませんので注意してください。

 ピクセル値は自分で計算することもできますので、算出した数値を直接設定しても構いません。1インチは1440Twipsです。画面のdpiはデフォルトでは96dpiとなっていますので、1インチの大きさは96ピクセル(ドット)で表されます。この場合に500Twipsと同じ長さとなるピクセルは次のような式で求められます。

( 500 / 1440 ) X 96 = 33.33333……

 続いては、動的に追加したコントロールを削除する部分について説明します。


 INDEX
  アップグレード・ウィザードに学ぶVB 6→VB 2005
  第3回 ココが違う! VB 6と.NETのコントロール・コレクション
  1.コントロールを動的に追加
    2.追加したコントロールを削除/すべてのボタンの背景色を白に
 
インデックス・ページヘ  「アップグレード・ウィザードに学ぶVB 6→VB 2005」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)
- PR -

注目のテーマ

業務アプリInsider 記事ランキング

本日 月間
ソリューションFLASH