A way to work with Visual FoxPro and API Structures

 

© Written by: Emanuele Cerlini

July 2004 - Reproduction Prohibited - Versione italiana

Download: rpstruct.zip (last update: April 18, 2006)

rAPIdStructure is an adapter for API Structures and it requires VFP 7 or greater.

Version 1.10

- Added properties: cExcludeList, lAutoFar
- Added parameter: nMemAddr to WriteMemory()
- Removed the obsolete lAllInCharString parameter of SplitStruct(). It was consequence of a wrong way of declaring certain Dlls.
- Added support for more elements in the same line, for the C structures.
- Fixed bug with arrays of BYTE when lAutoArray = .T., for the C structures.
- Reconsidered the count of bytes for the Bits structures.

  1. Introduction and adaptations
  2. Hints
  3. Properties
  4. Functions
  5. Data Types
  6. Samples

Introduction

Before starting, I would say straightaway that I do not know anything about Visual C++ and practically anything about Visual Basic. The little I know about Visual FoxPro allows me to wonder how comes that we have come by now to version 9.0 and there is no internal function yet that manages the structure of data working with the API functions (Application Programming Interface).
I developed most of the following work by logical deduction – therefore it is largely corrigible and integrable – from the study of documentation, from the examples taken in http://www.news2news.com and from the Struct class by Christof Lange (and Mark Wilden, published in 1999), people I thank. Now I add also William GC Steinford, of whom the work I have seen only after the first publication of this document, and the recent vfp2c32 of Christian Ehlscheid. Not for haughtiness or other demands, but just because I believe that now it is possible to simplify further the interaction of VFP with these structures, I allowed myself to develop a class, entirely in Fox, that I kindly ask you to help me to improve it.
My main idea is to take word for word a definition of structure written in C++ or VB, to transfer it in a Fox variable (or in a memo field), to implement with it a class where the structure members are created as new properties and from here to pass and receive the data from Dlls. Of course also the widest support available is needed: sub-structures, pointers to the memory buffer, arrays of characters, numbers and structures… And perhaps also an utility that copies easily in programming the members of structure… In short, all that is useful to eliminate the uneasiness feeling that may take the user when he looks at the documentation of an API function and finds out that such parameter is a structure.

Perhaps I express myself better with the code of the most banal example:

*!* code for VFP 7.00
Local cMyDef As String, ;
	oStruct As Object, ;
	cSysTime As String 
*!* inizialize
Set Procedure To rpstruct Additive
oStruct=Createobject("rAPIdStructure")
*!* declare function
Declare GetLocalTime In WIN32API ;
	STRING @ lpSystemTime
*!* copy and paste SYSTEMTIME structure from MSDN Help
TEXT to cMyDef NOSHOW
typedef struct _SYSTEMTIME {
	WORD wYear;
	WORD wMonth;
	WORD wDayOfWeek;
	WORD wDay;
	WORD wHour;
	WORD wMinute;
	WORD wSecond;
	WORD wMilliseconds;
} SYSTEMTIME, *PSYSTEMTIME
ENDTEXT
With oStruct
*!* Load it
	.LoadCDef(m.cMyDef)
*!* Build a string
	cSysTime=.MakeStruct()
*!* Call Dll
	GetLocalTime(@cSysTime)
*!* Split the result in members
	.SplitStruct(m.cSysTime)
*!* The result is here
	?"Year", .wYear
	?"Month", .wMonth
	?"Day Of Week", .wDayOfWeek
	?"Day", .wDay
	?"Hour", .wHour
	?"Minute", .wMinute
	?"Second", .wSecond
	?"Milliseconds", .wMilliseconds
*!* Using .ClipMembers() to paste here the members' name
Endwith
Clear Dlls "GetLocalTime"
oStruct=.Null.
*!* end example

Of course it is not always so simple. In particular:

To solve somehow the problem of data types variety, I chose to take an official list from MSDN -> Platform SDK: Win32 API -> Data Types, with some changes. The function DataTypes() returns the list of the data recognized in base to their length in bit (8, 16, 32 and 64), for the C language.
As far as Visual Basic data are concerned, the following are accepted:
BOOLEAN, BYTE, DOUBLE, INTEGER, LONG, STRING, SINGLE

I consider any data not recognized among these, in the 2 languages, as a sub-structure and so it brings about the creation of a rAPIdStructure internal object to load with its own structure definition, if it is not among the ones included in the DataTypes() returned string and they are enabled. If lUnknownAsStruct is.F., instead, the class marks each not recognized data type such as 32 bit number. It is necessary to see the guide of each structure to know which data are therein. It is also possible to use ClipMembers() with the parameters 1, 2 or 3 to know how and which data types have been recognized by the class.

In this case:

typedef struct _SHFILEOPSTRUCT{ 
HWND hwnd;
UINT wFunc;
LPCTSTR pFrom;
LPCTSTR pTo;
FILEOP_FLAGS fFlags;
BOOL fAnyOperationsAborted;
LPVOID hNameMappings;
LPCSTR lpszProgressTitle;
} SHFILEOPSTRUCT, *LPSHFILEOPSTRUCT;

we find the line

FILEOP_FLAGS fFlags; 

where FILEOP_FLAGS is not a sub-structure but just a non-recognized data type whose length is 2 bytes (please refer to Shellapi.h: typedef WORD FILEOP_FLAGS). Therefore, before loading all, let's change that line with this one:

WORD fFlags;

and the problem is resolved.

For pointers in memory, for those regarding text like LPTSTR and LPWSTR (those with STR or CHAR in the end), if lAutoMemory is .T., it can be entered a string in input, obtaining it directly in output. In the other cases input e output are numeric, also in order to the sub-structures in memory, directly managed with the functions WriteMemory(), etc. Also, if lAutoFar = .T., my special support for Windows Sockets Structures exists for reading of CHAR FAR * as LPTSTR and CHAR FAR * FAR * as array of pointers without direct conversion in text (above this last lAutoMemory doesn't affect).

In the following case we have 3 sub-structures FILETIME which are loaded automatically as they have lAllowIntStruct=.T., otherwise they have to be loaded by strucure1.member.LoadCDef (m.cVariableDef), that is to say:

oStruct.ftCreationTime.LoadCDef(m.cFileTime)

where m.cFileTime is a variable containing the definition of FILETIME structure. It will then be possible to access members of sub-structure in this way:

?oStruct.ftCreationTime.dwLowDateTime
typedef struct _WIN32_FIND_DATA {
DWORD dwFileAttributes;
FILETIME ftCreationTime;
FILETIME ftLastAccessTime;
FILETIME ftLastWriteTime;
DWORD nFileSizeHigh;
DWORD nFileSizeLow;
DWORD dwReserved0;
DWORD dwReserved1;
TCHAR cFileName[ MAX_PATH ];
TCHAR cAlternateFileName[ 14 ];
} WIN32_FIND_DATA, *PWIN32_FIND_DATA;

but in this last example we have 2 TCHAR arrays also:

TCHAR cFileName[ MAX_PATH ]; 
TCHAR cAlternateFileName[ 14 ]; 

If they are represented by a constant such as MAX_PATH, it means that in a header file there is:

#define MAX_PATH 260

and so, before loading the structure, we replace that constant manually:

TCHAR cFileName[ 260 ]; 

This topic is valid also for expressions such as (0 to 31): it must be replaced with an unique integer value (32).
Any data type can be represented with arrays, including sub-structures.
For C language, in case lAutoArray is .T., the class treats as ANSI text strings the arrays of BYTE, BCHAR, CHAR, TBYTE, TCHAR, UCHAR; for Unicode text, arrays of WCHAR. For Visual Basic, ANSI text for the arrays of BYTE or STRING; of INTEGER for Unicode. The class doesn't accept arrays with 0 elements.
If these data are not in array format, their numerical value is reported (except for Visual Basic STRING). It exists also the possibility for an API function to call directly an array of data or of structures as parameter: the InitAPIArray() function treats these as if they are a structure with an array composed by a single data type (or sub-structure) and it produces a passable and receivable string for the Dlls.

Going back over the pointers into memory, how previously pointed, there is also the possibility to have sub-structures in a memory block:

typedef struct _JOB_INFO_2 { 
DWORD JobId;
LPTSTR pPrinterName;
LPTSTR pMachineName;
LPTSTR pUserName;
LPTSTR pDocument;
LPTSTR pNotifyName;
LPTSTR pDatatype;
LPTSTR pPrintProcessor;
LPTSTR pParameters;
LPTSTR pDriverName;
LPDEVMODE pDevMode;
LPTSTR pStatus;
PSECURITY_DESCRIPTOR pSecurityDescriptor;
DWORD Status;
DWORD Priority;
DWORD Position;
DWORD StartTime;
DWORD UntilTime;
DWORD TotalPages;
DWORD Size;
SYSTEMTIME Submitted;
DWORD Time;
DWORD PagesPrinted;
} JOB_INFO_2, *PJOB_INFO_2;

here we have two elements that point to one DEVMODE and one SECURITY_DESCRIPTOR (not reported now) in the memory. In order to prepare the main structure we replace the references at the two structures

LPDEVMODE pDevMode;
PSECURITY_DESCRIPTOR pSecurityDescriptor;      

with data type HGLOBAL

HGLOBAL pDevMode;
HGLOBAL pSecurityDescriptor;      

in order to be able to store the numeric value which represents the address into memory. If afterwards, for instance, we wuold also use DEVMODE, we create a separated object rAPIdStructure into which we load and set this last structure, write the string of it, obtained by MakeStruct() into buffer with WriteMemory() and store the result into member .pDevMode. Now the main structure JOB_INFO_2 will use it directly. In order to free the allocated memory it will be necessary to act calling the function FreeMemory() because this doesn't happen automatically. It is needed to set attention to those written in Visual Basic because any, as that of the preceding example, seems to manage the memory handles directly as incorporated structures, while for other, like CHOOSEFONT, they report the data type representing the handle and with which one it is needed to replace the name of the structure: LONG.

Definitions in the preceding structure written in Visual Basic:

pDevMode As DEVMODE 
pSecurityDescriptor As SECURITY_DESCRIPTOR 

correct before the loading into the class:

pDevMode As Long
pSecurityDescriptor As Long

in alternative we could set lUnknownAsStruct to .F., but if we find a medley of sub-structures normally incorporated and other into memory, the manual substitution of the data type before the loading is the only way. I have not found a better way in order to automatize this particularity of the structures, considering the possible variants.

If lAutoUnicodeConv is .T., the conversion of Unicode text strings is automatic.

In case of keyword Union in a structure:

typedef struct _PROCESS_HEAP_ENTRY {
	PVOID lpData;
	DWORD cbData;
 	BYTE cbOverhead;
 	BYTE iRegionIndex;
 	WORD wFlags;
 	union {
	 	struct {
			HANDLE hMem;
		 	DWORD dwReserved[ 3 ];
		} Block;
	 	struct {
			DWORD dwCommittedSize;
			DWORD dwUnCommittedSize;
			LPVOID lpFirstBlock;
			LPVOID lpLastBlock;
		} Region;
	};
} PROCESS_HEAP_ENTRY, *LPPROCESS_HEAP_ENTRY;

We look at the guide to know which part is implemented and, by manual intervention, we remove the non-interesting one:

typedef struct _PROCESS_HEAP_ENTRY {
	PVOID lpData;
DWORD cbData;
BYTE cbOverhead;
BYTE iRegionIndex;
WORD wFlags;
union {
struct {
DWORD dwCommittedSize;
DWORD dwUnCommittedSize;
LPVOID lpFirstBlock;
LPVOID lpLastBlock;
} Region;
};
} PROCESS_HEAP_ENTRY, *LPPROCESS_HEAP_ENTRY;

or we specify the members that must be excluded in the cExcludeList property:

oStruct.cExcludeList="hMem;dwReserved"

Finally it is necessary to notice that, if a structure member corresponds to a property already existing in the class, while loading, a character _ (underscore) will be added at the beginning of the new property. This is the case of RECT structure (or RECTL) having left and top as members:

typedef struct _RECT {
	LONG left;
	LONG top;
	LONG right;
	LONG bottom;
} RECT

In order not to confuse them with the native properties, the new ones will be reported this way in the class:

With oStruct
	._left
	._top
	.right
	.bottom
EndWith

I hope this work will be helpful to somebody. I just remind that this is an adaptation and that, even if it concerns many of the most common structures, it is not possible to demand miracles.

 

Hints

- SET COMPATIBLE must be OFF.
SET FIXED OFF is recommended.

- Check always the final semicolon (;) for the elements of the C++ structures.

- Use rptest_en.prg in order to test quickly the loading of the structures.

Documentation of rAPIdStructure class in rpstruct.prg

For the initialization:

Set Procedure To rpstruct ADDITIVE
oStruct=CreateObject("rAPIdStructure")

PUBLIC PROPERTIES (between brackets the default value)

Properties lAllowIntStruct, lAutoArray, lAutoFar, lBoolNumeric, lSplit64bit and lUnknownAsStruct can be set only before loading a structure definition or before to create an API array.
Classes of the sub-structures inherit the properties settings of the main class.
The properties cDoubleNullList, cExcludeList, nPadding and vStopAt are not hereditary and are applied only to their own structure or to the first level in an array of structures.
It is possible to load just one structure at a time.

cDoubleNullList (="")
Contains the list, semicolon-separated (;), of the members that SplitStruct() must read from the memory as double-Null terminated strings.

cExcludeList (="")
Specifies a semicolon-separated list (;) of the members that are excluded from the structure processing. Expressly for the structures that use "Union" parts.

cStructure (="")
Contains the name of the loaded structure.

lAllowIntStruct (=.T.)
Allows the automatic loading of the internal structures (see DataTypes("IS"))

lAutoArray (=.T.)
Manages the arrays of 8 or 16 bit data automatically as text strings, or, if this property is .F., it considers them as the other arrays reporting the numerical value of each element.

lAutoFar (=.T.)
If it is False (.F.), disables the automatism for the data types CHAR FAR * and CHAR FAR * FAR *, recognizing them as simply pointers.

lAutoMemory (=.T.)
In order to the pointers in memory, if this value is .T., the class allows the automatic reading/writing into buffer with text strings, otherwise the class accepts and returns only numerical values.

lAutoUnicodeConv (=.T.)
If True (.T.), converts automatically the ANSI strings to Unicode and vice versa, in Input and Output.

lBoolNumeric (=.T.)
If True (.T.) indicates that Boolean values are represented as numerical (0 = False, True in the other cases); if False (.F.) the Boolean values are logical (.T. o .F.).

lSplit64bit (=.T.)
Only for C++ language data types. For the 64 bit integer value, if this value is .T., the class creates a sub-structure that separates these in two 32 bit portions. The elements will have the names of LowPart and HighPart. The formula in order to calculate the entire value would be (HighPart * (0xFFFFFFFF + 1)) + LowPart.

lUnknownAsStruct (=.T.)
Manages in automatic way the sub-structures creating for each not recognized data type an object rAPIdStructure. If this value is .F., it recognizes the data type as HGLOBAL (numeric, unsigned, 4 bytes) in order to the definitions in C language, or LONG (numeric, signed, 4 bytes) for those in Visual Basic.

nError (=0)
Contains the internal code in order to the last error occours.
These are the error codes:

0
no error
-11
parameters not correct
-301
structure not loaded
-302
structure already loaded
-303
definition of structure not valid
-304
name of structure is missing
-305
invalid array in structure
-306
no members loaded
-307
invalid data type in a member
-308
error in a structure of secondary level
-309

DLL error reading/writing memory

-310
no pointer stored
-311
member name not existing
-312
invalid member index
-313
the member is not a pointer
-314
the string doesn't have pointer in memory

nPadding (=0)
Adjusts artificially the size of the structure adding the specified number of Null characters. Whether this value is -1, the class adds automatically the necessary characters rounding up the size to the nearest multiple of 4. This setting out is most common for the structures that require it (see also the file correct.rtf).

vStopAt (=0)
Indicates the name (character) or the number (numeric and faster) of the last element to elaborate. It is needed to consider the members that contain arrays or sub-structures as a single element. This support is for the multi-version structures, for example the ones that change their dimension from an operative system to another. The number of element includes also the members that could be listed in cExcludeList.

PUBLIC FUNCTIONS (between brackets the valid parameters)

For all the functions is valid the topic that if the operation succeeds the property nError will have value 0, otherwise it will report the error code.
The functions CalculateBytes(), MakeStruct(), SplitStruct() and, with 0 or 2 as parameter, ClipMembers() have negative result if all the possible sub-structures have not been loaded.

CalculateBytes
Calculates and returns the size, in bytes, of the structure.
If the function fails, the return value is 0.

ClipMembers (nMode)
Utility for developers. It copies to the Clipboard the names of the structure's members, with a dot at the beginning, ready to paste it into a command WITH ... ENDWITH.
In order to the parameter nMode (numeric and optional): if the value is 1, forces the copy of the members also if the sub-structures have not been loaded; if the value is 2, adds a comment to each member with the description of how the class has recognized it, but it doesn't forces the copy; with value 3, forces the copy and adds the comment with the description. Without or with any other value, copies the names of the members, without comments and only if all the sub-structures are correctly loaded.
If the function fails, the return value is .F.

DataTypes (cType)
Returns the list of the data types automatically recognized by the class and of the internal structures. For C language, the list is separated in base to the length in bit of the represented data, passing as parameters 8, 16, 32 or 64; for Visual Basic with "VB" parameter the result will be a single list of the recognized data types. In all the other cases the returned list is that of the internal structures automatically recognized if lAllowIntStruct is .T.
The parameter cType (character or numeric and optional) must contain the indication for the list to obtain. Please, for the complete list of supported data types see at the end of this documentation.

FlagTest (nIntValue, nFlag)
Checks whether one or more flags (bits that are set to 1) exist in a determined field or numeric value and, when succeeding, it returns True (.T.). The function is similar to BITTEST() but it doesn't require the position of the bit to test and it also works with flags composed by more bits.
The parameter nIntValue (numeric) indicates the value that could contain the flags.
The parameter nFlag (numeric) specifies the number composed by one or more flags of which verify the presence in nIntValue (nFlag = 0 returns always .T.).
If the function fails, the return value is .F.

GetPtr (cMemberName, nIndex)
Returns the pointer of a text string from the memory. The function operates only with the members of the class in which it is contained. In base to the last of the two functions already called, the returned pointer is that of the string written by MakeStruct() or that reported by SplitStruct().
The parameter cMemberName (character) must contain the name of the structure member from which has to be returned the pointer.
The parameter nIndex (numeric and optional) specifies the index number of the element in an improbable array of pointers.
If the function fails, the return value is 0.

InitAPIArray (cDataType, nElement, cElementName)
Creates an array for API functions, composed by an unique data type or structure, and processes it like a single structure. If data type is a structure (not internal), it is afterwards necessary to load the definition of the structure into each member of the array. This function respects all the rules of LoadCDef() o LoadVBDef(). Only the data types of C language could be loaded like single.
The parameter cDataType (character) must contain the name of data type or structure to load.
The parameter nElement (numeric and optional) must contain the number of elements for the array. If it is empty, the array will have an unique element.
The parameter cElementName (character and optional) must contain the name of the new property where the class will store the array. If it is empty, the property takes the name of the data type.
If the function fails, the return value is .F.

LoadCDef (cDefStruct, lAnsi2Wide)
Loads a definition of structure written in C++ language.
The parameter cDefStruct (character) must contain the definition.
The parameter lAnsi2Wide (logical and optional), if True (.T.) loads a declared ANSI structure as if it is Unicode (TCHAR->WCHAR, LPTSTR->LPWSTR,...).
If the function fails, the return value is .F.

LoadVBDef (cDefStruct)
Loads a definition of structure written in Visual Basic language.
The parameter cDefStruct (character) must contain the definition.
If the function fails, the return value is .F.

MakeStruct (lAllZero, nLength)
Returns a character string assembling the members of the structure. This string is ready to be passed to the API function.
If lAutoMemory is .T. and a text has been introduced in a member that points to the memory, this function allocates the memory, writing the string. ResetData frees it automatically.
If the parameter lAllZero (logical and optional) is .T., it returns a string of characters Chr(0) without estimating the content of the various members, earning in speed. This string is proper for the API functions that don't require values in input.
The parameter nLength (numeric and optional) indicates the length of the returned string adding characters (Chr(0)) at the end if it is necessary. This is ignored if his value is small than the value returned by CalculateBytes().
If the function fails, the return value is an empty string (="").

ResetClass
Resets the class bringing it back to the initial condition, before loading a definition of structure (but only since VFP 8 it removes the properties added in the class).
This function doesn't modify the setting of cDoubleNullList, cExcludeList, lAllowIntStruct, lAutoArray, lAutoMemory, lBoolNumeric, lSplit64bit, lUnknownAsStruct, nPadding and vStopAt.
If the function fails, the return value is .F.

ResetData
Sets zero the data of the single members carring them to the empty value. It also cleans the memory allocated by the class (not by the API functions), if possible. However, this function is recommended every time that is to be entered in reading or writing to the memory buffer. Destroy Event calls this function if it is necessary.
If the function fails, the return value is .F.

SplitStruct (cCharString)
Redistributes the character string received by the API function in the members of the class. Automatically converts the data in the type requested by their reading.
The parameter cCharString (character) must contain the string of the structure.
(The obsolete parameter lAllInCharString (logical) has been removed).
If the function fails, the return value is .F.

 

Memory management

AllocateMemory (nBytes)
Allocates a number of bytes from the heap and return the handle to the newly allocated memory object. WriteMemory() calls this function automatically.
The parameter nBytes (numeric) specifies the number of bytes to allocate.
If the function fails, the return value is 0.

FreeMemory (nMemHandle)
Frees the specified global memory object.
The parameter nMemHandle (numeric) indicates which is the handle to free.
If the function fails, the return value is .F.

GetMemorySize (nMemHandle)
Retrieves the current size, in bytes, of the specified global memory object, whenever possible.
The parameter nMemHandle (numeric) indicates which is the handle to read.
If the function fails, the return value is 0.

ReadMemory (nMemAddr, nSizeRead, lUnicode, lDoubleNull)
Returns the contents of a pointer into memory as a string.
The parameter nMemAddr (numeric) specifies the pointer to a memory address. If the other parameters are missing, it reads up to the first null character.
The parameter nSizeRead (numeric and optional) specifies the number of bytes to read. If this value is present and greater than 0, the parameters lUnicode and lDoubleNull are ignored.
The parameter lUnicode (logical and optional) if True (.T.) considers the string as Unicode and, if lAutoUnicodeConv is .T., it converts the Unicode text to ANSI.
The parameter lDoubleNull (logical and optional), if True (.T.) specifies that the string to read is the one terminating with a double-Null character instead than one only.
If the function fails, the return value is an empty string (="").

WriteMemory (cMemString)
Writes a string into memory and returns the address.
The parameter cMemString (character), with length better than 0, must contain the string to write. Please, pay attention to the documentation of the structure to know how to terminate the string with the addition of one or more null characters Chr(0).
The parameter nMemAddr (numeric and optional) indicates the memory address in which to write directly. The use this parameter is potentially dangerous for the application. Please, see the command SYS(2600) in Fox Help.
If the function fails, the return value is 0.

 

Numeric conversion
These functions resent of the VFP limits and the values out of range are not verified.

Char2Float (cCharFloat)
Converts a binary character representation to a floating-point (IEEE) number.
The parameter cCharFloat (character) must contain 4 or 8 characters and the decimal places displayed in result are respectively 6 or 15.
If the function fails, the return value is 0.

Char2Num (cCharInt, lSigned)
Converts a binary character representation to an integer value.
The parameter cCharInt (character) specifies the binary character representation to convert.
The parameter lSigned (logical and optional) indicates if the returned number could be negative.
If the function fails, the return value is 0.

Float2Char (nFloat, lDouble)
Converts a floating-point (IEEE) number to a binary character representation.
The parameter nFloat (numeric) specifies the floating-point number to convert.
The parameter lDouble (logical and optional) indicates if the represented result is Float or Double (4 or 8 characters).
If the function fails, the return value is an empty string (="").

Num2Char (nIntValue, nChar)
Converts an integer value to a binary character representation .
The parameter nIntValue (numeric) specifies the integer value to convert.
The parameter nChar (numeric and optional) indicates the length in characters of the returned character string. When it is missing, the resultant string will be long 4 bytes.
If the function fails, the return value is an empty string (="").

 

Supported Data Types by the class (returned by DataTypes())

8 bit C (equal to DataTypes("8") )

BYTE
BCHAR
CHAR
TBYTE
TCHAR
UCHAR

16 bit C (equal to DataTypes("16") )

ATOM
LANGID
SHORT
USHORT
WCHAR
WORD

32 bit C (equal to DataTypes("32") )

BOOL
BOOLEAN
COLORREF
DWORD
DWORD_PTR
DWORD32
FLOAT
HACCEL
HANDLE
HBITMAP
HBRUSH
HCOLORSPACE
HCONV
HCONVLIST
HCURSOR
HDC
HDDEDATA
HDESK
HDROP
HDWP
HENHMETAFILE
HFILE
HFONT
HGDIOBJ
HGLOBAL
HHOOK
HICON
HIMAGELIST
HIMC
HINSTANCE
HKEY
HKL
HLOCAL
HMENU
HMETAFILE
HMODULE
HMONITOR
HPALETTE
HPEN
HRGN
HRSRC
HSZ
HWINSTA
HWND
INT
INT_PTR
INT32
IPADDR
IPMASK
LCID
LCSCSTYPE
LCSGAMUTMATCH
LCTYPE
LONG
LONG_PTR
LONG32
LPARAM
LPBOOL
LPBYTE
LPCOLORREF
LPCSTR
LPCTSTR
LPCVOID
LPCWSTR
LPDWORD
LPHANDLE
LPINT
LPLONG
LPSTR
LPTSTR
LPVOID
LPWORD
LPWSTR
LRESULT
PBOOL
PBOOLEAN
PBYTE
PCHAR
PCSTR
PCTSTR
PCWCH
PCWSTR
PDWORD
PFLOAT
PHANDLE
PHKEY
PINT
PLCID
PLONG
PSHORT
PSTR
PTBYTE
PTCHAR
PTSTR
PUCHAR
PUINT
PULONG
PUSHORT
PVOID
PWCHAR
PWORD
PWSTR
REGSAM
SC_HANDLE
SC_LOCK
SERVICE_STATUS_HANDLE
SIZE_T
SSIZE_T
UINT
UINT_PTR
UINT32
ULONG
ULONG_PTR
ULONG32
USHORT
VOID
WPARAM

64 bit C (equal to DataTypes("64") )

DWORD64
DWORDLONG
INT64
LONG64
LONGLONG
QWORD
UINT64
ULONG64
ULONGLONG

Visual Basic (single list, equal to DataTypes("VB") )

BOOLEAN
BYTE
DOUBLE
INTEGER
LONG
STRING
SINGLE

Internal Structures (inside in the class, equal to DataTypes("IS") or DataTypes(). It is possible to create them directly in the main class passing just the name instead of the complete definition, ignoring the lAllowIntStruct setting)

FILETIME
POINT (or POINTL)
RECT (or RECTL)
SYSTEMTIME

 

Included samples

Simple structures: createprocessVB.prg, ...
Sub-structure: getwindowplacementVB.prg, ...
Pointers into memory: getstartupinfoVB.prg, ...
Constants and non-supported expressions: findfirstfileC.prg, sendmessageVB.scx, ...
Non-recognized data type when it is not a sub-structure: shfileoperationC.prg, ...
64 bit data types: globalmemorystatusexC.prg, ...
Array as text: gettimezoneinformationC.prg, ...
Union: shellexecuteexC.prg
Structures in memory and complex: gethostbynameC.prg, getprinterVB.prg, ...
API array of single data types and structures: polypolygonC.scx, enumprinterdriversC.prg, ...
Array of arrays: devicecapabilitiesC.prg
Members in bits: shgetsettingsC.prg, ...
GetPtr: getopenfilenameC.prg, ...
Double-Null: getprinterdriverC.prg
Multi-version structures: rasgetconnectionstatisticsC.scx, ...

Other examples: faxsenddocumentC.prg, mapisendmailC, setprinterVB.prg, ...

 

"Section for whoever reads the detective story beginning from the last page..."


All brand or product names are trademarks or registered trademarks of their respective holders.

«The class has been tested with Windows XP Professional and Visual FoxPro 8 SP1 (with backward compatibility to VFP 7, recompiling it). Not all the data types, recognized by the class, have been tested.

The class is deprived of each warranty or refund for direct or indirect damages to whoever use it and/or to third users, it is "as-is" and each modification is under exclusive responsibility of whoever operates it.
The class is free and without royalties, it could also be distributed with the code and decompiled.

Be clement with the critics: I abandoned school when I was 16 years old and since around twenty years I've been working with cattle (it is true, not a scarce consideration of my colleagues...) in the nature of the emiliana country.

Thank you for having read up to here and to those people who will make use of my work. You could send bugs (dead or alive) and comments to my e-mail address.

I thank Laura and Sara for this translation (... and myself in order to technical and grammatical errors) »

© Article: Emanuele Cerlini, Sabbione - Reggio Emilia
Breeder, hobby developer

July 2004 - Reproduction Prohibited

Download: rpstruct.zip

 

© FoxPro e Visual FoxPro are registered trademarks of Microsoft Corporation

 



Date: July 30 2004
webmaster@foxitaly.com

 

dal 22 Giugno 1999