10 June 2025

Pointer (1)

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.

04 February 2025

The 'Owned' property



You will have noticed the Owned property in the Properties sidebar for a Form. You might also have noticed that there isn't the same property when editing; the auto-complete box doesn't show an 'Owned' property.
A Form's owner
Whenever a Form is created it can be 'assigned' to another Form. When this happens the Form is said to be owned. Using the OpenW command, you can explicitly specify an owner:
// Create the first unowned form
OpenW 1
// Create the second owned form
OpenW Owner Win_1, # 2, 0, 0

When a Form is created using the Form editor, it is impossible to explicitly specify an owner form. All you can do is set the design-property 'Owned' to True.The effect will be that the Form is assigned to the current Me at the time it is created using the LoadForm command. (If you enable the Owned property for the first form, it will be assigned to Me = Nothing.and the form isn't owned. Since Me might not be exactly what you want it to be, you can explicitly set Me before executing LoadForm.

Owned windows
We mostly speak of owned windows when it concerns top-level windows, windows that are put on the desktop. The relation between a window and a child control is called a parent-child relation, it is not an owner-relationship. This concept can be seen from the properties of child Ocxes; they provide a Parent property, not an Owner property, only Forms have an Owner property.

When there is an owner relationship between two windows the first window (the owner) has certain control over the other window (the owned window). This relationship has several important implications:

  1. The owned window is always displayed on top of its owner window
  2. When the owner window is minimized, the owned window is automatically hidden
  3. When the owner window is restored, its owned windows are shown again
  4. When the owner window is closed, all its owned windows are automatically closed

This relationship is commonly used for dialog boxes that should stay above their parent window, but also for tool windows (or palettes) that should minimize/restore with their main application window. For example, when you open a "Save As" dialog from a text editor, that dialog is typically owned by the main editor window. This ensures the dialog stays above the editor and behaves appropriately when the editor is minimized or closed. There for the Dlg Save & Open command require a Form reference as their first parameter.

This is different from a parent-child window relationship, where child windows are confined within the client area of their parent. Owned windows can be positioned anywhere on the screen while maintaining their behavioral connection to their owner.

Conclusion
You should definitely consider using the Owned design-time property when using the LoadForm command, you get behavioral features for free and the application will certainly look more professional.