一、调用静态方法
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 Sub4、执行委托
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 ClassInvoke对于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说明:重点在主窗体代码中来认识多播委托: