-
VB.NETの標準コントロールには Tag プロパティがあります。 このプロパティは Form Button TextBox など全ての標準コントロールには存在します。 (標準コントロールは System.Windows.Forms.Control から派生しているので当然なのですが) このプロパティを各種のデータの退避領域として使うのが今回の目的です。
VB.NETの「オブジェクト ブラウザ」で Tag 定義を見てみると以下の様になっています。Tag プロパティについて
Public Property Tag As Object System.Windows.Forms.Control のメンバー 概要: コントロールに関するデータを格納するオブジェクトを取得または設定します。 戻り値: コントロールに関するデータを格納している System.Object。既定値は null です。Tag プロパティの型は System.Object なのでどんな型のデータを設定しても良いということです。 つまり、Integer型等の数値だったり、Stringだったり、はたまたクラスでもOKです。
今回の例としては、クラスデータを Tag に設定することを行います。 以下のソースをご覧ください。
1個のフォームの中にクラス宣言を行っています。 そのクラスをフォームロードイベントで、2個のボタンの Tag に別々のクラスデータを設定します。 また、ボタンのクリック時にそのクラスのメソッドを呼び出しています。コントロールのTagプロパティを各種のデータ退避として使用(クラスデータ)
Public Class frmTagTest '''''' テストクラス ''' Class ClsTagTest Private strTest As String '文字列データ Private intTest As Integer '整数データ '''''' コンストラクタ ''' ''' <param name="astrTest">設定文字列</param> ''' <param name="aintTest">設定整数</param> Sub New(ByVal astrTest As String, ByVal aintTest As Integer) '設定値を退避する Me.strTest = astrTest Me.intTest = aintTest End Sub '''''' 表示テストメソッド ''' Public Sub TestDisp() Dim str As String = "strTest : " & Me.strTest & vbCrLf & _ "intTest : " & Me.intTest.ToString MsgBox(str) End Sub End Class '''''' フォームロード時に各ボタンのタグにクラスデータの設定 ''' Private Sub frmTagTest_Load(sender As Object, e As EventArgs) Handles Me.Load '[Button1]のタグにクラスデータ設定 Dim tagTest1 As New ClsTagTest("Test-aaa", 100) Me.Button1.Tag = tagTest1 '[Button2]のタグにクラスデータ設定 Dim tagTest2 As New ClsTagTest("Test-bbb", 200) Me.Button2.Tag = tagTest2 End Sub '''''' ボタンクリックイベント(Handles以降に複数のイベントを記述) ''' Private Sub Button_Click(sender As Object, e As EventArgs) Handles Button1.Click, Button2.Click 'ボタンに設定されたクラスを取得 Dim tagTest As ClsTagTest = DirectCast(sender, Button).Tag 'クラスのメソッドを呼び出す Call tagTest.TestDisp() End Sub End Classこれは初心者の方向けですが、上記のソースの中での注意点としては、 ボタンクリックのイベントを1カ所に集めて処理する様に、 Handles の所で複数のボタンクリック宣言を行っています。
あともう一つ注意点なのですが、Tag プロパティの初期値は null であることです。 何も設定しない状態で Tag を参照しても結果は何も入っていない状態ですので、 プログラム的には IsNothing か何かで判定して処理を分ける必要があります。
関連する記事
⇒コントロールを配列で処理する方法 :[AddHandler,DirectCast]
⇒コレクション「List」をコントロール配列の様に使う方法
PR -
VB.NETの ComboBox には枠線(ボーダー)を表示するプロパティが標準ではありません。
ComboBox の FlatStyle を Flat に設定すると、 枠線が白色になりよく見えなくなります。 そこで、 ComboBox の簡単な拡張クラスをとして枠線の色を追加のプロパティとして作成しました。
クラス名は名前は ComboBoxEx とします。
ウインドウメッセージの処理の中で、 WM_PAINT のメッセージの処理でコンボボックスコントロールの枠を描画します。 枠線を指定する為のプロパティを BorderColor として定義しています。ComboBoxの簡単な拡張クラス
Imports System Imports System.ComponentModel Imports System.Drawing Imports System.Drawing.Drawing2D Imports System.Windows.Forms '''
''' 拡張コンボボックスコントロール ''' '''Public Class ComboBoxEx Inherits System.Windows.Forms.ComboBox Private Const WM_PAINT As Integer = &HF ''' ''' コンストラクタ ''' Sub New() 'ComboBoxのコンストラクタを呼ぶ MyBase.New() End Sub '''''' Windowsメッセージ処理 ''' ''' Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message) Select Case m.Msg Case WM_PAINT 'ペイントイベントでデフォルトの処理をさせる MyBase.WndProc(m) 'その後で強制的に枠描画 Call DrawRectangle() Case Else MyBase.WndProc(m) End Select End Sub '''''' 枠描画関数 ''' '''再定義可能関数 Protected Overridable Sub DrawRectangle() 'グラフィッククラスの参照取得 Dim g As Graphics = Me.CreateGraphics() '枠の四角い領域 Dim rect As Rectangle = Me.ClientRectangle '描画用のペン生成 Dim framePen As New Pen(Me.BorderColor) Try '枠描画 g.DrawRectangle(framePen, rect.X, rect.Y, rect.Width - 1, rect.Height - 1) Catch ex As Exception Finally 'ペンの解放 framePen.Dispose() End Try End Sub 'ボーダー色退避 Private _BorderColor As Color = System.Drawing.SystemColors.ControlText '''''' ボーダー色プロパティ ''' '''Color値 '''Color値 Public Property BorderColor() As Color Get Return Me._BorderColor End Get Set(ByVal value As Color) Me._BorderColor = value End Set End Property End Class
このクラスを clsComboBoxEx.vb の様な名前で保存し、一度コンパイルすると、ツールボックスの中に ComboBoxExが現れるので、それをフォームに貼り付けます。 フォームに張り付けた時のプロパティウインドウに BorderColor があることがわかります。
フォームにComboBoxExを2個貼り付け、それぞれのボーダーを赤と青に設定した例を示します。
関連する記事
⇒コンボボックスの基本的な使い方(項目に文字列のみを設定)
⇒コンボボックスのItemsプロパティにクラスデータを設定する方法(コードと文字列をセットで設定)
-
フォームが閉じる方法としては、自分のプログラムの中で Close を呼出すか、 またはウインドウの右上に表示された「X」をクリックするか、「Alt + F4」を押下するかになります。
この場合にフォームのイベントとしては FormClosing と FormClosed がその順番に発生します。
FormClosing は呼び出された関数の引数として FormClosingEventArgs を持ち、 その中のプロパティである CloseReason を調べることで、閉じられた原因が分かります。
MSDNの説明によれば以下の様になっています。FormClosingEventArgsについて
・CloseReason :フォームの終了理由を示す値 ApplicationExitCall :Application.Exitによる FormOwnerClosing :所有側のフォームが閉じられようとしている MdiFormClosing :MDIの親フォームが閉じられようとしている TaskManagerClosing :タスクマネージャによる UserClosing :ユーザーインターフェイスによる WindowsShutDown :OSのシャットダウンによる None :未知の理由 ・Cancel:イベントをキャンセルする必要があるかどうかを示す値を設定します。 True :フォームを閉じない False :フォームを閉じる
以下のソースは、フォームの中に「ボタンでのクローズ指示フラグ」を宣言し、 ボタン押下時にはそのフラグをONして自分のフォームを Close しています。
フォーム右上「X」を押下したり、「Alt+F4」でウインドウを閉じる時にも フォームFormClosingイベントが発生しますが、ボタンでのクローズなのかを上記のフラグで区別しています。
フォームFormClosingイベントで CloseReason.UserClosing の場合しか処理しない様にしていますので、 その他のシャットダウン時等のクローズでは、素通りとなり、次のフォームFormClosedイベントへと移ります。フォームが閉じるのをキャンセルする方法
Public Class frmClose 'ボタンでのクローズ指示フラグ Private mblnButtonClose As Boolean = False '''''' ボタンクリックイベント ''' Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click Me.mblnButtonClose = True Me.Close() End Sub '''''' フォームFormClosingイベント ''' Private Sub frmClose_FormClosing(sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing If e.CloseReason = CloseReason.UserClosing Then 'ボタンでのクローズかチェック If mblnButtonClose = False Then 'ボタンでは無い場合 Dim strDsp As String = "ウインドウ右上の[X]または[Alt + F4]で閉じようとしています。" _ & vbCrLf & "よろしいですか?" If MsgBox(strDsp, MsgBoxStyle.YesNo, "クローズテスト") = MsgBoxResult.No Then '「いいえ」⇒閉じるのを止める e.Cancel = True End If End If End If End Sub '''''' フォームFormClosedイベント ''' Private Sub frmClose_FormClosed(sender As Object, e As FormClosedEventArgs) Handles Me.FormClosed 'ここで通常はオブジェクトの廃棄等を行う End Sub End Class以下の画像は、フォーム右上「X」を押下した時の様子です。
関連する記事
⇒フォームの位置設定を行う処理 :[Screen.PrimaryScreen.WorkingArea]
⇒フォームクラスにプロパティ宣言し外からアクセスする方法
⇒親フォームのコントロールを子フォームからアクセスする方法
⇒フォームが閉じるのをキャンセルする方法:[FormClosingEventArgs,Cancel]
⇒フォームの表示をモジュールのMain関数から行う(エントリポイントの変更)
⇒フォームがKeyDownなどのキーイベントを受取り、ファンクションキー処理をする
⇒最初のフォームActivatedイベントでの処理(1回のみしか処理しない様にする)
⇒初回のフォームActivatedイベント発生させるフォーム継承について
-
ある親フォームから別の子フォームを表示し、その子フォームから親のフォームのコントロールをアクセスしたい場合があります。 親フォームに公開プロパティ及び公開メソッドを持ち、それを介してデータのやり取りを行います。
以下の例では、親フォームから子フォームを呼出した時に、子フォームから親フォームのテキストボックスの 「Text」を取得し、子フォームのテキストボックスの「Text」に初期設定します。
その後、子フォームのボタンを押下することで、親フォームのテキストボックスの「Text」に 子フォームのテキストボックスの「Text」を再設定します。
以下の画像は、親フォームのテキストボックスに「aaaaa」を入力し、子フォームを表示した子フォームを表示した様子です。その後、子フォームのテキストボックスを「bbbbbbbb」と入力し、子フォームのボタンを押下し親フォームに戻った時を表示した画像です。
以下のソースは、親フォームのクラスの宣言ですが、子フォームから直接テキストボックスにアクセスせずに プロパティを介して行う様にしています。
また、プロパティではなくメソッドからアクセスできる様にもしてあります。 (内容的には自分自身のプロパティを利用してはいますが)親フォームのクラス
'''
''' 子フォームを呼出す親フォーム ''' Public Class frmPropTextMain '''''' TextBox1の「Text」プロパティ ''' '''設定文字列 '''TextBox1の文字列を返す Public Property TextBoxVal As String Set(value As String) Me.TextBox1.Text = value 'TextBox1に設定 End Set Get Return Me.TextBox1.Text 'TextBox1の値を返す End Get End Property '''''' TextBox1への設定メソッド ''' ''' <param name="astrText">設定文字列</param> Public Sub SetTextBox(ByVal astrText As String) '自分のプロパティを利用する Me.TextBoxVal = astrText End Sub '''''' 「サブフォーム表示」ボタンクリックイベント ''' Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click 'プロパティテストウインドウ生成 Dim frmPropSub As New frmPropTextSub(Me) 'ウインドウ表示 frmPropSub.ShowDialog() 'プロパティテストウインドウ廃棄 frmPropSub.Dispose() frmPropSub = Nothing End Sub End Class子フォームの処理は以下の様になります。
子フォームのクラス
'''
''' フォーム生成時にメインフォームが必要な子フォーム ''' Public Class frmPropTextSub 'メインフォームオブジェクト Private mfrmMain As frmPropTextMain '''''' このフォームのコンストラクタ ''' ''' <param name="afrm">メインフォームオブジェクト</param> Sub New(ByVal afrm As frmPropTextMain) ' この呼び出しはデザイナーで必要です。 InitializeComponent() ' InitializeComponent() 呼び出しの後で初期化を追加します。 'メインフォームオブジェクトの退避 Me.mfrmMain = afrm End Sub '''''' フォームロードイベント ''' Private Sub frmPropTextSub_Load(sender As Object, e As EventArgs) Handles Me.Load 'メイン側のプロパティでメイン側のTextBox1の内容を取得し、サブ側に設定 Me.TextBox1.Text = Me.mfrmMain.TextBoxVal End Sub '''''' 「設定(プロパティ)」ボタンクリックイベント ''' Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click 'メイン側のプロパティを使用し、サブのTextBox1の内容を設定 Me.mfrmMain.TextBoxVal = Me.TextBox1.Text '自分を閉じる Me.Close() End Sub '''''' 「設定(メソッド)」ボタンクリックイベント ''' Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click 'メイン側のメソッドを使用し、サブのTextBox1の内容を設定 Me.mfrmMain.SetTextBox(Me.TextBox1.Text) '自分を閉じる Me.Close() End Sub End Classこの子ウインドウのコンストラクタでは、引数の親フォームのオブジェクト参照を プライベート変数に退避しています。 この変数を介して親フォームクラスのプロパティ及び、メソッドにアクセスします。
フォームロード時には親フォームのテキストボックスの内容を、 自分自身のテキストボックスに設定しています。
「設定(プロパティ)」ボタンクリックイベントでは 自分自身のテキストボックスの内容を、親フォームのプロパティに設定し、 それにより親フォームのテキストボックスの内容が変更されます。 「設定(メソッド)」ボタンクリックイベントでは、 親フォームのメソッドを呼び出すことで 親フォームのテキストボックスの内容を変更しています。通常ではコンストラクタを変更することは無いのですが、 コンストラクタに引数を持たせるための方法を説明します。
最初に子フォームのソース上で Sub New と入力した時点で 以下のソースまでは自動で生成されますので、あとは「呼び出しの後で初期化を追加します。」の 後に必要な処理を追加します。Sub New() ' この呼び出しはデザイナーで必要です。 InitializeComponent() ' InitializeComponent() 呼び出しの後で初期化を追加します。 End Sub今回の例ではクラス生成の時の引数として親フォームの参照を渡しますので、 ソースは以下の様になります。
'メインフォームオブジェクト ← ここの変数を追加する Private mfrmMain As frmPropTextMain Sub New(ByVal afrm As frmPropTextMain) ' この呼び出しはデザイナーで必要です。 InitializeComponent() ' InitializeComponent() 呼び出しの後で初期化を追加します。 'メインフォームオブジェクトの退避 ← ここの処理を追加する Me.mfrmMain = afrm End Sub
関連する記事
⇒親フォームのコントロールを子フォームからアクセスする方法その2(DirectCast)
⇒フォームクラスにプロパティ宣言し外からアクセスする方法
⇒フォームがKeyDownなどのキーイベントを受取り、ファンクションキー処理をする
⇒最初のフォームActivatedイベントでの処理(1回のみしか処理しない様にする)
⇒初回のフォームActivatedイベント発生させるフォーム継承について
⇒フォームクラス生成時に設定値を同時に渡す方法
おすすめ本
-
あるフォームから別のフォームを表示し、その子フォームでの情報を親のフォームからアクセスしたい場合に、 子フォームにプロパティを持ち、それを介してデータのやり取りを行います。
以下の例では、親フォーム上のチェックボックスのチェック状態を、子フォームのチェックボックスに設定し、 子フォームを閉じた後で、子フォーム上のチェックボックスのチェック状態を親フォームに再度表示します。
以下の画像は、親のフォームでチェックボックスをONにして、子フォームを表示した様子です。以下のソースは、子フォームの中に「チェック状態プロパティ」を宣言し、 処理的には「チェック状態退避値」に値を設定・取得しています。
フォームロード時に「チェック状態退避値」の値をフォーム上のチェックボックスに設定し、 「終了」ボタン押下時にはチェックボックスの状態を「チェック状態退避値」に退避しています。プロパティを持つ子フォームのクラス
'''
''' プロパティを持つ子フォーム ''' Public Class frmProperty 'チェック状態退避値 Private mblnChkStatus As Boolean = False '''''' チェック状態プロパティ ''' '''チェック状態の設定値 '''チェック状態を返す Public Property ChkStatus As Boolean Set(value As Boolean) mblnChkStatus = value '退避値に設定 End Set Get Return mblnChkStatus '退避値を返す End Get End Property '''''' ボタンクリックイベント ''' Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click 'チェックボックスの状態を退避 Me.mblnChkStatus = Me.CheckBox1.Checked '自分を閉じる Me.Close() End Sub '''''' フォームロードイベント ''' Private Sub fomProperty_Load(sender As Object, e As EventArgs) Handles Me.Load 'チェックボックスの初期状態設定 Me.CheckBox1.Checked = Me.mblnChkStatus End Sub End Classこの子フォームを呼出す親フォームの処理が以下の様になります。
子フォームを呼出す親フォームの処理
'''
''' 子フォームを呼出す親フォーム ''' Public Class frmPropMain '''''' ボタンクリックイベント ''' Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click 'プロパティテストウインドウ生成 Dim frmProp As New frmProperty 'プロパティに自分のチェックボックスの値を設定 frmProp.ChkStatus = Me.CheckBox1.Checked 'ウインドウ表示 frmProp.ShowDialog() 'プロパティ値を自分のチェックボックスの値に設定 Me.CheckBox1.Checked = frmProp.ChkStatus 'プロパティテストウインドウ廃棄 frmProp.Dispose() frmProp = Nothing End Sub End Classボタンクリックイベントでは、子ウインドウのオブジェクトを生成し、 子ウインドウのプロパティに自分自身の上のチェックボックスの状態を設定し、 ダイアログウインドウとして子ウインドウを表示します。
子ウインドウの表示終了後、子ウインドウを廃棄せずにプロパティを取得し、 自分自身の上のチェックボックスの状態に設定し直しています。
ここで重要なのは、子ウインドウのオブジェクトを廃棄する前にプロパティにアクセスすることです。 子ウインドウのオブジェクトを廃棄するとアクセスは不可能になります。関連する記事
⇒フォームの位置設定を行う処理 :[Screen.PrimaryScreen.WorkingArea]
⇒フォームクラスにプロパティ宣言し外からアクセスする方法
⇒親フォームのコントロールを子フォームからアクセスする方法
⇒フォームが閉じるのをキャンセルする方法:[FormClosingEventArgs,Cancel]
⇒フォームの表示をモジュールのMain関数から行う(エントリポイントの変更)
⇒フォームがKeyDownなどのキーイベントを受取り、ファンクションキー処理をする
⇒最初のフォームActivatedイベントでの処理(1回のみしか処理しない様にする)
⇒初回のフォームActivatedイベント発生させるフォーム継承について