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.

26 November 2020

The Naked attribute in practice

In the previous posts The Anatomy of a Procedure (1) and The Anatomy of a Procedure (2) I discussed the effect of the Naked attribute on the code generated by the compiler. Everything you want to know about the Naked attribute can be found in these posts, but – unfortunately – the posts are rather technical. If you lack any experience in assembly it might be hard to understand, so I will recap on the use of the Naked attribute in ‘layman’s’ terms here.

Naked explained
A Naked procedure is fully optimized, both in size and in performance. This comes with a penalty though, a naked procedure lacks support for dynamic variables types (String, Object, Variant, array and hash), structured exception handling, and runtime debugging (Tron, Trace). The reason for this is the lack of ‘procedure-housekeeping’ that GFA-BASIC 32 inserts in each regular procedure. In a regular procedure GB starts of by inserting a 80 bytes stackframe (68 in an EXE) to store all information necessary for housekeeping of the procedure. At the end of the procedure in insert code to restore the stack to automatically release all (dynamic) variables (even in case of a runtime error). The housekeeping code is missing in a naked procedure. Consequently, a naked procedure can execute faster, in certain cases up to 50% faster than a regular procedure. Only short procedures benefit from the Naked attribute; the executable code must be relative small compared to the code necessary to setup a stackframe of 80 bytes, as we will see. The example procedure from the previous post is a good example of a candidate for Naked, it executes 50% faster:

TestMul(2, 3)
Proc TestMul2(x As Int, y As Int) Naked
  Local tmp As Int
  tmp = x Mul y

When the procedure grows and contains more executable code the relevance of Naked disappears. The next example shows two things. First, it declares a local dynamic string variable (which needs to be released explicitly by setting it to the ‘empty-string’). Secondly, the assignment of data to the string will allocate memory and produce code to copy the data to that memory. This is a relatively expensive operation and will reduce the possible performance gain of Naked.

Dim i%, t#
t# = Timer
For i% = 0 To 100000 : TestMul(2, 3) : Next
Debug "Normal: "; Timer - t#
t# = Timer
For i% = 0 To 100000 : TestMul2(2, 3) : Next
Debug "Naked: "; Timer - t#

Proc TestMul(x As Int, y As Int)
  Local tmp As Int, s As String = "Something"
  tmp = x Mul y
Proc TestMul2(x As Int, y As Int) Naked
  Local tmp As Int, s As String = "Something"
  tmp = x Mul y
  s = ""

The measured time for calling TestMul() and TestMul2() a 10000 times is

TestMul: ca 0.021 seconds
TestMul2: ca 0.019 seconds.

In this example, the time to execute the naked procedure is almost the same as executing the regular procedure. Adding a dynamic variable – and assigning it a value - to a naked procedure negates the benefit almost entirely. The code to execute is drastically increased, assigning a value to a string causes the execution of malloc() and memcopy(), and these take so much time the advantage of naked is almost gone. In addition, the string must be released which leads to an extra call of mfree(). All in all, just by adding one dynamic variable the procedure contains too much code to really benefit from Naked.

Other issues
Another disadvantage of using Naked is the issue of runtime error trapping. In case of an error the IDE stops running the program and puts the the error-line-marker on the line that calls the procedure and not inside the naked procedure.

A non-naked, regular procedure will not only trap the error, but also clears the contents of the (dynamic) local variables automatically. With naked-procedures the dynamic variables must be released explicitly. The local variables can be released using the following commands.

Local dynamic variable        Release command           
String s$ = “” or Clr s$
Variant var = Empty
Object (any COM) Set obj = Nothing
Hash Hash Erase hs[]
Array (not allowed, unless static)   If static: Erase ar()

A local array cannot be used in a naked-procedure. A local array declaration allocates an array-descriptor plus the memory required to store the array elements. Using the Erase command on a local array only releases the memory for the data, not the array-descriptor. Each time the procedure is executed a new descriptor is allocated without being released. Consequently, the program will leak memory. If you need a local array it must be static, then the descriptor is allocated only once. This is not a problem in regular procedures, of course.

Only short procedures that don’t use local dynamic variables are candidates for the Naked attribute.

27 August 2020

New features: my personal top 5

The past years GFA-BASIC 32 received some updates; bugs were fixed and new IDE features were added. If you checkout the readme25.rtf file that comes with the updates you might be overwhelmed by the number of (small) new features. To help you find your way I discuss my personal top 5 of the new IDE additions.

5 Print a Procedure
In a large program with many subroutines it is likely you want to print a single procedure rather than the entire program. To print the current subroutine – the one that contains the caret - choose the Procs button on the toolbar and select Print:

After selecting Print you will be presented the Windows Print dialog to select a printer and other options. Note that this is another fix, since the original GB only printed to the default printer.

4 Run As Exe
When developing a (new) program you should test the EXE version of the program on a regular basis. To make the process of compiling and testing a lot easier the toolbar offers the Run As Exe button. This button is enabled for a normal program and disabled when the editor contains a GLL or LG32. When you select the Run As Exe button the program is saved and compiled to exe. The first time you will be presented with the GFA-BASIC’s compile dialog box to specify the name and icon for the exe. If the program is compiled before and the exename is already specified the code is compiled with that name immediately and the dialog box is not shown. Also note that the dialog box contains a default icon for the exe.

When the compiling process did not generate any errors the EXE is executed directly. However, before executing the presence and version of of the GfaWin23.ocx runtime in the program’s directory is checked. In case there is a newer version of the runtime or if it is missing a message box will popup to inform you about the copying of the GfaWin23.ocx to the program’s directory. These days a DLL is no longer placed in the System32 directory, but accompanies the EXE in its own directory.

The new default icon for a GFA-BASIC standalone EXE contains 9 images to conform to the latest SDK requirements. A full set of icons includes images for 16x16, 32x32, 48x48, and 256x256. Windows selects the appropriate icon for the current DPI and Explorer View setting. The icons are taken from the multi-image app.ico file, which is located in the GFA-BASIC directory and is loaded when a program is compiled for the first time. The app.ico adds a resource of 41 KB to your program. Of course, a different .ico file can be loaded, but you should make sure to conform to UI-guidelines; an .ico format file of 766 Bytes is no longer the standard. Note - You can also use app2.ico (only 4 KB) from the GFA-BASIC directory which holds the same images but in a packed format. We did not encounter any problems with the packed version so far, so you could try it instead.

To support visual styles in your own programs the EXE must include a manifest file, either as a resource or as a stand-alone file. When Add Manifest Resource is checked the GfaWin32.exe.manifest is included as a resource after compiling automatically. The checkbox is only checked if the IDE is run with a manifest file. The checkbox setting isn’t stored in the program and is reset each time. To prevent the automatic inclusion of the manifest resource you should include the $ManifestOff directive in your code.

3 Insert miscellaneous text
Sometimes you want to store the program’s name and date into a comment line. By pressing App+I a popup menu appears that allow you to insert several kinds of information into the program’s code. These are the possible text items:

To easily insert the current procname into the code you can also use App+P. Inserting a procedure’s name is useful when displaying an error message box in a Try/Catch handler. The gfawinx function ErrMsg() is created with this feature in mind. ErrMsg returns the relevant properties of the Err-object in a single string ready to be displayed in a message box (see gfawinx.g32 in the Include directory for more info). The following picture shows when to press App+P to insert the proc’s name:

2 Grouping procedures
Actually this feature is my favorite, but I don’t use it as often as my number 1 favorite. To get a better overview of a large code file the procedures and functions can be grouped in collapsible groups. For this to happen a new editor command $Group has been implemented. To collect a series of procedures into a group add the $Group "title" statement just above a procedure in your code. As a result, the Procs tab in the sidebar will contain a collapsible group named “title” holding all procedures until the next $Group statement. A group can be removed by typing $GroupOff at the line with the $Group statement.

The picture above shows my grouping in the GfaWin32.gll program. Grouping allows me to collect related procedures into one section. It makes navigating the code very simple.
By right clicking in the Procs-tab listview you can fine tune the displaying of groups. For instance, the grouping can be (temporarily) disabled to display the procedures in the default manner. By default, groups outside the current the group are collapsed. This automatic collapsing of non-active groups can be disabled.

Hoovering over a procedure name (a Procs Listview-item) brings up a scrollable tooltip. The tooltip displays the code of that Proc. Use the mousewheel to show more or less lines. This also works in the editor. Hoover the mouse over a procedurename and Proc-PeekView pops up.

1 Edit history
My number one feature is Edit History, simply because I use it all the time without even realizing it. Edit History works in the background and saves the line last edited to the top of a stack. By using Esc or Ctrl+minus or the toolbar button < you are taken back to the lines you just edited. When stepping backwards, the steps are saved in a ‘forward stack’ so you can return easily to the last edited line using Ctrl+Shift+minus, or by clicking the appropriate > button in the toolbar.
The toolbar button for walking back has a collapsible menu that shows the line numbers and procnames you last edited. This way you can easily jump back to some line previously stored on the stack.