25 April 2021

The gfawinx library

It’s been a while since GFA Software Technologies GmbH released GFA-BASIC 32. At that time (2001) it could not be foreseen how Windows - and PC-use in general - would evolve. Consequently, GB32 misses runtime functions to coop with the latest Windows developments and the introduction of better hardware. To fill that gap gfawinx.lg32 comes with a set of commands and functions to access and use the newer features. The name gfawinx stands for “GFA-BASIC 32 expansion” library, gfawinx contains several categories. When you load the gfawinx.g32 code file in the editor the Procs sidebar shows the current groups:

Screenshot 2021-04-23 112115

Download latest version
Previous gfawinx versions – until and including the version of 16 Feb 2021 - contain an error that may lead to problems when loading the library into a program. If you are planning to use gfawinx make sure you have a version later than 16 Feb 2021. Please check the date of the file in the Include directory.

Download a newer version if necessary here and unzip the file to the Include directory.

What’s the problem? One of the library functions uses a DLL function declared using the Declare command. However, when a lg32 library uses a declared function it must also export that DLL function using an $Export Decl command.The program that is importing the library must be able to add that declared function to the program’s table of DLL functions. Gfawinx used a declared function, but did not export it. The current version of gfawinx doesn’t use Declare anymore, but uses GetProcAddress() to obtain the function’s address and calls it using StdCall()(). Something to remember when you are developing your own libraries.

The String functions
The Wide and Ansi functions are mainly used with Windows API functions that take a UNICODE string. An example of both functions was discussed in Task Dialog as a replacement for Alert, which demonstrates the use of a Windows API taking UNICODE strings as parameters. This blog post also contained an example of StrToArr, which is used to convert a string, containing sub-strings separated with any character, to an array. StrToArr is an addition or replacement for the Array ar$() = $ command.
The Replace string function is a VB(A) compatible function, much easier to use then the Split command of GB32. The Replace function is optimized for speed and takes the string arguments by reference if the arguments are string variables. Only in case a string literal is passed GB32 will pass the string parameter by value (making a copy first and then pass that copy). This is achieved by making Replace a FunctionVar rather than a Function.

FunctionVar and Sub anonymous String and Variant parameters
When a parameter of a FunctionVar or Sub does not explicitly specify ByVal or ByRef the parameter is anonymous. In this case the compiler decides how to pass the parameter to the FunnctionVar or Sub. If possible, the compiler generates code to pass the String or Variant by reference, otherwise the parameter is passed by value. To be able to pass by reference the caller must pass a variable; a literal is always copied to a temporary locally variable which is then passed by reference. Note that a ByVal parameter always gets a copy of the data that is passed, which requires the compiler to insert additional code to create a copy first. Passing by reference is almost always faster. Using anonymous parameters can speed up the execution of a procedure or function considerably.

An example that shows the difference:

$Library "gfawinx"
Dim src$, find$, new$, result$
result$ = Replace(src$, find$, new$)     ' variables, fast
result$ = Replace("GFA-BASIC", "A", "x") ' literals, slower

ErrStr is a convenient function to obtain the relevant Err-properties as a string. Usually, ErrStr will be used in a Try/Catch handler to present information about the trapped error to the user. The problem is to decide which Err-properties contain the relevant error information. ErrStr examines the properties and only returns the properties that contain the actual error information. ErrStr takes one string parameter that is added to the error information. This parameter is perfectly suited for the current proc-name, which is easily inserted using the keyboard short cut App+P. Here App+P inserts “main” into text:

$Library "gfawinx"Screenshot 2021-04-23 131437
  Error 3
  MsgBox ErrStr("main")

The program produces the following message box:

The $ = HexDump(addr%, size%) string function returns a memory dump starting from the specified address addr% and with a length of size%. The result of this debugging aid can easily be displayed in the Debug Output window or a MsgBox.

The Windows functions
Here we find the Windows API and form-windows related commands and functions. Let’s first examine the WinVer function which returns the Windows OS version. In the latest version of gfawinx it returns the value obtained using the RtlGetVersion() API in a hexadecimal format $XXYY, where XX represents the major version and YY the minor version:

$Library "gfawinx"
Print Hex(WinVer())  // A00 (Win 10)

There is a lot of information to be found on how to obtain the Windows version. The method used by WinVer() does not depend on the manifest file as other methods do and should be safe to use with future releases of Windows. (Note - only the latest version of gfawinx - later than 16 Feb 2021- contains this method.)

GetWorkArea is a useful command when using multiple monitors where the Screen.Work* properties don’t work. GetWorkArea returns the work area of the monitor containing the largest area of a given window.
GetProcAddr returns the address of a function from a specified DLL. It works a little different than the GetProcAddress() API, because it first checks if the required DLL is already loaded.
The GetClientSize command returns the size of the client area, useful if _X and _Y are not available (in API windows).
ModifyStyle and ModifyExStyle make it easy to change the windows Style or ExStyle on the fly. They allow to both set and remove a windows-style simultaneously.
The Assoc() function returns system information associated with files, extensions or Prog IDs. For instance to obtain the full path of the default application that is associated with the .txt extension use:

$Library "gfawinx"
Print Assoc(".txt") // full path of default app

SaveFormPos and LoadFormPos save and load the form’s position respectively. For single monitor apps these are simple functions to store and retrieve the form’s current position in and from the registry. They are especially useful when used with multiple displays and DPI-aware applications. For detailed information see the help file.
MemStat is is a helper function to obtain memory statistics. If the argument is omitted (or is 0) it returns the memory used by the application. It is possible to trap a possible memory leak by using MemStat() when the program starts and compare the returned values at each start of the program.

The DPI-related functions
When you want to write DPI-aware applications these helper functions will be very useful. For more information on writing DPI-aware programs please see the English CHM helpfile: in the Contents section see Creating an application. Programming DPI aware programs is beyond the scope of this blog post. The gfawinx library provides the following functions.

WinDpi returns the DPI of the display for a window or form.
DpiAwareness set the DPI mode for the program.
ScaleToDpi(Sng) helps to scale coordinates.
ScaleXYWHToDpi scales ScaleLeft, ScaleTop, ScaleWidth, and ScaleHeight to a form's DPI.

The TimerQ function
The TimerQ function creates a high-resolution timer wrapped in a (minimal) COM object. This is the gfawinx implementation of the discussion in the blog High Resolution Timer . By using a COM object for a resource it can be guaranteed that the resource is freed when the program ends – either normally or through a runtime error.

The gfawinx library provides functions and commands that are not included in the GB32 runtime. The commands and functions are displayed in the GB32 syntax color for statements and GB32 functions. The procedures that implement the additions are optimized for speed, when possible the procedures are Naked. It is recommended that you – sometime - take a look at the code, it contains comments on implementation details you might find interesting. The library will grow over time when more ‘missing’ features will be added.

23 March 2021

Update version 2.59


After releasing update version 2.59 on 18 March 2021 a new version was released at 22 March 2021. To check if you have installed the latest release select the About-box in the menu-item Help | About and look at the version of GfaWin32.gll; it should be version 2.590.

A new update is necessary because it fixes two major bugs in the runtime. After the last update (version 2.58 in December 2020) I found the time to investigate and fix a long-standing bug where the Ocx Form child control crashes the IDE. While fixing the bug I stumbled upon another runtime bug: the Item property of the Controls collection did not work and could crash the IDE as well. Besides these fixes, version 2.59 improves auto-complete and comes with an update of the Direct2D library.
The rest of the blog explains the runtime bugs and introduces Direct2D version 1.1.

About the fixed runtime bugs
The Ocx Form-control-bug presented itself as a crash of the IDE after one or two times running the program. For a long time, it was unclear what caused the bug. If a form contained an Ocx Form child control the program executed fine unless the Ocx Form child control was assigned to Me, or when the program iterated over the form’s controls using For Each ctrl in Form.Controls, or when the Ocx Form was used in a With statement. There were other symptoms of the bug, for instance setting the Ocx Form’ s scrollbar properties might cause a floating-point stack error. In the end it turned out that the bug was caused by the runtime when it wrongly released the Ocx Form (COM) object prematurely.

After a COM object is assigned to another object (variable) the reference count of the COM object is increased. When a COM object is set to Nothing the reference count is decreased. When the reference count is zero all resources of the COM object are freed and the variable referencing the object becomes Nothing. However, when the Ocx Form child control is referenced twice or more and is then released, the object’s underlying resources are completely freed as if the the reference count has become zero. The next time the Ocx Form object is released (for instance automatically at the end of the program) it’s resources are already freed and memory pointers have become invalid resulting in access violation errors in the runtime. GB32 tried to recover from these corrupted pointers but could not prevent an IDE crash.

As you can see, the symptoms of the Ocx Form bug were an indication of this wrong behavior. When assigning the Ocx Form frx to Me, both frx and Me reference the Ocx Form and more than one reference to the Ocx Form would eventually crash the IDE. Before knowing the cause of the bug I advised not to assign an Ocx Form to Me, now it can be done without any problem.

OpenW 1
Ocx Form frx = "", 10, 10, _X - 20, _Y - 20
Set Me = frx    ' OK now

The same problem occurred with With frx. With creates a hidden temporary object variable to which frx is assigned. So, after executing With, two object variables reference the Ocx Form frx. EndWith will release the hidden variable by setting the hidden variable to Nothing, which – with the bug present - would destroy the frx object completely, but not anymore.

With frx        ' assigns frx to a hidden local object variable
  ' use properties and methods
EndWith         ' releases the hidden variable

The For Each loop mentioned before shows the same behavior:

Local Control ctrl
For Each ctrl In Win_1.Controls
  ' use Control properties/methods

Each iteration assigns a new Ocx child control object to the ctrl variable. In the process the object that is currently assigned to ctrl is released (set to Nothing). When ctrl is assigned the Ocx Form child control the next iteration will release ctrl and thus release the Ocx Form object. Due to the bug all it’s resources are freed. As said, this is now fixed in runtime (GfaWin23.ocx) version 2.38.

While investigating the Ocx Form bug I stumbled upon two other bugs, which are fixed also. First, autocomplete didn’t show the properties for Win_1.Controls and secondly, the Item property of the Controls collection failed.

Local Control ctrl
Set ctrl = Win_1.Controls.Item(1) ' OK now 

The Direct2D library version 1.1
The new Direct2D library contains several new commands and functions. The purpose of this release was to fill the gaps that were left by the previous version. Therefor, the following commands are extended to provide the same functionality as the GFA-BASIC 32 built-in drawing commands. The D2 circle and ellipse commands now support arc- and pie drawing, which required a new syntax:

D2(P)Circle x!, y!, r! [, w1%][, w2%][, Figure%] [,D2Brush] 
D2(P)Ellipse x!, y!, rx!, ry! [, w1%][, w2%][, Figure%] [,D2Brush]

The library supports the polygon commands in the same manner as the GB32 commands D2PolyLine and D2PolyFill draw a polygon directly into the render target. There is also a D2DefPoly() function to create and cache a polygon to be drawn later on when the render target is updated. The implementation of the polygon commands required the Direct2D geometries. There is whole set of commands and functions to create and draw into a geometry. Check out the help file and the examples in Samples\Direct2D directory. Many D2 help file topics contain a link to the Microsoft online SDK for further information on Direct2D issues. The examples directory also contains two SDK examples converted to GB32; D2ClockSDK.g32 and D2PathGeometry.g32.

In addition, it is important to know that the D2GetRT() syntax has changed. It won’t be noticeable if you use the default settings: Set RT = D2GetRT(), which creates a DC-render target. However, when you do use arguments, for instance to create a window render target, you need to update your code. See the help file for more information on the syntax.

This isn’t the latest Direct2D update, I will continue to work on the Direct2D library. Regularly check this site for more information.

23 February 2021

The Include directory

After installing GFA-BASIC 32 you’ll find four directories in the installation path: Bin, Doc, Include, and Samples.


The \Bin directory contains the GB32 binaries, the \Doc contains the original (German) doc-files that came with GFA-BASIC 32 back in 2001 (now obsolete because everything can be found in the English CHM helpfile), the \Include contains the Windows API include files, and the \Samples directory the samples g32 files, including the new Direct2D example programs.This time we’ll focus on the \Include directory only.

What is the \Include directory for?
The purpose of the \Include directory is to collect all Windows API definitions and declarations in one directory. Because of the huge amount of Windows APIs the definitions and declarations are split into multiple smaller include library files. These GB32 Windows API include-files come both with the source code and the compiled library (lg32) file. The organization of the GB32 include files follows the way the Windows SDK presents the C/C++ include header files. For instance, the C/C++ header file winuser.h has an equivalent GB32 include file winuser.inc.lg32. All include files follow this naming convention: name.inc.lg32.
You import a GB32 include library file using the $Library command, for instance:

$Library "winuser.inc"  ' .lg32 may be omitted

By default, the line doesn’t need to specify the full path, because the location of the \Include directory is pre-selected in the Properties | Extra tab dialog box.


You can easily add your own paths that contain your own library files. The entire string with the specified paths is stored in “lg32paths”registry key. To add a path first type a semicolon ; after the existing path and then specify the full path after the semicolon. Once a path is part of Library paths you do no longer need to type the full path in the $Library statement. Note that libraries are searched for (1) in the current program's directory, (2) in My Documents\lg32, and (3) in the paths stored in the registry key "lg32paths".

Note The \Include directory also contains the libraries gfawinx.lg32, direct2d.lg32 and variants.lg32. These are not include files and don’t have the .inc clause in their names. These are libraries that are part of the GFA-BASIC 32 updates and need an easily accessible path.

Why multiple include files?
Each include file contains only a part of the Windows API, that way you don’t need to include a single large file with many APIs just to have a few declarations. The GB32 include files only provide the APIs that are not built-in by GFA-BASIC32. (Note that the Win32API.g32 that originally came with GB is incomplete and full of errors.) Due to the amount of new APIs that come with each new Windows version, the include files in the \Include files aren’t complete either. They do however provide more declarations and definitions than the original Win32API.g32. Some of the include files are updated with the latest APIs (most specifically APIs supported by Win7 and Windows 10) like, for instance, winuser.inc.lg32. However, many haven’t been updated for a while. They tend to get an update on a ad hoc basis; when I need new APIs I add them to the include files. It is a boring job and, because of the translation from C/C++, errors are easily made. If you need an API that isn’t in one of the include library files yet, let me know (gfabasic32@gmail.com).

Contents of an include library
By default, the GB32 Windows include files only provide function declarations (Declare statements), constant definitions, and user-defined type definitions. They don’t contain executable code and besides the Declare’s they do not contribute to the size of the program. You should know that Declare-ed DLL functions are collected in a DLL-import table that do become part of the program (executable). By spreading the Declare’s over multiple include files the DLL-import table can remain small.
There is one “include” file that does contain executable code: winmacros.lib.lg32 (note the lacking .inc clause in the name). This library contains functions for often used Windows macros that are used as functions in C/C++, but are defined as macros in the C/C++ header files. Some of these function macros are collected into winmacros.lib.lg32. Among others, the library provides (Naked) functions for GET_X_PARAM, GET_Y_PARAM, MakeLParam, MakeIntResource, etc. Please take a look at the source code in winmacros.lib.g32 for an overview of the supported functions/macros.

How to locate a specific API
How do you know in which include file a specific API (type, constant, or function) is located? It might be that GB32 already supports the API as a built-in API, only function declarations and constant definitions. GB32 does not have built-in API support for user-defined API type definitions, they always have to be defined by the program or imported from an include library. The easiest way to check if GB32 supports a specific API is by using the auto-complete feature. Just type the first letters of the function or constant and check if the auto-complete pops up with the required name. If it isn’t provided by GB32 you’ll need to check the Windows SDK documentation to see which C/C++ include file provides the declaration or definition for that API and load the equivalent GB32 .inc library file.

An example of using an API
Each topic in the Windows SDK specifies in which C/C++ header file an API function, type, or constant is declared. For instance, if and API is located in the winuser.h C/C++ header file you have a big chance of finding it in the winuser.inc.lg32 file. Let’s look at an example. Suppose your program wants to process the WM_GETMINMAXINFO message. After looking up the documentation for this message, it tells you to obtain the  MINMAXINFO structure from the lParam. However, GB32 itself does not provide a definition for the MINMAXINFO user-defined type, and you need to import the type. When you go to the SDK page that describes this type you’ll find at the bottom of the page the location of the definition of this structure: the winuser.h C/C++ header file. Now you know which GB32 include library you need: winuser.inc and the program can import that library. As it happens this structure contains members of the API type POINT, which is defined in wingdi.inc. However, you won’t need to include wingdi.inc in your program, because it is imported by winuser.inc (otherwise it couldn’t be compiled). After importing winuser.inc in your program the constants and user-defined types from wingdi.inc are available as well. So, the POINT structure is available as a user-defined type in your program.

Note winuser.inc exports the constants and type definitions of wingdi.inc, but not the function declarations. If you need an API function declared in wingdi.inc you’ll need to import wingdi.inc as well. Importing both include files won’t collide with each other.

$Library "winuser.inc"
$Library "wingdi.inc"

Although both include files export the same constants and user-defined types they are added only once to the program. Now if winuser.inc would also export the function declares from wingdi.inc the internal database of GB32 may become corrupted. Therefor, winuser.inc exports all constants and types using the $Export Const * and $Export Type * statements, but the exported $Export Decl name statements must specify each exported declare separately. This is easily done using the App+E shortcut, it inserts $Export Decl lines for each Declare in the library file.

You can use the Windows API inc files to import Windows APIs easily. Because the (compiled) user-defined types are imported from a library the autocomplete function has direct access to their members and is fully operational without first compiling your program.

10 December 2020

Version 2.58 December 2020 Update

A new version of GFABASIC 32 is available now. It has a better auto complete that comes with a little help box for the listbox elements. In addition, version 2.58 has support for Direct2D, for developing multiple monitor applications, and comes with a new gfawinx library with new commands and functions. James Gaite did a good job by making the English CHM helpfile up-to-date with the latest information.

Auto complete
Version 2.58 improves on auto complete by doing a better job in showing relevant elements and by providing a little help box.

This (optional) help for auto complete displays the syntax and a small description of the GFABASIC 32 commands and functions. The syntax is also copied to the statusbar and remains visible to help in using the correct syntax even after the auto complete listbox has disappeared. The help is also displayed for the program’s procedures and functions, the lg32 procedures and functions, and the declared DLL functions. Their prototypes are both visible in the help box and in the statusbar.
New parsing routines made it possible to display real time help for variables in the auto complete listbox. The help box shows whether the constant or variable is local or global and constants display their current value. While most of information is obtained while editing, the only structure that needs compiling is a type (UDT) definition. The Type name and members need to present in the internal GB database before auto complete can show its members.

Ditect2D support
Windows’ Direct2D, which is implemented as COM objects, are encapsulated in GFA-BASIC as GB32 - like commands. All the Direct2D command names start with D2, like D2Color, D2Line, D2Brush, etc. To use Direct2D include the GFA-BASIC 32 library direct2d.lg32 in your program. The library is located in the Include directory and exports GFA-BASIC like commands and functions that correspond to the set of graphic commands GFA-BASIC already offers. For instance, the syntax of D2Line mimics the behavior of the Line command, D2DefFill selects a new fill brush as DefFill does, etc.
The new English CHM helpfile plays an important role in developing Direct2D applications.

The new help provides an introduction to Direct2D programming and discusses the D2 command's. The example code presented in the help-topics are stored in the Samples/Direct2D directory. You are encouraged to step through the samples, but you should start reading with the D2GetRT topic in the help-file. D2GetRT is the base in each program to initialize Direct2D and to provide a render target (canvas) to draw on. So, it is a good place to start reading.

DPI-aware applications
To develop DPI-aware apps you'll need two monitors, one regular 96 dots-per-inch display to run the GFABASIC 32 IDE and one high-resolution display to run and test the program. In addition, the manifest of GfaWin32.exe must include the <dpiawareness> tag. For this purpose the Bin directory contains a separate dpi-manifest file that needs to be renamed to GfaWin32.exe.manifest. You can accomplish this by saving or renaming the current manifest (GfaWin32.exe.manifest) and then rename the GfaWin32.exe.dpiawaremanifest to GfaWin32.exe.manifest. See the help-file for more information on creating DPI-aware applications. It provides information for new gfawinx DPI-scaling commands that will help developing high-resolution apps, like ScaleToDpi, ScaleToDpiSng, ScaleXYWHToDpi, and WinDpi, but also LoadFormPos and SaveFormPos to handle loading and saving the application’s main form on multiple monitors.

The Large Address Aware command
When the $LargeAddressAware compiler directive is used in the code, the compiled EXE is modified to handle memory addresses above 2 GB, theoretically allowing access to up to 4 GB of virtual memory. Normally, a 32-bit application can address only the first 2 GB of memory, however on 64-bit operating systems and when the application is large address aware it can access the additional 2 GB memory that isn’t used by the OS.

The gfawinx library
The gfawinx library is the source for new GB32 commands and functions. To stress the importance of these additions they have the same syntax-color in the editor as regular GB32 commands. When a new program is started, the first thing to do is to import this library as follows:

$Library "gfawinx"

Besides the string functions, gfawinx contains several commands to support developing multiple monitor programs. A brief overview of the new commands and functions:

HexDump A debugging aid to show the contents of a piece of memory.
ErrStr Converts the information from the Err object in a single string.
Wide, Ansi Allows conversion between UNICODE and ANSI formatted strings.
Replace Replaces a string in a given string.
StrToArr Separates a delimited – any delimiter character - string into a string array.
Assoc Retrieves a file association-related string from the registry.
GetWorkArea Retrieves the work area of the monitor containing the largest area of a given window.
GetClientSize Retrieves the width and height (in pixels) of any window's client area.
ModifyStyle, ModifyExStyle Modifies the style or extended-style of a window.
SaveFormPos, LoadFormPos Saves and loads the form's position on the screen to and from the registry. Especially useful with multiple-monitor systems.
ScaleToDpi, ScaleToDpiSng Converts pixels based on a 96 dot-per-inch resolution to DPI physical pixels of the Form's display.
ScaleXYWHToDpi Scales ScaleLeft, ScaleTop, ScaleWidth, and ScaleHeight to a form's DPI.
WinDpi Returns the dots per inch (dpi) value of the display for the specified form.
GetProcAddr Returns the address of an exported function or variable from the specified dynamic-link library (DLL).
WinVer Retrieves version information about the currently running operating system (preferred way to obtain Windows’ version).
TimerQ Creates a high-resolution timer wrapped in a (minimal) COM object.

The Include directory
The Include directory contains Windows API library files ready to import in your program using the $Library command. Several include files are modified to export their Declares explicitly by their name. This was necessary because a bug in GB causes a corruption of the Declare-database if the program declared DLL-functions as well.
Their is also a winmacros.inc.lg32 file with commonly used Windows API macros. The include file provides optimized GB functions to mimic the macros from C/C++ header files.

You can download the new update here.