Using callback functions in API calls from Visual Basic
Introduction
This page shows how to use a callback function with API calls from Visual Basic.
Example code
The example below detects all available windows on your desktop.
- Using a callback function in API calls:
' Declarations
Private Declare Function EnumWindows Lib "user32.dll" _ (ByVal lpEnumFunc As Long, ByVal lParam As Long) As Long' Main starts the enumeration, pass the address of the callback function
Public Sub Main() Debug.Print "=============================" Debug.Print " Start of enumeration:" If EnumWindows(AddressOf EnumWindows_CallBack, 0) = 0 Then _ Err.Raise 12345, , "Could not enumerate all windows!" Debug.Print "=============================" End Sub' This function is called from the EnumWindows API
Private Function EnumWindows_CallBack(ByVal hWnd As Long, _ ByVal lParam As Long) As Long Debug.Print "hWnd Found: " & hWnd EnumWindows_CallBack = 1' The API ends if we return false
End Function
The EnumWindows() accepts two parameters. The first parameter contains the address of your callback function in the system memory. The second parameter will be passed literally to the lParam variable of the callback function. It can be used to supply a custom value to your function. Only use the specific function declaratin dictated by the API, using a different declaration causes the application to crash.
The Main() function starts the window enumeration, and tells the EnumWindows() API to call the function EnumWindows_CallBack() each time a window is found.
The EnumWindows() API aborts it the callback function returns false.
- Just to let you know...
With an API function, you shouldn't use the keywords True and False. Visual Basic uses the value -1 for true, and 0 for false. API functions expect to receive the value 1 for true, and 0 for false.
Visual Basic magic
Never close the Visual Basic application while a callback function is active. Closing the application removes the callback function from the system memory, but the API function still keeps calling your function again. As a little service, Visual Basic does overwrite the callback function with an empty function returning zero. This prevents a crash in most cases.
Modifying the callback function at run-time also doesn't do much good. Visual Basic stores the modified function at a different memory location, and the callback will fail.
AddressOf trick
The AddressOf operator can only be used in the argument list of a function. There is a little trick to store the address of the function in a variable:
- Storying the AddressOf result:
' Get the value of the AddressOf operator
Public Function GetAddress(AddressOf_FunctionName As Long) As Long GetAddress = AddressOf_FunctionName End Function Public Sub Main() MsgBox "The address of MyFunction is: " _ & GetAddress(AddressOf MyFunction) End Sub Public Function MyFunction() As Long' Statements here...
MyFunction = 0 End Function
blog comments powered by Disqus