VB.NET中使用委托(Delegate)来注册回调(callback)函数

前些日子捣鼓了下VFW,里面注册回调(callback)函数是通过sendmessage函数实现的,也就是把回调函数的指针作为参数发送给hWnd即可。折腾了不少时间,下面是代码

这是C/C++代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
typedef struct videohdr_tag {
LPBYTE lpData;
DWORD dwBufferLength;
DWORD dwBytesUsed;
DWORD dwTimeCaptured;
DWORD dwUser;
DWORD dwFlags;
DWORD dwReserved[4];
} VIDEOHDR, *PVIDEOHDR, *LPVIDEOHDR;
#define capSetCallbackOnVideoStream(handle, callback)
(safeSendMessage (handle, WM_CAP_SET_CALLBACK_VIDEOSTREAM, 0, callback))
capSetCallbackOnVideoStream(mhwnd, VideoCallback);
LRESULT CALLBACK VDCaptureDriverVFW::VideoCallback(HWND hwnd, LPVIDEOHDR lpVHdr) {
VDCaptureDriverVFW *pThis = (VDCaptureDriverVFW *)capGetUserData(hwnd);
if (pThis->mpCB && !pThis->mbBlockVideoFrames) {
DO SOMETHING……
}
return 0;
}12345678910111213141516171819202122231234567891011121314151617181920212223

下面是VB.NET的代码,因为.NET里不允许使用指针,就必须使用委托(Delegate)来实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
Structure LPVIDEOHDR
Public lpData As IntPtr 'point to the buffer
Public dwBufferLength As UInt32 'length of buffer
Public dwBytesUsed As UInt32 'buffer's Byte
Public dwTimeCaptured As UInt32 'time:ms
Public dwUser As UInt64 '
Public dwFlags As UInt32 '
Public dwReserved() As UInt64 'Reserved for driver.
Public Sub New(ByVal Size As UShort) '
dwReserved = New UInt64(Size) {}
End Sub
End Structure
Public lpVHdr As LPVIDEOHDR = New LPVIDEOHDR(4)
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (
ByVal hWnd As Integer,
ByVal wMsg As Integer,
ByVal wParam As Integer,
ByVal IParam As callback)
Public Delegate Function callback(ByVal whnd As IntPtr, ByVal lpVhdr As IntPtr)
Dim a1 As callback = Function(ByVal whnd As IntPtr, ByVal lpVhdr As IntPtr)
If count < 30 Then
Clipboard.GetImage.Save("D:\" & count & ".bmp")
count = count + 1
End If
Return True
End Function
Public Function fuckcallback(ByVal whnd As IntPtr, ByVal FramePoint As IntPtr) As Boolean
DO SOMETHING
Return True
End Function
Dim a2 As callback = AddressOf fuckcallback
Private Sub Button4_Click(sender As Object, e As EventArgs) Handles Button4.Click
'SendMessage(hwnd, Cam.WM_CAP_SET_CALLBACK_FRAME, 0, a2)
'SendMessage(hwnd, Cam.WM_CAP_SET_CALLBACK_FRAME, 0, a1)
'SendMessage(hwnd, Cam.WM_CAP_SET_CALLBACK_FRAME, 0, AddressOf fuckcallback)
'上面3个都行
End Sub1234567891011121314151617181920212223242526272829303132333435363738394041424344454612345678910111213141516171819202122232425262728293031323334353637383940414243444546

上面其实是有问题的,排查了半天,才发现是声明委托的时候,漏了函数返回值
Public Delegate Function callback(ByVal whnd As IntPtr, ByVal lpVhdr As IntPtr) 改成
Public Delegate Function callback(ByVal whnd As IntPtr, ByVal lpVhdr As IntPtr) as integer 即可 。

PS:以后可能不会再用VB.NET了,这篇文章算是个End.