With the Pointer command, Pointer() function, and Pointer type, GFABASIC-32 features a powerful tool. With the Pointer command you can assign a Pointer type variable to a memory address.The Pointer type variable is 32-bits integer variable that stores the address of some memory; it is a memory pointer. To see it in practice look at this code:
Dim i As Int = 9 Dim p As Pointer Int Pointer p = V:i Debug p ' displays 9
The variable p is a pointer to a type Int. From this declaration GB32 knows how to interpret the pointer p; it is pointing to an Int. Initially, the pointer variable p is 0, it is not assigned a memory address yet. You can obtain the memory address it is pointing to with the Pointer() function.
Debug Pointer(p) ' displays 0
To be useful, it must be assigned a memory address and the contents of the memory address is then interpreted as an Int type. To assign a memory address use the Pointer p = addr command. The Debug command shows that p points to the memory address of the integer variable i, because it displays the value of i.
ByRef & Pointer are identical
Because the pointer variable is exactly the same as a ByRef variable, the auto-complete info shows a Ref indication. A by reference variable/parameter is also a (local) variable without an address. When a variable is passed to a ByRef parameter, the address of that variable is assigned to the by reference (pointer) variable. Because the compiler checks for the type of the passed in variable, you cannot assign a random memory address to a by reference parameter. With the Pointer type you can though.
Practical example: ownerdraw
The Pointer type comes to a practical use with Windows system messages that are handled in the MessageProc() event sub.One example is the ownerdrawn message WM_DRAWITEM. Ownerdrawn is used with controls and menu-items, to draw the items yourself. The WM_DRAWITEM specifies a pointer to a DRAWITEMSTRUCT structure in the lParam. In C/C++ this is written as DRAWITEMSTRUCT* or LPDRAWITEMSTRUCT, meaning Long Pointer to DRAWITEMSTRUCT, where the 'Long' is a holdover from the 16-bits days. This description is easily translated to GB32 to declare a pointer variable:
Dim pdi As Pointer To DRAWITEMSTRUCT
Since the DRAWITEMSTRUCT is defined in the Windows winuser.h header file, you can find the GB32 definition in winuser.inc.lg32. which must be included before the structure can be used:
$Library "winuser.inc"
In the MessageProc event sub the WM_DRAWITEM message is used like this:
Sub Win_1_MessageProc(hWnd%, Mess%, wParam%, lParam%, retval%, ValidRet?) Switch Mess% Case WM_DRAWITEM Local pdi As Pointer To DRAWITEMSTRUCT // = null Pointer pdi = lParam% // Do your drawing here retval% = 1 // handled the message ValidRet? = True // retval% is a valid value // other messages EndSwitch EndSub
The local pointer variable pdi is 0 initially. By using the Pointer command the pdi variable is set to the DRAWITEMSTRUCT passed by the system in the lParam%. From that point you can use the pdi variable as any other user-defined variable to get access to a member. For instance, to obtain the device context use pdi.hDC.
If you handled the message, the system must be notified by returning 1, which is the C/C++ value for TRUE. To force GB32 to return the value set in retval% you must set the ValidRet? boolean variable to True.
The next time I will explore the use of Pointer with converting a C/C++ source using pointers.
No comments:
Post a Comment