Visual Basic Concepts

Passing User-Defined Types to a DLL Procedure

Some DLL procedures take user-defined types as arguments. (User-defined types are referred to as "structures" in C and as "records" in Pascal.) As with arrays, you can pass the individual elements of a user-defined type the same way you would pass ordinary numeric or string variables.

You can pass an entire user-defined type as a single argument if you pass it by reference. User-defined types cannot be passed by value. Visual Basic passes the address of the first element, and the rest of the elements of a user-defined type are stored in memory following the first element. Depending on the operating system, there may also be some padding.

For example, several procedures in the operating environment DLLs accept a user-defined type for a rectangle, which has the following structure:

Type RECT
   Left As Long
   Top As Long
   Right As Long
   Bottom As Long
End Type

Two of the procedures that accept a rectangle are DrawFocusRect, which draws a dotted outline around the specified rectangle, and InvertRect, which inverts the colors of the specified rectangle. To use the procedures, place these declarations in the Declarations section of a standard module:

Declare Function DrawFocusRect Lib "User32" Alias _
"DrawFocusRect" (ByVal hdc As Long, _
lpRect As RECT) As Long

Declare Function InvertRect Lib "User32" Alias _
"InvertRect" (ByVal hdc As Long, _
lpRect As RECT) As Long

Dim MouseRect As RECT

Now you can use the following Sub procedures to call the DLLs:

Private Sub Form_MouseDown (Button As Integer, _
Shift As Integer, X As Single, Y As Single)
   ScaleMode = 3
   If Button And 1 Then
      MouseRect.Left = X
      MouseRect.Top = Y
      MouseRect.Right = X
      MouseRect.Bottom = Y
   End If
End Sub

Private Sub Form_MouseUp (Button As Integer, _
Shift As Integer, X As Single, Y As Single)
   ScaleMode = 3
   If Not (Button And 1) Then
      MouseRect.Right = X
      MouseRect.Bottom = Y
      InvertRect hDC, MouseRect
   End If
End Sub

Private Sub Form_MouseMove (Button As Integer, _
Shift As Integer, X As Single, Y As Single)
   ScaleMode = 3
   If Button And 1 Then
      DrawFocusRect hDC, MouseRect
      MouseRect.Right = X
      MouseRect.Bottom = Y
      DrawFocusRect hDC, MouseRect
   End If
End Sub

User-defined types can contain objects, arrays, and BSTR strings, although most DLL procedures that accept user-defined types do not expect them to contain string data. If the string elements are fixed-length strings, they look like null-terminated strings to the DLL and are stored in memory like any other value. Variable-length strings are incorporated in a user-defined type as pointers to string data. Four bytes are required for each variable-length string element.

*Note* When passing a user-defined type that contains binary data to a DLL procedure, store the binary data in a variable of an array of the Byte data type, instead of a String variable. Strings are assumed to contain characters, and binary data may not be properly read in external procedures if passed as a String variable.