一、调用静态方法
1、声明
委托须使用前声明定义,可以带参数(一个或多个),可以有返回值。
'位于一个模块或类的声明部分
Delegate Sub OneArgSub{ByVal msg As String) '带一个参数,且无返回类型
定义了一个委托的类。后台创建了一个名为OneArgSub的新类,这个类是从System.Delegate类继承而来的。(更准确地说从 Systetn.MuhicastDelegate 继承而来的,而 System.MulticastDelegate 则又是从 System.Delegate 继承而来 的。)
Dim deleg As OneArgSub '声明类
deleg = New OneArgSub(AddressOf DisplayMsg) '实例化1:用New
deleg = AddressOf DisplayMsg '实例化2:直接用AddressOf
实例化就是让B与C建立联系,通过AddressOf(提取函数指针)把C方法(或函数)的地址赋予B,所以执行B就是最终执行C.
Private Sub DisplayMsg(ByVal mes As String) '带一个参数,且无返回类型
TextBox1.Text = mes 'DisplayMsg与AddressOf后的签名一致
End Sub
4、执行委托
deleg.Invoke("帮我打官司") '执行委托,参数类型与个数应与声明一致
完整整个委托过程如下:
Public Class frmMain
'位于一个模块或类的声明部分
Private Delegate Sub OneArgSub(ByVal msg As String) '带一个参数,且无返回类型
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim deleg As OneArgSub '声明类
deleg = New OneArgSub(AddressOf DisplayMsg) '实例化1:用New
deleg.Invoke("帮我打官司") '执行委托,参数类型与个数应与声明一致
End Sub
Private Sub DisplayMsg(ByVal mes As String) '带一个参数,且无返回类型
TextBox1.Text = mes 'DisplayMsg与AddressOf后的签名一致
End Sub
End Class
Public Class frmMain
Private Delegate Function AskYesNoQuestion(ByVal msg As String) As Boolean
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim question As AskYesNoQuestion
question = New AskYesNoQuestion(AddressOf MessageDisplayer.AskYesNo) '共享方法地址返回
If question("Do you want to save?") Then '相当于调用类中的共享方法AskYesNo,这里没用invoke
TextBox1.Text = "Saving......"
Else
TextBox1.Text = "Nothing"
End If
End Sub
End Class
Public Class MessageDisplayer
Shared Function AskYesNo(ByVal mes As String) As Boolean '共享方法,通过类名调用
Dim answer As MsgBoxResult
answer = MsgBox(mes, MsgBoxStyle.YesNo Or MsgBoxStyle.Question)
Return (answer = MsgBoxResult.Yes) '回答是时,返回真
End Function
End Class
Invoke对于system . Delegate类和所有从这个类继承得到的类来说都是默认成员;因此,在调用这个函数时可以省略它。最终,通过委托变量调用过程和调用方法看起来差不多:
Public Class frmMain
Private Delegate Function AskYesNoQuestion(ByVal answer As Boolean) As Boolean
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
'首先实例化对象
Dim msgdisp As New MessageDisplayer
msgdisp.MsgText = "对话类要显示的内容"
msgdisp.MsgTitle = "对话类的标题 "
'然后,实例化委托
Dim question As New AskYesNoQuestion(AddressOf msgdisp.AskYesNo)
'执行委托
If question(True) Then
TextBox1.Text = "回答真真的"
Else
TextBox1.Text = "回答是假的"
End If
End Sub
End Class
Public Class MessageDisplayer
Public MsgText As String
Public MsgTitle As String
Function AskYesNo(ByVal DefaultAnser As Boolean) As Boolean '共享方法,通过类名调用
Dim style As MsgBoxStyle
If DefaultAnser Then
style = MsgBoxStyle.DefaultButton1
Else
style = MsgBoxStyle.DefaultButton2
End If
style = style Or MsgBoxStyle.Question Or MsgBoxStyle.YesNo
Return MsgBox(MsgText, style, MsgTitle) = MsgBoxResult.Yes
End Function
End Class
Module Module1
Delegate Sub LogWriter(ByVal Msg As String) '声明委托类型
Dim log As LogWriter '定义委托变量(即上面能带一参的函数)
Dim fw As System.IO.StreamWriter '定义流变量
Sub main()
Dim args() As String = Environment.GetCommandLineArgs '获取命令行参数
If args.Length > 1 Then '如果命令行包含有一个文件名,打开这个文件
fw = New System.IO.StreamWriter(args(1))
log = New LogWriter(AddressOf fw.WriteLine) '1、委托到流输出的WriteLine方法
Else
log = New LogWriter(AddressOf Console.WriteLine) '2、委托到控制台输出
End If
Call DoTheRealJob() '3、子函数中才执行委托函数
If Not (fw Is Nothing) Then fw.Close()
End Sub
Sub DoTheRealJob()
log("Start of program.") '4、这里执行
log("In the middle of the program.")
log("End of program.")
End Sub
End Module
说明:Environment.GetCommandLineArgs 返回包含当前进程的命令行参数的字符串数组。这是什么意思呢?
Declare Function EnumWindows Lib "user32" (ByVal IpEnumFunc As EnumWindows_Callback, ByVal lParam As Integer) As Integer
委托能够有效地用于接收来自从Windows API的回调通知,使之更安全。对上面回调声明委托:
Delegate Function EnumWindows_Callback(ByVal hWnd As Integer, ByVal lParam As Integer) As Integer
然后完善委托的事(方法或函数):
Function EnumWindows_CBK(ByVal hWnd As Integer, ByVal IParam As Integer) As Integer
Console.WriteLine(hWnd) '显示这个顶级窗口的句柄
Return 1 '返回1,继续列举
End Function
最后执行委托即可:EnumWindows(AddressOf EnumWindows_CBK, 0)
Module Module1
Declare Function EnumWindows Lib "user32" (ByVal IpEnumFunc As EnumWindows_Callback, ByVal lParam As Integer) As Integer
Delegate Function EnumWindows_Callback(ByVal hWnd As Integer, ByVal lParam As Integer) As Integer
Sub main()
EnumWindows(AddressOf EnumWindows_CBK, 0)
Console.Read()
End Sub
Function EnumWindows_CBK(ByVal hWnd As Integer, ByVal IParam As Integer) As Integer
Console.WriteLine(hWnd) '显示这个顶级窗口的句柄
Return 1 '返回1,继续列举
End Function
End Module
Module Module1
Delegate Function TraverseDirectoryTree_CBK(ByVal dirName As String) As Boolean
Sub main()
TraverseDirectoryTree("E:\", AddressOf DisplayDirectoryName)
End Sub
Function DisplayDirectoryName(ByVal path As String) As Boolean
Console.WriteLine(path)
If path = "E:\tools\Thunder\Bho" Then '3、一直查到此目录为止
Return True
Else
Return False
End If
End Function
Sub TraverseDirectoryTree(ByVal path As String, ByVal callback As TraverseDirectoryTree_CBK) '1、委托作为参数
Dim dirName As String
Static nestLevel As Integer '嵌套级别
Static isCanceled As Boolean '取消列举时为True
nestLevel += 1 '嵌套层次
For Each dirName In System.IO.Directory.GetDirectories(path)
isCanceled = callback.Invoke(dirName) '2、回调程序执行时返回通知
If isCanceled Then Exit For '4、通知为真(取消列举)则退出循环
TraverseDirectoryTree(dirName, callback) '否则,递归继续列举
Next
nestLevel -= 1 '退出这个嵌套层
If nestLevel = 0 Then '如果准备返回给用户则取消重置
isCanceled = False '否则以下x次调用不能正确工作
End If
End Sub
End Module
说明:1处委托作为参数进入传入,在2处时真正调用委托事项,3处决定委托的状态,4处根据委托的返回值将决定递归是否继续。
Public Class ChildForm
Inherits System.Windows.Forms.Form
Private Sub ChildForm_Load(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load
Text = "Created " & DateTime.Now.ToLongTimeString() '子窗体标题
End Sub
Public Function Repaint(ByVal theColor As Color) As String
BackColor = theColor '子窗体背景色
Text = "Updated " & DateTime.Now.ToLongTimeString() '子窗体刷色时间
Return Me.Text
End Function
Protected Sub ChildForm_Cancel(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Closing
'Tell the main form we are closing, so the main form can 'remove us from its multicast delegate
Dim MyOwner As frmMain = CType(Owner, frmMain)
MyOwner.ChildFormClosing(Me)
End Sub
End Class
Public Class frmMain
Delegate Function MyDelegate(ByVal aColor As Color) As String '1、声明委托类
Private mTheDelegate As MyDelegate '2、定义委托变量
Private Sub btnAddWindow_Click(sender As Object, e As EventArgs) Handles btnAddWindow.Click
Dim aChildForm As New ChildForm()
aChildForm.Owner = Me
aChildForm.DesktopBounds = New Rectangle(800 * Rnd(), 800 * Rnd(), 300 + 200 * Rnd(), 50 + 200 * Rnd())
aChildForm.Show() '建立子窗体并显示
Dim newDelegate As MyDelegate = AddressOf aChildForm.Repaint '3、建立新委托
If mTheDelegate Is Nothing Then '多播委托为空
mTheDelegate = newDelegate
sbStatus.Text = "Created first child form."
Else
mTheDelegate = System.Delegate.Combine(mTheDelegate, newDelegate) '4、不空,则添加
'显示多播委托列表中的个数
sbStatus.Text = "Created child form " & mTheDelegate.GetInvocationList().Length & "."
End If
End Sub
Private Sub btnColor_Click(sender As Object, e As EventArgs) Handles btnColor.Click
If mTheDelegate Is Nothing Then
MsgBox("多播委托列表为空!")
Exit Sub
End If
Dim dlgColor As New ColorDialog()
dlgColor.ShowDialog()
mTheDelegate.Invoke(dlgColor.Color) '6、多播委托执行,全部刷色
sbStatus.Text = "Updated " & mTheDelegate.GetInvocationList().Length & " child form(s).”
End Sub
Public Sub ChildFormClosing(ByVal aChildForm As ChildForm)
Dim unNeededDelegate As MyDelegate = AddressOf aChildForm.Repaint
mTheDelegate = System.Delegate.Remove(mTheDelegate, unNeededDelegate) '7、关闭时,移出这个窗体的委托
If mTheDelegate Is Nothing Then '移出后显示
sbStatus.Text = "Final child form has been closed."
Else
sbStatus.Text = "Child form closed, " & mTheDelegate.GetInvocationList().Length & " form(s) remaining."
End If
End Sub
End Class
说明:重点在主窗体代码中来认识多播委托: