A Number object in FFish Script can be passed to a dll function as a parameter of character type, integer type or floating-point number type, or as a pointer to these data types. For instance, the GetSystemMetrics function can be used to retrieve various system metrics (widths and heights of display elements) and system configuration settings:
dllimport "user32.dll" stdcall int GetSystemMetrics(int) as getSysMetrics;
//get the width and height of the screen
var SM_CXSCREEN = 0;
var SM_CYSCREEN = 1;
// A Number object can be passed to a function as an integer parameter
var scr_width = getSysMetrics(SM_CXSCREEN);
var scr_height = getSysMetrics(SM_CYSCREEN);
trace("The width of the screen: ", scr_width);
trace("The height of the screen: ", scr_height);
The Beep function, which can be used to generate simple tones on the speaker
dllimport "kernel32.dll" stdcall Boolean Beep(int, int) as beep; trace(beep(500, 1000));
Calculates the arcsine:
dllimport "msvcrt.dll" cdecl double asin(double); // A Number object can be passed to a function as a floating-point parameter trace(asin(1.0));
A String object in FFish Script can be passed as a parameter of string(char*) type or wide string(short*) type. For instance, finding the task bar:
dllimport "user32.dll" stdcall pointer FindWindowA(String, String) as findWindow;
// To find a window, we need specify the class name or window name
// of the window to find. At here we use the class name of the
// task bar, which is "Shell_TrayWnd".
trace(findWindow("Shell_TrayWnd", null));
where "Shell_TrayWnd" is the class name of the window to find. The second parameter of this
function is the name of window, which can be NULL. The result of this function is the handle of
the found window, which is a pointer. SWFKit Pro always converts pointer results to Numbers,
that is, it will always returns the addresses of the pointers.
The unicode version of the FindWindow function (on Windows NT, 2000 or XP):
dllimport "user32.dll" stdcall pointer FindWindowW(short*, short*) as findWindow;
// A String object can also be passed as a wide string parameter
trace(findWindow("Shell_TrayWnd", null));
As you can see, String objects can be passed as both parameters of string type and parameters of
wide string type.
A Number object can be passed as a pointer to an unspecified type. In this case, the Number object must represent the address the pointer. As we have just discussed in the above part, SWFKit Pro always converts function results of pointer type to Number objects, that is, you can pass these returned Number objects to functions that require pointer parameters. For instance, in the above example, the FindWindow function returns the found window handle, which is a pointer. Now you can use the returned window handle to get the size of the window:
struct
{
int left;
int top;
int right;
int bottom;
} RECT;
dllimport "user32.dll" stdcall pointer FindWindowA(String, String) as findWindow;
dllimport "user32.dll" stdcall Boolean GetWindowRect(pointer, RECT*) as getWinRect;
var handle = findWindow("Shell_TrayWnd", null);
var obj = new Object;
obj.value = new Struct(RECT);
// "handle", a Number object represents the address of a pointer, is
// passed to the "getWinRect" as a pointer parameter.
if (getWinRect(handle, obj))
{
trace("left: ", obj.value.left);
trace("top: ", obj.value.top);
trace("right: ", obj.value.right);
trace("bottom: ", obj.value.bottom);
}
A StringStream object in FFish Script can be passed as a parameter of structure type or as a pointer to any data type. If the data size of the StringStream object is smaller than that of the structure type, the remain data area will be filled with zero. The StringStream object is very useful when the dll functions need allocated data buffers. We will discuss this in more detail in the "passing parameters by reference" part.
A Struct object in FFish Script can be passed as a parameter of structure type or as a pointer to structure type. The "struct" keyword only declares a structure type, you must use the "new Struct(structName);" clause to create a Struct object of that structure type. For instance, confines the cursor to a rectangular area on the screen:
// first we should declare the structure type for the
// "ClipCursor" function
struct
{
int left;
int top;
int right;
int bottom;
} RECT;
dllimport "user32.dll" stdcall Boolean ClipCursor(RECT*) as clipCursor;
// then we should create a Struct object and initialize its members
var rc = new Struct(RECT);
rc.left = 0;
rc.top = 0;
rc.right = 100;
rc.bottom = 100;
clipCursor(rc);
Note: when you assign a FFish Script variable to a member of a structure object, the rule is similar to that of passing parameters to dll functions.
Passing parameters by reference. Generally, SWFKit Pro pass parameters to functions by value. However, many dll functions have out parameters, that is, these parameters will be used for output so that they must be passed by reference. The ffish scripting language does not support to pass parameters by reference directly, so an alternative calling method is introduced into the ffish scripting language to support this feature. The method is to use Object objects to pass parameters to functions. The objects used to do this must have a "value" property, which is the actual variable to pass to the functions. After calling the functions, the "value" property of the objects will contain the new value output by the functions.
For instance, to get the system directory, the GetSystemDirectory function has an output parameter to receive the path of the system directory. In order to get the output value, we must use an Object object to pass parameter by reference:
dllimport "kernel32.dll" stdcall int
GetSystemDirectoryA(char*, int) as getSysDir;
// to get the output value, we must pass parameter by reference
var obj = new Object;
// the "value" property of the obj object must be a buffer whose
// size is big enough to hold the output path name of the system
// directory. To prepare a buffer, the StringStream object is
// recommended. We just need to create a StringStream object and
// set its size to meet our requirement.
var buffer = new StringStream;
buffer.length = 260;
obj.value = buffer;
if (getSysDir(obj, buffer.length) > 0)
{
// if the function call is successful, the value property
// will contain the output value
trace(obj.value);
}
// Of course you can use String object to hold the output value,
// however, it is not as convenient as using the StringStream
// object, because we must initialize the String object to be
// long enough
buffer = new String;
buffer = "aaaaaaaaaaaaaaaaaaaaaaaa" +
"aaaaaaaaaaaaaaaaaaaaaaaaaa" +
"aaaaaaaaaaaaaaaaaaaaaaaaaa" +
"aaaaaaaaaaaaaaaaaaaaaaaaaa" +
"aaaaaaaaaaaaaaaaaaaaaaaaaa" +
"aaaaaaaaaaaaaaaaaaaaaaaaaa";
obj.value = buffer;
if (getSysDir(obj, buffer.length) > 0)
{
trace(obj.value);
}
From the example you may find that the StringStream is suitable for allocate buffers. Although
you can use a very long string object to provide a buffer, it is not so convenient as using
a StringStream object. The "GetWindowRect" example in another part of this tutorial also shows how
to pass a parameter of structure type by reference so that we can get the output coordinations of
the specified window.
Sometimes a member of a structure object may be used to receive output value, for instance, the GetOpenFileName function outputs the file name to the "lpstrFile" member of the "OPENFILENAME" structure. In this case, you must do two things: the first one is to use a StringStream to allocate a buffer to hold the output value, the second one is to use an Object object to pass the parameter by reference since you want to get output value.
struct
{
unsigned int lStructSize;
pointer hwndOwner;
pointer hInstance;
char *lpstrFilter;
char *lpstrCustomFilter;
unsigned int nMaxCustFilter;
unsigned int nFilterIndex;
char *lpstrFile;
unsigned int nMaxFile;
char *lpstrFileTitle;
unsigned int nMaxFileTitle;
char *lpstrInitialDir;
char *lpstrTitle;
unsigned int Flags;
unsigned short nFileOffset;
unsigned short nFileExtension;
char *lpstrDefExt;
pointer lCustData;
pointer lpfnHook;
char *lpTemplateName;
pointer pvReserved;
unsigned int dwReserved;
unsigned int FlagsEx;
} OPENFILENAME;
dllimport "comdlg32.dll" stdcall Boolean
GetOpenFileNameA(OPENFILENAME*) as getOpenFileName;
var ofn = new Struct(OPENFILENAME);
ofn.lStructSize = ofn.structSize;
trace(ofn.lStructSize);
ofn.hwndOwner = getMainWnd().handle;
var filter = new StringStream;
filter.write("All");
filter.put(0);
filter.write("*.*");
filter.put(0);
filter.put(0);
ofn.lpstrFilter = filter;
var buffer = new StringStream;
buffer.write("1.txt");
buffer.length = 260;
trace(buffer.length);
ofn.lpstrFile = buffer;
trace(ofn.lpstrFile);
ofn.nMaxFile = buffer.length;
ofn.nFilterIndex = 0;
ofn.Flags = 0x80000;
var obj = new Object;
obj.value = ofn;
trace(getOpenFileName(obj));
trace(obj.value.lpstrFile);
trace(ofn.lpstrFile);
One more example shows how to list files in "c:"
struct
{
unsigned int dwLowDateTime;
unsigned int dwHighDateTime;
} FILETIME;
struct
{
unsigned int dwFileAttributes;
FILETIME ftCreationTime;
FILETIME ftLastAccessTime;
FILETIME ftLastWriteTime;
unsigned int nFileSizeHigh;
unsigned int nFileSizeLow;
unsigned int dwReserved0;
unsigned int dwReserved1;
char cFileName[260];
char cAlternateFileName[14];
} WIN32_FIND_DATA;
dllimport "kernel32.dll" stdcall pointer
FindFirstFileA(char *, WIN32_FIND_DATA*) as findFirstFile;
dllimport "kernel32.dll" stdcall Boolean
FindNextFileA(pointer, WIN32_FIND_DATA*) as findNextFile;
dllimport "kernel32.dll" stdcall Boolean
FindClose(pointer) as findClose;
var obj = new Object;
obj.value = new Struct(WIN32_FIND_DATA);
var hFind = findFirstFile("c:\\*.*", obj);
if (hFind != 0xFFFFFFFF)
{
do
{
trace(obj.value.cFileName);
trace(obj.value.cAlternateFileName);
} while (findNextFile(hFind, obj))
findClose(hFind);
}
About the return values. If the return values are numbers, they will be converted to Number objects automatically. However, if the return values are pointers, they will be converted to Number objects, even if they are strings, and you would have to use the Dll.getPointerStringValue method to get the value of the string. Finally, if the return values are structures, they will be converted to structure objects automatically. If some members of the returned structures are pointers, they are also converted to numbers, and you would have to use Dll.getPointerXXXValue method to get the values that the pointers point to.