The following information will help you translate Windows SDK call to a PowerBuilder API function call. It doesn't matter whether what version of PowerBuilder is being used.
Step 1: Converting an SDK Call to a PowerBuilder API Call.
First you need to get the syntax that wil be converted. This can be obtained from either a Windows API Bible or the MSDN (Microsoft Developers Network).
Step 2: Determining Whether it is a Function or a Subroutine.
Function calls return a value; subroutines do not.
Here is an example of a Microsoft function:
BOOL GetFileVersionInfo(
LPTSTR lptstrFilename, DWORD dwHandle, DWORD dwLen, LPVOID lpData );
Here is an example of a Microsoft subroutine:
VOID
GlobalMemoryStatus(LPMEMORYSTATUS lpBuffer);
Step 3: Converting the datatypes from Microsoft to PowerBuilder.
| MICROSOFT | PowerBuilder |
| Bool | Boolean |
| Char* | Ref String |
| Colorref | Ulong |
| Dword | Ulong |
| Handle | Ulong |
| Hdc | Ulong |
| Hfile | Ulong |
| Hinstance | Ulong |
| Hwnd | Ulong |
| Int | Int |
| Lparm | Ulong |
| Lpbyte | Ref Long |
| Lpbword | Ref Ulong |
| Lpstr,Lpststr | Ref String |
| Lpfiletime | Ref Time |
| Lpint | Ref Long |
| Lpvoid | Ref Struct struct_inst |
| Mcierror | Long |
| Pbyte | Reg Long[#] |
| Short | Int |
| Structure | Ref Struct Struct_inst |
| Uint | Uint |
| Void** | SUBROUTINE |
| Word | Ulong |
| Wparam | Ulong |
Most of the datatypes are listed above, but some may be missing. When in doubt read the datatype description first.
*If the word "Callback appears as a datatype, it cannot be performed by PowerBuilder. Callback routines are functions that are called from within functions.
Step 4: Coding the Global/Local External Function:
This is a Microsoft function:
BOOL GetFileVersionInfo( LPTSTR
lptstrFilename, DWORD dwHandle, DWORD dwLen, LPVOID lpData );
The BOOL represents a boolean return code, which is translated to "Boolean" in PowerBuilder. A LPCTSTR means a pointer to a string (see step 3). In PowerBuilder, simply use the word "ref" before declaring the string. An LPVOID indicates that a structure is being used. In owerBuilder, create a structure, assign it to an instance variable of that structure and pass it by reference. As a result, the following function declarations can be derived:
PowerBuilder example
FUNCTION boolean GetFileVersionInfoA(ref
string filename, ulong f_handle, ulong f_length, ref lpdata lpdata2) LIBRARY
"version.dll"
Note: In the "gotchas" section listed below, you'll get a further explanation
why an "A" is appended to the 32-bit function. You'll also find a
handy
technique to help you locate function calls within the DLLs.
Step 5: Creating a Structure
In this particular example a structure is needed so you'll need information
on what elements are contained within this structure. The MSDN
provides this
information since the function being called is a Windows function.
In the MSDN the structure appears like this:
LPDATA = { DWORD dwSignature
; DWORD dwStrucVersion ; DWORD dwFileVersionMS ; DWORD dwFileVersionLS ; DWORD
dwProductVersionMS ; DWORD dwProductVersionLS ; DWORD dwFileFlagsMask ;
DWORD dwFileFlags ; DWORD dwFileOS ;
DWORD dwFileType ; DWORD dwFileSubtype
; DWORD dwFileDateMS ; DWORD dwFileDateLS }
In PB you would go into the structure painter and in this particular case all
of these elements would be converted to ULONG. If one of the
elements within
the structure was a nested structure or callback routine you would not be able
to use this function within PB. In that case
the only option would be to
create a C DLL that makes the function call and call it from PB.
Step 6: Scripting the Function Call.
Now that you have the function declaration you need to pass it the proper
arguments. Taking the function " GetFileVersionInfoA" listed in
Step 4 the
following script. would be needed:
First you'll need to declare the datatypes. Keep in mind the variable names do not have to match the function declaration listed in step 4.
boolean lb_rtn // Return code
string ls_filename // 1st argument -
filename
ulong lu_hand // 2nd argument - f_handle
ulong lu_len // 3rd
argument - f_length
lpdata lpdata2 // Last argument - assigning an instance
of a structure.
Next is the hardest part and that is assigning values to the arguments. This
part may require use of the MSDN, API Bible or whatever
reference is
available that covers the function you are calling. In this particular case the
information is contained within the MSDN.
The first argument " ls_filename ", should be set to the path and filename of the target file.
ls_filename = "c:windowscalc.exe" // The calculator would be a good file to test against.
The second argument "lu_hand" according to the MSDN is ignored. This is
probably reserved for a future version of Windows to use. To
be safe the
argument should be set to null.
setnull(lu_hand)
The third argument "lu_len" contains the size of the buffer that the
information will be returned into. It is critical that the buffer size not be
too
small or the information may overflow into another part of memory
causing a GPF or Dr. Watson error. In this particular case since the
structure contains 13 elements that are all ulong, the number 256 should be
sufficient to contain the information.
lu_len = 256
The last argument "lpdata2" is an instance of the structure "lpdata" and it will be populated by the function call.
The final script. will appear as follows:
boolean lb_rtn
string ls_filename
ulong lu_hand, lu_len
lpdata
lpdata2
ls_filename = "c:windowscalc.exe" // The calculator would be a good
file to test against.
setnull(lu_hand)
lu_len = 256
lb_rtn =
GetFileVersionInfoA(ls_filename, lu_hand, lu_len, lpdata2)
// Viewing the output
-------------------------------------------------------------
sle_1.text =
string(lpdata2.dwSignature)
sle_2.text = string(lpdata2.dwStrucVersion)
sle_3.text = string(lpdata2.dwFileVersionMS)
sle_4.text =
string(lpdata2.dwFileVersionLS)
sle_5.text =
string(lpdata2.dwProductVersionMS)
sle_6.text =
string(lpdata2.dwProductVersionLS)
sle_7.text =
string(lpdata2.dwFileFlagsMask)
sle_8.text = string(lpdata2.dwFileFlags)
sle_9.text = string(lpdata2.dwFileOS)
sle_10.text =
string(lpdata2.dwFileType)
sle_11.text = string(lpdata2.dwFileSubtype)
sle_12.text = string(lpdata2.dwFileDateMS)
sle_13.text =
string(lpdata2.dwFileDateLS)
Messagebox("Return Code", string(lb_rtn))
//
-----------------------------------------------------------------------------------------
Gotcha's to look out for:
1. Some functions are cap sensitive.
"Findwindowa" might fail whereas "FindWindowA" works.
2. All handles in
PowerBuilder are ULONG. Using the datatypes INT or LONG may work but if the
handle points
to an area in high memory the latter two datatypes may not be
able to support such a large number.
4. Make sure you have the correct
function name. Under 32 bit many of the functions had an "A" (for Ansi)
Microsoft named the functions this way to differentiate between (A)-Ansi and
(W)-Wide/Unicode format.
MSDN does not always list the proper names for the
functions.
For example: GetFileVersionInfo is listed as a 32 bit function
but it is in fact GetFileVersionInfoA.
5. Global versus Local External
Function declaration.
If the function is declared globally it can be called
from anywhere in your application.
If you declare the function as a Local
External Function it can only be called from that window where it's declared.
Local Functions use less resources than global but the difference is very
minimal.
Error Messages and what they mean:
1. Error: Error opening DLL
library for external function at line in the event of
object
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/32036/viewspace-442589/ ,如需转载,请注明出处,否则将追究法律责任。