(for Internet Explorer)
Class  EventResponders
  Public  Responders

  Private Sub  Class_Initialize()
    ReDim  Responders(-1)
  End Sub

  Public Sub  Add( Func, Object )
    Dim  res : Set res = new EventResponder

    ReDim Preserve  Responders( UBound( Responders ) + 1 )
    Set Responders( UBound( Responders ) ) = res
    res.Func = Func
    res.Object = Object
  End Sub

  Public Sub  Calls( Caller, Args )
    Dim  res

    For Each res  In Responders
      res.Func  res.Object, Caller, Args
    Next
  End Sub
End Class

Class  EventResponder
  Public  Func
  Public  Object
End Class
イベントに応答する方法の1つとして、
すべてのイベントに応答することは、まれなので、メソッドが存在しないというエラーが発生
しないようにすべてのメソッドを記述する必要があるインターフェイスは、扱いづらいもの
です。

継承を使うと(多重継承が使える言語でも)、複数のインスタンスから発生するイベントに
応答することができません。

応答する処理では、アプリケーションのデータが必要になることが多いので、関数では
なくメソッド(オブジェクトをパラメーターに持った関数)をコールバックした方がよいでしょう。

応答するオブジェクトが複数であることは、めずらしくありません。

以上から、イベントに応答するときは、複数の登録されたメソッドを呼び出す機能を持った
EventResponders クラスを使うとよいでしょう。
がありますが、あるクラスの、
参考
→ EventRespondersClass クラス (vbslib)
Dim  ClassA::Delegate as _
 Function ( Caller as ClassA, ... )
Class ClassA
  Public  FuncA_Delegate  ' as Function( Caller as ClassA )

  Private Sub  Class_Initialize()
    Set Me.FuncA_Delegate = GetRef( "DefaultFunction" )
  End Sub
End Class

Sub  DefaultFunction( Caller ) : End Sub
Dim  obj : Set obj = new ClassA
Set obj.FuncA_Delegate = GetRef( "ClassB_funcA" )
obj.Run  '// call ClassA::FuncA_Delegate
Class ClassA
  Public  FuncA_Delegate  ' as Function( Caller as ClassA )

  Public Sub  Run()
    Me.FuncA_Delegate  Me
  End Sub
End Class
FuncA_Delegate
FuncA_Delegate
FuncA_Delegate 変数を宣言しています。
初期値は、通常、何もしない DefaultFunction 関数です。
ClassB_funcA 関数を、FuncA_Delegate 変数に代入しています。
通常、オブジェクトの使用者が代入します。
ClassB_funcA
FuncA_Delegate 変数に登録されている関数を呼び出しています。
通常、メンバー変数が所属するクラスが呼び出します。
DefaultFunction
FuncA_Delegate
FuncA_Delegate
通常、デリゲート(委譲)する関数は複数存在するため、ここで説明する
変数より、インターフェイスの使用を推奨します。
イベントに応答する場合、応答できるオブジェクトが複数になる可能性
があるため、ここで説明する変数より、複数の登録された関数を呼び
出すメンバー変数の使用を推奨します。
参考
参考
ver2 候補
参考
→ デリゲート(C#)
PreField.OnEnevtA
PreField.m_Delegate = PostField
イベントがあったとき
委譲先を生成して双方向参照にする
PostField.OnEventA
同じインターフェイス (ClassI) を持つクラスが複数あるとき、それらのクラスが似ているときは、
共通のクラスに委譲するとよいでしょう。
委譲する(される)2つのオブジェクトの関係は、担当領域(WorkField)を分割しただけのもので
あり、親子関係ではないので、通常、m_Delegate プロパティで、双方向参照できるようにします。
担当領域の分割は、メンバ変数やメンバ関数をどちらのクラスに所属させるかということです。
ただし、複数のオブジェクトが、メンバ変数の値か、メンバ関数ポインタの値か、メソッドポインタ
の値だけ異なるのであれば、クラスは共通の ClassC クラスだけでよく、そのインスタンスを返す
関数を用意してください。委譲する必要はありません。
ClassI
ClassB
ClassI
ClassA
ClassC
m_Delegate
m_Delegate
FuncB
ClassI
ClassI
ClassC : ObjectB
FuncA
ClassC : ObjectA
function pointer
function pointer
m_Delegate
m_Delegate
get_ObjectA()
get_ObjectB()
PreField
PostField
PostField
PreField
new_ClassA
PostField.m_Delegate = PreField
(PreField が処理する)
または
初期化時、または委譲先が必要になったとき
ClassC.Param = "ClassA"
共通クラスのパラメータ設定
メソッド呼び出し、インターフェイス、関数ポインタなど
委譲を使うと、両方のクラスの依存関係が強まり、両方の定義が必要になってしまいます。
あるケースでは片方のクラスだけで十分である場合、冗長であってもメンバ変数やメンバ
関数を両方で持たせます。 また、共通のメンバ変数(ClassC に所属すべき変数)を、
あえて共通ではないクラス(ClassA, ClassB) のメンバ変数にしたりします。 適当なタイミング
で、冗長なデータの同期をとる SyncDelegete 関数を呼び出します。
ClassA
ClassC
m_Name
m_Name
m_LastDate
m_Delegate
←必要な冗長
SyncDelegete
SyncDelegate
冗長なデータの同期をとる
Property  m_Delegate as variant
委譲先が複数あるときは、名前は m_Delegate でなくてもよい
検討中
委譲先となるユーザー定義オブジェクト。
Dim g_g : Sub GetMainSetting( g ) : If not IsEmpty(g_g) Then Set g=g_g : Exit Sub
    Set g=CreateObject("Scripting.Dictionary") : Set g_g=g
    '// または、Set g = new LazyDictionaryClass : Set g_g=g

    '[Setting]
    '==============================================================================
    g("ExeName") = "Sample"
    '// または、g("${ExeName}") = "Sample"
    '==============================================================================
End Sub
Sub GetResetMainSetting( g ) : g_g = Empty : GetMainSetting g : End Sub

Sub  Main()
    GetResetMainSetting  g
    echo  g("ExeName")
    '// または、echo  g("${ExeName}")
End Sub
メイン *.vbs ファイルに記述するユーザー定義データは、GetMainSetting 関数で取得できるようにします。
メインではない *.vbs ファイルは、
に記述してください。
ExeName
Sample
ExeName
UnitTest::Delegate
vbslib の Test.vbs の中では、
ver2 候補
その中で、特に定数は、
で取得できるようにしてください。
定義例、使用例:
new_TestCaseData
などを記述してください。
GetMainSetting が定義されているスクリプトを ExecuteGlobal (vbslib の include、call_vbs など)
すると、GetMainSetting の定義が変わってしまいますが、初めて GetMainSetting を呼んだとき
の定義内容で g が初期化された後は、GetMainSetting を呼んでも g は変わりません。
なので、main 関数の最初で必ず呼び出してください。
Dim g_g : Sub GetMainSetting( g ) : If not IsEmpty(g_g) Then Set g=g_g : Exit Sub
  Set g=CreateObject("Scripting.Dictionary") : Set g_g=g
  call_vbs  SearchParent( "Common.vbs" ), "Common_setVariables", g

  '[Setting]
  '==============================================================================
  g("ExeName") = "Sample"
  '==============================================================================
End Sub
複数のメイン *.vbs ファイルで共通の設定を1つのファイルにまとめるときは、vbslib の
メイン *.vbs ファイル:
Common.vbs ファイル:
Function  Common_setVariables( g )
    g("Config") = "Debug"
End Function
call_vbs
を使ってください。
関連
LazyDictionaryClass
Property Get  ClassA::xml() as string
使用例:
オブジェクトのデータを XML 形式にしたもの。
最後に改行は付きませんが、複数行になることはあります。
  start  CreateFile( "*.xml", obj.xml )
xml
obj の xml プロパティを、テンポラリファイルに出力して開く。
start
CreateFile
obj
オブジェクトのプロパティが多すぎて見にくいときは、xml プロパティとは別のプロパティ
で出力するプロパティを制限するとよいでしょう。
obj.XmlFilter = obj.F_GroupA
定義例
関連
Class  ClassA
    Public  Name ' as string
    Public  DefinePath ' as string

    Public Property Get  xml() : xml=xml_sub(0) : CutLastOf xml,vbCRLF,Empty : End Property
    Public Function  xml_sub( Level )
        xml_sub = GetTab(Level)+ "<"+TypeName(Me)+" Name='"+ XmlAttrA( Name ) + _
            "' DefinePath='"+ XmlAttrA( DefineInfo.FullPath ) +"'/>"+ vbCRLF
    End Function
End Class

Function  GetTab( Level )
    GetTab = String( Level*2, " " )
End Function

Sub  CutLastOf( Str, LastStr )
    Dim  length = Len( LastStr )
    If Right( Str, length ) = LastStr Then _
        Str = Left( Str, Len( Str ) - length )
End Sub
Property Get  xml
ClassA
出力例:
<ClassA Name="Object1" DefinePath="C:\FolderA\File1.txt"/>
関連
→ XmlAttr (vbslib)
→ XmlText (vbslib)
XmlAttrA
Function  ClassA::xml_sub( Level as integer ) as string
Level の値に応じて行頭に空白が付き、最後に改行が付く xml プロパティを返します。
通常、
→ save (IXMLDOMDocument)
の内部で使います。
XML で使える文字に変換してください。
XML タグの属性の値
XML タグの外のテキスト
→ XmlAttrA (vbslib)
  Public Sub  loadXML( XmlObject )
    m_Name  = XmlObject.getAttribute( "name" )
    m_Value = CInt2( XmlObject.getAttribute( "value" ) )
  End Sub
Sub  ClassA::loadXML( XmlObject as IXMLDOMElement )
DOM による XML 要素を使って、オブジェクトの属性値を設定します。
IXMLDOMElement
定義例:
関連
→ new_ObjectFromStream (vbslib)
使用例:
  sample.loadXML  LoadXML( "sample.xml", Empty )
LoadXML
CInt2
name
value
m_Name
m_Value
Option Explicit

Dim  g_SrcPath
Class  Sample_vbs  '// has_interface_of DefineInfoClass
  Public  FullPath
  Public  DataPath
  Private Sub  Class_Initialize()
    FullPath = g_SrcPath
    DataPath = GetAbsPath( "..\Data", g_SrcPath )
  End Sub
End Class
Dim  g_Sample_vbs
Set  g_Sample_vbs =_
   new Sample_vbs

Class  SampleObj
  Public Property Get  DefineInfo() : Set DefineInfo = g_Sample_vbs : End Property
End Class
オブジェクトを定義している
静的オブジェクトを定義している場所や、関連するファイルパスなどを参照します。
DefineInfo というプロパティ名は変えないでください。 DefineInfoClass は、FullPath プロパティ
のみを定義しているインターフェイスです。
関連
Dim  g_SrcPath
Dim  g_Sample_vbs : get_DefineInfoObject  g_Sample_vbs, g_SrcPath

Class  SampleObj
  Public Property Get  DefineInfo() : Set DefineInfo = g_Sample_vbs : End Property
End Class
FullPath プロパティしか無いときは、vbslib を使って下記のように記述することもできます。
get_DefineInfoObject
Property  DefineInfo as DefineInfoClass
一般名が Name プロパティに入っているオブジェクトの DefineInfo は、正式名が Name
プロパティに入っているオブジェクトと同じ内容にします。
定義例:
ClassA
DefineInfoClass
.DefineInfo
.FullPath
string
に関する情報です。
Class  DefineInfoClass  '// defined_as_interface
  Public  FullPath  ' as string
End Class
データ構造
Class  ClassA
  Public  m_DebugMode
  Public  F_BreakAtSetting  '// Const

  Private Sub  Class_Initialize()
    Me.F_BreakAtSetting = 1
  End Sub
End Class

Me.m_DebugMode = Me.F_BreakAtSetting
Dim  ClassA::m_DebugMode  as integer
Dim  ClassA::m_DebugMode_Param1  as string
サンプル:
m_DebugMode から始まるプロパティは、
デバッグ時のブレークポイントやデバッグ出力の有効無効を制御します。
m_DebugMode
ステートメント
Func  param
関数名とパラメータの間は 2つの空白にする。
括弧のために Call を使うと、Call が意味的主役になって混乱するため、使わない。
VBScript のコードを、見やすいコード、必要な情報が表現されているコードにする方法です。
括弧の内側
Array( 1, 2 )
関数名とパラメータの区切りを明確にします。
基本的に空白を入れるが、パラメータの内容が無視できたり、関数とパラメータの
両方で1つのものを表現しているのなら入れなくてよい。例 Hex2Dec("3F")
関数コールの出力変数
Func  param '// [out] param
コメント
'// comment
// は太線の輪郭に相当し、コメントであることを識別しやすくします。
いくつかの文からなる意味的なブロックの先頭行にコメントを書きます。
デバッグするときは、変数値の変化を追うので、出力を明確にします
関数定義の出力変数
Sub  Func( ParamA, out_ParamB, in_out_ParamC )
出力変数は、out_ から始めます。
入出力変数は、in_out_ から始めます。
ローカル変数の大文字小文字
Dim  a, i, long_name
小文字とアンダースコアだけ使えます。
中間的なものなので、なるべく短くします。
関数名と引数の大文字小文字
Sub  Func( ParamA, ParamB )
関数名も引数も、単語の開始は大文字、2文字目以降は小文字にします。
引数も、関数名と同様に意味を明確にすることが重要です。
タブ
タブ文字は使わない。
エディタによってタブ幅が異なるとレイアウトがずれてしまいます。
コーディングルールは、必須にするとろくなことはありません。 必須にしてしまうと、ルールを作った
人の技術レベル(高い低いに関わらず)に引っ張られることになります。 たとえば、MS Office の
Visual Basic Editor の自動整形を使うと、以下のルールで埋めこまれる情報を失い、ソースコードから
必要な情報を得られなくなってしまいます。 逆に、以下のルールも状況によっては(ある標準に準拠
しないとお客が受け入れないなど政治的な理由などでは)自動整形ツールなどを通して、ルールから
外します。
Sub  Func( ParamA, out_ResultDic )
いくつ処理したなど、処理内容の情報は、out_ResultDic という名前の辞書型引数で返す。
情報が不要のときは、呼び出す側で out_ResultDic = Empty を指定します。
  Set out_ResultDic = CreateObject( "Scripting.Dictionary" )
  out_ResultDic.Item( "OutputPath" ) = "file.txt"
報告を行う関数に記述するコードの例:
ActiveX COMオブジェクトを通じてシェルやアプリケーションを操作できます。
COM オブジェクトのインスタンスを返します
エクスプローラの操作
→ VBA
関連
参考
Dim excel
Set excel = WScript.CreateObject("Excel.Application")
excel.Visible = True
excel.SheetsInNewWorkbook = 1
excel.WorkBooks.Add()
新規ワークシートを作成する
Dim excel
Set excel = WScript.CreateObject("Excel.Application")
excel.Visible = True

Dim fs, path
Set fs = WScript.CreateObject( "Scripting.FileSystemObject" )
path = fs.GetAbsolutePathName( "sample.xls" )
excel.WorkBooks.Open( path ) ' フル・パスであること
エクセルのファイルを開く
関連
参考
→ Excel.Application オブジェクト
→ Excel の vbslib
Excel の vbslib を使うと、もっと簡単に記述できます。
Dim  sh_ap
Set  sh_ap = CreateObject( "Shell.Application" )
【引数】
ClassName
返り値
クラス名
ClassName に指定したクラスのインスタンス
Function  CreateObject( ClassName as string ) as variant
サンプル:
COM オブジェクトのインスタンスを返します。
レジストリの、HKEY_CLASSES_ROOT 直下のキーで、CLSID キーを持っている
ものの一部を指定できます。
関連
→ ActiveXObject (JScript)
<job>
<reference object="VisualStudio.DTE.8.0"/>
<script language="VBScript">
Option Explicit

WScript.Echo  vsBuildStateDone
</script>
</job>
sample.wsf
wsf ファイルの reference タグを使うと、COM オブジェクトで定義されている定数を使うことが
できるようになります。
CreateObject("VisualStudio.DTE.8.0") で Visual Studio の COM オブジェクトを取得できるとき、
次のように記述すると、vsBuildStateDone 定数(vsBuildState 列挙体の要素)などが使えるよう
になります。
→ クラスの定数
関連
ただし、wsf は、vbs_inc ほど柔軟に再利用できないので注意してください。
reference の値
<reference object="VisualStudio.DTE.8.0"/>
Visual Studio 2005
Excel
参照
<reference guid="{00020813-0000-0000-C000-000000000046}"/>
デバッガで、オブジェクトをウォッチして、[Method] を展開すると、メソッドの一覧が分かります。