Visual Basic Concepts

Passing Other Types of Information to a DLL Procedure

Visual Basic supports a wide range of data types, some of which may not be supported by the procedures in certain dynamic-link libraries. The following topic describes how to handle some of the special cases you may find when using Visual Basic variables with DLL procedures.

Passing Null Pointers

Some DLL procedures may sometimes expect to receive either a string or a null value as an argument. If you need to pass a null pointer to a string, declare the argument As String and pass the constant vbNullString.

For example, the FindWindow procedure can determine if another application is currently running on your system. It accepts two string arguments, one for the class name of the application, and another for the window title bar caption:

Declare Function FindWindow Lib "user32" Alias _
"FindWindowA" (ByVal lpClassName As String, _
ByVal lpWindowName As String) As Long

Either of these arguments can be passed as a null value. Passing a zero-length string ("") does not work, however, as this passes a pointer to a zero-length string. The value of this pointer will not be zero. You instead need to pass an argument with the true value of zero. The easiest way to do this is by using the constant value vbNullString for the appropriate argument:

hWndExcel = FindWindow(vbNullString, "Microsoft Excel")

Another way to handle this situation is to rewrite the declare to substitute a Long data type for the argument that you want to pass as null, and then call that argument with the value 0&. For example:

Declare Function FindWindowWithNull Lib "user32" -
Alias "FindWindowA" (ByVal lpClassName As Long, _
ByVal lpWindowName As String) As Long

hWndExcel = FindWindow(0&, "Microsoft Excel")

Passing Properties

Properties must be passed by value. If an argument is declared with ByVal, you can pass the property directly. For example, you can determine the dimensions of the screen or printer in pixels with this procedure:

Declare Function GetDeviceCaps Lib "gdi32" Alias _
"GetDeviceCaps" (ByVal hdc As Long, _
ByVal nIndex As Long) As Long

You can also pass the hDC property of a form or the Printer object to this procedure to obtain the number of colors supported by the screen or the currently selected printer. For example:

Private Sub Form_Click ()
Const PLANES = 14, BITS = 12
   Print "Screen colors ";
   Print GetDeviceCaps(hDC, PLANES)* 2 ^ _
   GetDeviceCaps(hDC, BITS)
   Print "Printer colors ";
   Print GetDeviceCaps(Printer.hDC, PLANES) * _
   2 ^ GetDeviceCaps(Printer.hDC, BITS)
End Sub

To pass a property by reference, you must use an intermediate variable. For example, suppose you want to use the GetWindowsDirectory procedure to set the Path property of a file list box control. This example will not work:

ReturnLength = GetWindowsDirectory(File1.Path,_
Len(File1.Path))

Instead, use the following code to set the property:

Dim Temp As String, ReturnLength As Integer
Temp = String(255, 0)
ReturnLength = GetWindowsDirectory(Temp, Len(Temp))
Temp = Left(Temp, ReturnLength)
File1.Path = Temp

Use this technique with numeric properties if you want to pass them to DLL procedures that accept arguments by reference.

Using Handles with DLLs

A handle is a unique Long value defined by the operating environment. It is used to refer to objects such as forms or controls. The operating environment DLL procedures make extensive use of handles — handles to windows (hWnd), handles to device contexts (hDC), and so on. When a procedure takes a handle as an argument, always declare it as a ByVal Long. DLL functions that return a handle can be declared as Long functions. Handles are identifier (ID) numbers, not pointers or numeric values; never attempt mathematical operations on them.

The hWnd property of forms and nongraphical controls and the hDC property of forms and picture box controls supply valid handles that you can pass to DLL procedures. Like any other property passed to a DLL procedure, they can be passed only by value.

Passing Variants

Passing an argument of type Variant is similar to passing any other argument type, as long as the DLL procedure uses the Automation VARIANT data structure to access the argument data. To pass Variant data to a argument that is not a Variant type, pass the Variant data ByVal.