Condividi tramite


Accessing Dynamic-Link Libraries

If the functionality you require is available in a DLL, you can link to the library and call its functions. Before calling a DLL function, you must determine its calling protocol, including the name of the function, the number and data types of its parameters, and the data type of its return value.

In Visual FoxPro, you can only use DLLs that have been written for a 32-bit environment. However, if you require access to a 16-bit DLL, you can call it using functions available in Foxtools.fll. For details, see Help for Foxtools (Foxtools.chm).

To call a DLL function

  1. Register the DLL function using the DECLARE - DLL command. Function names are case-sensitive.

    Note   If you specify WIN32API for the library name, Visual FoxPro searches for the 32-bit Windows DLL function in Kernel32.dll, Gdi32.dll, User32.dll, Mpr.dll, and Advapi32.dll.

  2. Call the function as you would any Visual FoxPro function.

For example, the following program registers the GetActiveWindow( ) function from the Windows USER system DLL, which displays the handle of the Visual FoxPro main window. The GetActiveWindow( ) takes no parameters, but returns a single integer:

DECLARE INTEGER GetActiveWindow IN win32api
MESSAGEBOX(STR( GetActiveWindow() ) )

The DLL containing the function you're registering must be available in the default directory, in the Windows or System directories, or along the DOS path.

If the function you want to call has the same name as another function already available in Visual FoxPro (either a native function or a DLL function previously declared), you can assign an alias to the function with the duplicate name, then call it using the alias.

DECLARE INTEGER GetActiveWindow IN win32api AS GetWinHndl
MESSAGEBOX(STR( GetWinHndl() ) )

Linked DLL functions remain available until you quit Visual FoxPro, so you only need to declare them once per session. If you don't intend to call the functions in a DLL again, you can issue the CLEAR DLLS command to remove it from memory and free resources.

Note   Issuing CLEAR DLLS clears all declared DLL functions from memory.

Passing Parameters to a DLL

When you register a DLL function, you must specify the number and data types of its parameters. By default, data is passed by value. You can force a parameter to be passed by reference by including an at sign (@) in front of the parameter.

In general, DLL functions follow the data type conventions used for C, which differ from those used in Visual FoxPro. For example, DLL functions do not support a data type for a date or for currency. If the data you're passing to a DLL function is in a data type not supported by the function, you must convert it to an appropriate type before passing it. For example, you can convert a date to a numeric Julian format using commands such as the following:

cDate = sys(11, date())
nDate = val( cDate )

Some DLL functions require more complex parameters, such as structures or arrays. If the function requires a pointer to a structure, you must determine the layout of the structure, then emulate it as a string in Visual FoxPro before passing it or receiving it from the DLL function. For example, the Windows system function GetSystemTime( ) expects a pointer to a structure consisting of eight words or unsigned 16-bit integers indicating the year, month, day, and so on. The structure is defined this way:

typedef struct _SYSTEMTIME { 
   WORD wYear ;
   WORD wMonth ;
   WORD wDayOfWeek ;
   WORD wDay ;
   WORD wHour ;
   WORD wMinute ;
   WORD wSecond ;
   WORD wMilliseconds ;
} SYSTEMTIME

To pass data between Visual FoxPro and the GetSystemTime( ) function, you must create a 40-byte string buffer (consisting initially of spaces) and then pass the address of this string to the function for it to fill in. When the string is returned, you must parse it in 2-byte increments to extract the individual fields of the structure. The following fragment illustrates how you could extract three of the fields from the structure:

DECLARE INTEGER GetSystemTime IN win32api STRING @
cBuff=SPACE(40)
=GetSystemTime(@cBuff)

tYear = ALLTRIM(STR(ASC(SUBSTR(cBuff,2)) *  ; 
   256 + ASC(SUBSTR(cBuff,1))))
tMonth = ALLTRIM(STR(ASC(SUBSTR(cBuff,4)) * ; 
   256 + ASC(SUBSTR(cBuff,3))))
tDOW = ALLTRIM(STR(ASC(SUBSTR(cBuff,6)) * ; 
   256 + ASC(SUBSTR(cBuff,5))))

For more information, you can examine the sample form Systime.scx in the Visual FoxPro …\Samples\Solution\Winapi directory. For other examples of how to pass parameters to DLL functions, see the program Registry.prg in the Visual FoxPro …\Samples\Classes directory.

If the data you're working with in Visual FoxPro is in an array, you must loop through the array and concatenate it into a single string representing a C-style array before passing it to the DLL function. If the Windows function expects 16-bit or 32-bit values, you must convert the values to their hex equivalents before concatenating them into string. When you pass the string containing the array data, Visual FoxPro passes the address of the string variable to the DLL, which can then manipulate it as an array. For an example of this, see the sample form Syscolor.scx in the Visual FoxPro …\Samples\Solution\Winapi directory.

See Also

Accessing ActiveX Controls and Objects | Accessing a Visual FoxPro Library | Extending Visual FoxPro with External Libraries | Accessing the Visual FoxPro API | DECLARE - DLL | CLEAR DLLS