イベント

 クラスにイベントを用意すれば、そのオブジェクトを保持している親オブジェクトが、オブジェクトからの信号(イベント)を受信できるようになります。

この身近な例は、フォームやコントロールのイベントです。
各コントロールのイベントプロシージャは、フォームモジュールに記述されますよね。フォームに貼り付けたコントロールは、「フォームオブジェクトの内部オブジェクト」として生成され、親であるフォームがそのイベントをとらえているのです。

今まで、何気なくコントロールを貼り付けて、イベントプロシージャにコードを記述して、とやってきたことですが、実はこのシステムは、VB の仕組みを理解する上で非常に重要です。

実装方法

 イベントの実装方法も簡単で、モジュールの先頭部分(General セクション)に Event ステートメントを指定して実装します。

Option Explicit

Public Event name(argument, ...)

 例として、TV クラスに Change イベントを用意します。
Channel プロパティ(後述)が変更されたときに発生するイベントとします。

Option Explicit

Public Event Change()

この構文で、クラスにイベントが用意されます。

イベントは引数を持つことができますが、戻り値は持ちません。
プロシージャではないので、General セクションに記述します。

また、イベントは“インターフェイス”であることが必須なので、必ず Public で宣言します。


 イベントをとらえるのは親オブジェクトですが、そのイベントを発信するのは、当然、そのイベントを実装しているクラスです。言い換えれば、そのオブジェクトだけが「イベントを発信する権利」を持っています。

    RaiseEvent Change

RaiseEvent ステートメントは、クラス内に存在するイベントを「発信」します。

この命令で発信されたイベントを親オブジェクトが受け取ります。
具体的には、親オブジェクトに記述されたイベントプロシージャが呼び出されます。

ただし、クラスモジュールに実装されたイベントを呼び出す場合は、単純にオブジェクト変数を宣言するだけではイベントを認識できません。


 子オブジェクトのイベントを受け取りたい場合は、親オブジェクトの General セクションに以下のような記述をします。

Option Explicit

Private WithEvents m_MyTV As TV 'イベントを持つクラス TV のオブジェクトを宣言

WithEvents キーワードは、オブジェクトのイベントトラップを有効にする宣言キーワードです。このキーワードは、オブジェクトモジュールのみで記述できます。標準モジュールに記述することはできません。

さらに、モジュールレベルでの宣言で、かつ、「イベントをもつ指定のオブジェクト型」でなければなりません。(プロシージャレベルでの宣言や Object 型としての宣言はできません。)

練習

 では、実際に TV クラスに Change イベントを実装してみましょう。

でも、その前に Channel プロパティが必要です。
クラスにプロパティを実装する方法は覚えていますか?

Option Explicit

'Channelプロパティ
Private m_Channel As Integer 'プロパティ変数
Private Const CHANNEL_MINVALUE As Integer = 1
Private Const CHANNEL_MAXVALUE As Integer = 12

'イベント
Public Event Change()
Public Property Get Channel () As Integer
    
    Channel = m_Channel
    
End Property
Public Property Let Channel (ByVal NewValue As Integer)
    
    If (NewValue >= CHANNEL_MINVALUE) And _
    (NewValue <= CHANNEL_MAXVALUE) Then
        'チャネルが変更されたら、イベントを発信
        If m_Channel <> NewValue Then
            m_Channel = NewValue
            RaiseEvent Change
        End If
    End If
    
End Property

Channel プロパティの値が変更されたときに、Change イベントが発生します。

これを確かめるために、フォームなどに TV オブジェクトを宣言します。

Option Explicit

Private WithEvents m_MyTV As TV
Private Sub Form_Load()
    
    Set m_MyTV = New TV
    
End Sub
Private Sub Form_Unload(Cancel As Integer)
    
    Set m_MyTV = Nothing
    
End Sub

 コードエディタのオブジェクトセクションリストを開くと、m_MyTV が追加されています。

オブジェクトセクションリストを開くと…

m_MyTV を選ぶと、イベントボックスには Change() が選択され、Change イベントプロシージャが記述されるでしょう。

Private Sub m_MyTV_Change()
    
    lblChannel.Caption = m_MyTV.Channel
    
End Sub
Private Sub Form_MouseDown(Button As Integer, Shift As Integer, _
X As Single, Y As Single)
    
    Select Case Button
        Case vbLeftButton
            m_MyTV.Channel = m_MyTV.Channel + 1
        Case vbRightButton
            m_MyTV.Channel = m_MyTV.Channel - 1
    End Select
    
End Sub

ここでは、フォームに貼り付けたラベルにチャネル番号を書くようにしました。

フォームをクリックするとチャネルが変更されます。
すると、TV クラス側からフォームに対してイベントが発信され、処理全体の流れとして「値の変更 → 値の表示」がスムーズに行われます。

まとめ

 このように、クラスモジュールで用意されたオブジェクトに対しても、イベントトラップを実装することができます。この例のように、たとえばイベントの受信からフォームに配置されたピクチャボックスの画像を変更する(TV の電源状態やチャネルに応じた絵を表示する)などの応用例が挙げられます。

イベントの制御はあまり多用することがないかもしれませんが、親子関係のオブジェクトを意識するときは重要なキーワードとなってきますので、仕組みだけは理解しておきましょう。

2000年 7月15日(土) 更新