22 November 2015

Execute a new process using System

In a previous blog post Execute a new detached process I discussed GB32 commands to start a new detached program, or process. After the new process is created and executing, the parent process cannot communicate with the new process. There is no relationship between the both, hence the term detached. The GB32 commands WinExec, Exec rely on the WinExec() API, which does not return a process instance handle. The only thing you can get from WinExec is some error code when starting the new process somehow failed.

But there is System
Starting a new process might involve more than simply executing it and leaving it out there to be managed by the user. Maybe your program needs to wait for the second application to quit, or you want to execute a process with elevated privileges, or maybe you just want a handle on the new process so you can manage it programmatically. All of this can be done using System, command or function, depending on your needs.

The System command/function comes in two flavors. A simple version, a function, that only takes one parameter. Then there is the less simple one, implemented also as a command and function, taking multiple arguments. When you only need the creation of new process, for example to get a handle on it, use the simple version. It only takes one parameter, the command line. The command line is a null-terminated character string that contains the filename plus optional parameters:

Large = System("filename [parameters]")

This looks much like the WinExec() – and Exec()  – function, but without the the show-window  argument (which is most of the times a ShowWindow SW_* constant to make the new process visible). The difference between System and the other functions is the meaningful return value, a 64-bit integer holding the process-handle and its process identification number. Together these values uniquely identify the new process.

Using System requires some effort
Using the System() function comes with a responsibility. The process handle must be freed using the CloseHandle(hProcess) API.  First let’s see how to use System() and how to interpret the return value:

Global Int32 hProcess   ' keep in memory
Local Int32 ProcessId   ' you may keep it
Local Large Process64   ' can be discarded
Exe$ = "process.exe", Param$ = "-options"

Process64 = System(Exe$ & " " & Param$)
hProcess  = LoLarge(Process64)
ProcessId = HiLarge(Process64)

In this scenario the System() function replaces WinExec, and Exec (and maybe ShellExec but that is a different story).

It might be preferable, because System() invokes the CreateProcess API directly, passing it Null for all parameters, except for the lpszCmdLine argument and the argument taking if the address of a PROCESS_INFORMATION structure. This structure receives the output (or return values) of CreateProcess. It is used to store/return four values; the process an thread handles, and the process-id and the thread-id. GB32 only returns the process handle and process-id through an Int64 data-type.

Taking a closer look at those handles
In pseudo GB32 code, System(cmdline$) function acts like this:

If CreateProcess(0,cmdline$,0,…, V:pi)
Return MakeLarge(pi.Process.Id, pi.hProcess)

Generally, CloseHandle API only decrements a reference count on a handle. When the reference count reaches zero, the OS knows that the object can be freed. That’s all, it is not some kind of destroy-function. Closing a handle might become your responsibility, keep these rules in mind:

  • With the function variant of System(), GB32 only closes the handle to the primary thread. It returns the process handle and you have to close it in time.
  • With the System command both handles are automatically closed - unless you explicitly ask for them as return values.

When you specify the “hProcess var” and/or “hThread var” options with the System command you are explicitly asking to obtain the handles and taking responsibility. For instance, in the following code System does not call CloseHandle on the handles:

Global Handle hProcess
System FileName$, hProcess hProcess, hThread hThread

When, one way or the other, the program gains ownership of a handle, it is also responsible for closing it. The application should close a handle when it isn’t necessary anymore. A good place for a call to CloseHandle could be in your exit code, after the main message loop in the main section of your program:

Until Me Is Nothing
' End of Program

Termination and usage count
CreateProcess creates two objects identified using handles: a handle to a thread object and a handle to a process object. These objects are given an initial usage count of one. Then, just before CreateProcess returns, the function opens both the process and the thread object and increments the usage count again to two. It then places handles and IDs in the members of the PROCESS_INFORMATION structure. In the end, CreateProcess has set the usage count for both objects to two. In the end, the handles must be decremented twice to reach zero.

Before the OS can completely free the process, it must - of course – terminate. This will decrement the usage count with one to one. To reach a zero usage count, the parent process must also call CloseHandle. Only then the final usage count od zero is reached. 
To free the primary thread object, a two step decrement is also required. The thread’s usage count is decremented when its process terminates. (During process termination the thread’s handle is closed). But this leaves the thread with a count of one. Because the System command already decremented the usage count of the thread, it can be freed as well.

The reason to immediately close the primary thread’s handle must be found in the OS. It has something to do with multiple creations of the same process. I don’t know why, but it is heavily recommended to proceed this way. The process handle on the other hand can be kept to be used in future API calls that require a process-handle.

In the next post I’ll discuss the termination of child process.

17 November 2015

Execute a new detached process

What if you want to execute another program (process) from a GFA-BASIC 32 program? GB32 offers quite some commands and functions to do so. However, every new process is eventually started by calling the CreateProcess() API function. All those functions, including Windows API functions like ShellExecute(), WinExec() invoke the CreateProcess() API, which is declared as follows:

BOOL CreateProcess(
   LPCTSTR lpszImageName,              // image file (.EXE) name
   LPCTSTR lpszCmdLine,                // command line for new process
   LPSECURITY_ATTRIBUTES lpsaProcess,  // how process will be shared
   LPSECURITY_ATTRIBUTES lpsaThread,   // how new thread will be shared
   BOOL bInheritHandles,               // TRUE to inherit handles
   DWORD fdwCreate,                    // creation flags
   LPVOID lpvEnvironment,              // new environment (default = NULL)
   LPTSTR lpszCurrentDir,              // name of new current directory
   LPSTARTUPINFO lpStartupInfo,        // gives info about new process
   LPPROCESS_INFORMATION lpProcInfo )  // receives info about new process

WinExec - Command and Function
The CreateProcess function’s parameters permit precise control over the new process’s starting conditions. Because of these big number of parameters and options, some commands provide a simplified execution of CreateProcess. The WinExec() API already invokes CreateProcess with a lot of default values to create a detached process. WinExec() only expects lpszCmdLine and a show-window value for the STARTUPINFO.dwFlags member. All other values are set to zero or other default values. The new process is not a child process; after it is started there is no elation between the parent and the child process whatsoever.
WinExec() is a GB32 built-in API function, but it is not used. Instead GB32 uses its own WinExec function and it is defined as:

[Long =] WinExec(CmdLine$, CmdShow%)             

The CmdLine$ is a null-terminated character string that contains the command line (file name plus optional parameters) for the application to be executed. WinExec passes parameters to the CreateProcess function in such a way that it is compatible to the 16-bits version of Windows. The return value is greater than 31 if the function succeeds. Otherwise it returns an error value

Value Meaning
0 The system is out of memory or resources.
ERROR_BAD_FORMAT (1) The .exe file is invalid.
ERROR_FILE_NOT_FOUND (2) The specified file was not found.
ERROR_PATH_NOT_FOUND(3) The specified path was not found.

The 32-bit WinExec() does not return an instance handle as the 16-bit WinExec() does. The return value can only be used to inspect an error value. Therefore, GB32 also defines a command variant: WinExec CmdLine$, CmdShow%.
Both versions - function and command - are linked to the same runtime function. Obviously, the return value can only be obtained with the function variant.

Exec – Command and Function
The WinExec takes two parameters, a command line argument and a show-window argument. Most of the times the second argument will be a default value of SW_SHOW or SW_SHOWNORMAL. The GB32 command Exec takes advantage of this behavior and allows the command-line parameter CmdLine$ to be split into a filename (path included) and options part. Although this might be useful for the developer, the command itself concatenates the parts before WinExec() API is invoked. The SW_SHOW is automatically used.

[Long =] Exec(file$, parameters$)   

ShellExec – Command and Function
All processes are started using CreateProcess. It depends on the function which parameters are set and to what value. The GB32 ShellExec command/function invokes the ShellExecute() API, which sets and fills another set of CreateProcess’ arguments. Where the Exec and WinExec commands allow a simple start of a named exe program, the ShellExecute() function allows to start a process by a registered extension. Depending on the version used, ShellExec allows a more extended set of parameters for CreateProcess. In itself is ShellExec also a simplified form of invoking CreateProcess. See the help for more information on the parameters that can be used. For a comparison with WinExec and Exec we’ll only look at the variant that takes two parameters and performs exactly like these GB32 functions:

[Long = ] ShellExec file$ [, parameters$]

It doesn’t matter which GB32 command/function you use to spawn a new detached process. They all invoke the CreateProcess API. The return values of the function do not provide some handle to the new process, only an error value (if less than 32). Using Exec is tempting because it provides the easiest interface where the file and parameters are split.

GFA-BASIC 32 does provide a function that bypasses the above mentioned shortcuts to CreateProcess(): the System function/command. I will discuss this briefly in a next post.

18 October 2015

The Non-existing MenuItems Collection

MenuItems is a collection representing all the menu items contained in a Form’s menu. According to COM/VB rules the next phrase should be true:
calling Add on this collection adds an item to the menu and returns a MenuItem object”.
However, there is no actual MenuItems collection you can use in GB32. The MenuItems data type does exist, but contains nothing more than empty stub functions.

Logically, the MenuItems dependent collection (it exists only when a menu-bar is present) should be used to manage the menu items. But in Dependent Collections I showed you why GB32 considers an in-between collection redundant and overkill. Generally, the collection’s implementation does nothing more than reroute all the collection’s properties and methods to the required item object (by key or index). In the case of the MenuItems collection, well GB32 skips the collection entirely.

Where do they come from
GB32 creates a MenuItem object for a menu-entry when it parses the one-dimensional string array containing the menu-entries for a window.

Menu menuEntries$()

Since the beginning, this how a GFA-BASIC menu-bar is created. Fill an array with string elements and let GB create and assign a menu-bar to the current active window. When the window is destroyed, the MenuItem objects are destroyed as well. The only other way to release the MenuItem-objects associated with a menu-bar of a Form is by using Menu Kill.

Now let’s see how to manage the menu-bar entries without the MenuItems collection. This process is not VB-compatible, as VB prescribes the use of a collection. As you probably know, dependent collections are used to iterate over the items they contain, to add new items, to remove items, etcetera. To provide these facilities, the MenuItems collection would provide the following properties and methods:

Property or method Description
Add method Add menu-items to the collection.
Count property Return the number of menu-items in the collection. Read-only.
Item method Return a menu item, by index (or by key).
Remove method Delete a menu.item from the collection, by index (or by key).
Clear Remove and delete all menu-items

Since GB32 doesn’t implement the MenuItems collection, these properties and methods aren’t available. GFA-BASIC 32 does not provide a collection to manage menu-items, but it does however provide MenuItem objects to allow access to single menu-entries. The Form supports a property that returns a MenuItem object. The property takes one parameter, a Long MenuID-value. The value must represent the menu-ID of the menu-entry, which is either the index of an element of the string-array or a designated ordinal (specified in the string element that specifies the menu-item text).

Dim mnuItem As MenuItem
Set mnuItem = frm1.MenuItem(1)

The MenuItem-objects are created at run-time when GFA-BASIC executes the command Menu $(). The ordinal ID-value is assigned both to the MenuItem object as well as to the Windows API functions. The ID-value can not be changed later on. Also, any changes made to a menu-entry using API functions will not be reflected in the MenuItem object. So, all changes of the menu-entries are to be done using a MenuItem object.

03 October 2015

Dependent Collection Objects (Non-Creatable)

A dependent collection object can only exist in the context of a parent COM object.

Often we find those collections as part of an OCX control. COM-controls that support dependent collections include the TreeView Ocx, ListView Ocx, ListBox OCX, Toolbar Ocx, etc. These Ocx-es provide run-time access to their functionality through Dependent Collection Objects. For example, the TreeView Ocx control has a Nodes collection of Node objects that represent the items in the hierarchy the Tree-View control displays. Tree-View Node items are appended or inserted by using the Add method of the Nodes collection. For a List-View control you’ll use the ListItems to add ListItem objects. A dependent collection doesn’t exist until an Ocx is created and are – in COM terms - Classes That Are Not Creatable.

These collections are also provided as a means to iterate over the items of a control. This could concern a collection of all items or a collection of selected items. The collection helps in quickly locating a specific item using a key or an index. Therefor each collection object comes with properties and methods you can use to insert, delete, and retrieve the items in the collection.

Property or method Description
Add method Add items to the collection.
Count property Return the number of items in the collection. Read-only.
Item method Return an item, by index or by key.
Remove method Delete an item from the collection, by index or by key.

I won’t go into the details about the basic services of adding, deleting, and retrieving from a collection. Suffice to say, that the methods and properties depend on keys (type String) and/or indexes. An index is a Long between one (1) and the number of items in the collection (Count). The Add method determines whether or not you associate a key with an item, otherwise the collection items are only accessible through their index. A typical statement to add a Node object, representing the first position, to a TreeView Ocx is:

Form frm1
Ocx TreeView tv1 = "", 10, 10, 230, 200

Dim nodes As Nodes, node As Node

' Add an item through Nodes Collection
tv1.Nodes.Add , , , "Item #1"

' Use Dependent Collection
Set nodes = tv1.Nodes
nodes.Add , , , "Item #2"

' These are exactly the same
Set node = nodes.Item(1)
Set node = nodes(1)   // .Item is hidden

'Using With when adding multiple nodes:
With nodes
  .Add 1, tvwChild , , "SubItem1/1"
  .Add 1, tvwChild , , "SubItem1/2"
  ' ... etc.

  .Item(1).Expanded = True

' Additional GB32 - optimizing ways
tv1.AddItem 2, tvwChild, , "SubItem2/1"
tv1.Add 2, tvwChild , , "SubItem2/2"

' GB32 Shortcut Property
tv1(2).Expanded = True

For Each node In tv1  // rather than tv1.Nodes
  Debug.Print node.Text

Until IsNothing(Me)

In fact, these intermediate dependent collections insert additional code and slow down execution speed. These collections are introduced by VB to provide a systematic way of managing items of an OCX. In the end they only consume code and time.  To overcome these disadvantages, GFA-BASIC provides collection properties and methods to the OCX control directly. This concept makes the use of the dependent collections redundant. Even the iteration properties used with For Each is simplified, see listing above.
The following collection properties and methods have been added to the OCX-es:

Property or method Description of shortcuts
Ocx.AddItem or Ocx.Add method Add items to the collection of the Ocx.
Ocx.Count property Return the number of items in the collection. Read-only.
Ocx.Item method Return an item, by index or by key.
Ocx.Remove method Delete an item from the collection, by index or by key.
Ocx.Clear method Clears the entire collection

Using these shortcuts makes the intermediate collections redundant. The OCX-es that benefit are:

OCX Available Dependent Collections Shortcut To
TreeView Nodes Nodes
ListView ListItems, ColumnHeaders, SelectedItems, CheckedItems, Icons, SmallIcons ListItems
ToolBar Buttons Buttons
StatusBar Panels Panels
TabStrip Tabs Tabs
ImageList ListImages ListImages

Whenever you operate on an OCX-item, first check if the collection-properties are implemented onto to OCX directly.

There is one more dependent collection; the MenuItems collection of the Form Object. In the next post I’ll  show you how to handle MenuItems.

30 July 2015

Tip: How to create short jmp

When doing some assembler I noticed an important optimization setting for jumps. To force the compiler to generate short jumps (short jmp, short jz, short jnz) the Branch optimization setting must be >= 1.


A short jump requires 2 bytes of opcode instructions. Otherwise a jump takes 6 bytes. Short jumps are only generates when the target is within 127 bytes offset, of course.

27 June 2014

Passing default ByRef parameters to a Sub, a flaw?

In my opinion the GFA-BASIC’s Sub procedure type is an anomaly. When possible you should use Procedure instead. Oh, and when you are too lazy to type Procedure than just use its abbreviation Proc. A Procedure takes all arguments by value by default and is completely backwards compatible to previous GFA-BASIC versions.

On the other hand, if you are stubborn enough and want to use Sub anyway, make sure you use ByRef and ByVal explicitly with all parameters. Do not expect the default ByRef passing will work, because it won’t. We discussed this earlier in The Sub-ByRef flaw. This posting ended with the quote “Why this is happening is unclear, but it is easily repaired by using ByRef explicitly in Sub headings.” I was never convinced this was a real bug and I always assumed a reasonable explanation would come up some day. And it did ….

VB is the flaw; ByRef turns into ByVal
Let us consider the default Sub by reference implementation in VB, VBA, and VBScript. An argument is passed by reference only when the caller uses a very specific syntax. Only when the program executes the subroutine without parentheses the sub gets a reference to the actual argument. When the programmer puts the arguments between parentheses the arguments are passed by value. The next sample demonstrates how and when VB(A/Script) executes the default:

' Normal VB call of a Sub
' passing a reference to Hello$
SPrintStr Hello$ Sub SPrintStr(sArg As String)

When VB encounters a call with arguments inside parentheses, the arguments are evaluated first. In other words, before something is put on the stack the expression inside the parentheses is evaluated (executed, calculated, etc) and a local copy of the variable is assigned the outcome of the evaluation. The local copy is passed by reference to the subroutine, which than becomes a by value passing of the original parameter. Using the parentheses-syntax in the next example will pass the address of a local variable to the Sub SPrintStr.

' VB call of a Sub using ()
’ making and passing a copy of Hello$
Sub SPrintStr(sArg As String)

Conclusion VB
When VB calls the subroutine with parentheses the sub gets a reference to a copy of the argument and the default ByRef situation suddenly turns into a ByVal passing. The VB Sub and its implicit, default, by reference passing introduces performance loss and unnecessary memory consumption! Remember this when you port VB code to GB32.

You’ll find the whole story on http://blogs.msdn.com/b/ericlippert/archive/2003/09/15/52996.aspx

GFA-BASIC supports with parentheses
You can almost feel the agony FO must have felt when he found out about this VB quirk. How to maintain backward compatibility to previous GFA-BASIC versions and VB? In GB we are used to place parameters between parentheses. Should we suffer from this VB anomaly as well? Either way, FO decided to support the Sub implementation with parentheses only. Passing arguments without parentheses is equal to passing them with parentheses.

Although the Sub-ByRef problem is much clearer now, the GB32 implementation is still a bit ambiguous. Because GB32 mimics the call with parentheses only the subroutine always receives a by-value argument to a default ByRef parameter. You may omit the parentheses in GB32, but it still executes the version with parentheses. Only when a global variable is passed to a default by reference argument the actual variable address is put on the stack.

Conclusion GB32
Despite the ambiguity between global and local parameters, you should, as a general rule, no longer consider a default by reference parameter as [in/out] when you omit ByRef in a Sub declaration. Inside the Sub you don’t know if you are dealing with the actual variable [in/out] or with a copy [in]. Always use ByVal and ByRef explicitly in a Sub declaration.

31 May 2014

Problem with local Hash variables

GB32 does not support the destruction of local Hash variables. This is by design. Global Hash variables are released when the program terminates. This does not mean you can’t use local Hash variables, you just have to add the termination code yourself.

This behavior might be the cause of many reported memory leaking problems.

Let us look at some examples. First suppose you have a subroutine like this where a local hash variable is used to store the results of the Split regular expression command:

Proc Split_Local(ByRef t$, sep$)
  ' Declare a local Hash variable.
  Dim hs As Hash String

  ' Split creates a new hash table of String,
and destroys the hash allocated memory first. Split hs[] = t$, sep$ ' Explicitly erase Hash variable, because ' memory allocated by hs[] is not destroyed ' automatically when going out of scope. Hash Erase hs[] EndProc

The Dim command declares a Hash String variable hs. The variable is put on the stack. Stack memory is temporary space limited to the scope of the procedure call. A hash variable occupies 8 bytes divided in two Long types. The first Long is a pointer to heap memory. This pointer is set to the hash-table descriptor once a value is added to the table. Initially, the pointer is Null. The second Long contains the code for type of data the hash is going to store. Here the type indicates a String, so the hash is used to store String values.
When the hash variable goes out of scope, at the end of the procedure, the stack is cleared or reset to the value it was at the point where the procedure started executing. The 8 bytes reserved for the hash variable are simply discarded without freeing allocated memory first.
A hash table allocates memory dynamically. When the hash needs more memory, it is allocated automatically. The hash grows and shrinks automatically allocating and freeing heap memory on demand. When the hash variable goes out of scope the allocated memory is no longer referenced by any GB variable or GB garbage collector. This memory gets freed after the application has ended and all of the application’s memory is released to the OS.

  • A local hash variable must be freed explicitly using Hash Erase on the variable name.

The Split command clears the Hash table as well, that is when the first Long of the hash variable isn’t Null. Before Split starts splitting the string in to tokens that are to be stored in the Hash String variable, it completely erases the Hash. In fact, the Split command invokes the runtime function HASHERASE, which is also called with the Hash Erase command.

Static Hash
Now suppose you would like to use Static on a local hash variable. That would prevent unnecessary memory de-allocations in your procedure and would improve performance when the procedure is executed, wouldn’t it? Wrong. Look at the next example:

Proc Split_Static(ByRef t$, sep$)
  ' Static declares a global Hash variable
  ' with local scope.
  Static hs As Hash String
  Split hs[] = t$, sep$, 10

Although the hash variable is declared local, a Static variable is actually a global variable. They are treated the same as other global variables, only their visibility is limited to the procedure they are declared.

Note When asked for the variable address using VarPtr(hs) the address returned is located in the global data section of the program. VarPtr() does not return a stack address, the Static variable is not stored in the stack. For the duration of the program execution the static/global hash variable hs[] can not be changed by other code than the procedure it is declared in. Because a static variable is assigned to the program’s data section, the GB32 application will release the memory it allocated. The static hs[] variable is destroyed when the application quits. When a program is executed from within the IDE all globals will be destroyed and so will be the static hs[] hash variable.

Let us consider the example where the static/global hash variable is passed to Split. Upon entry Split will destroy any entries the hash variable references, the hash variable is destroyed. Than, a new hash table is allocated and its new pointer is stored in VarPtr(hs) + 0. The contents of  VarPtr(hs) + 4 remains unchanged, because it specifies the hash data type. When Split finishes the global/static variable hs[] points to a new hash table. Access to the elements in hs[] is now limited to the code between the Split command and EndProc. Since the hash isn’t destroyed when the procedure returns, the program now carries with it allocated memory that cannot be accessed until the next time the procedure is called. And when the procedure is executed the Split command immediately destroys the hash table. Instead, you could insert a Hash Erase at the end of the procedure, but what does that give you? A local hash variable that is stored as a global variable.

If you like to read more on hash variable, go to Passing a hash variable to a subroutine

More on local scope
Automatic destruction of variables with local scope is only supported for String, Variant, Object,  BSTR and arrays. When a local array is used the compiler inserts a call to CLEARARR(). The code responsible for clearing other type of local variables – a function called CLEARMULTI located in the runtime GfaWin23.Ocx – accepts a Long integer (4-bytes) where each byte contains the number of local variables of one specific type. The Long is coded like this: BBVVOOSS. The Lo byte contains the number of String variables to clean and the high byte of the lo-word contains the number COM objects to release. The hi-word contains the number of Variants and BSTR types.

Yes BSTR types. Unfortunately GB does not provide a data type BSTR we can use to store UNICODE strings. However, all COM objects that require a string use BSTR as a parameter type. When the compiler creates code to invoke a method or property taking a COM string as an argument, the ANSI string is converted to a BSTR before the method or property is called. When necessary the BSTR is stored in a hidden local variable and should later be destroyed.

02 December 2013

Using methods and properties through IDispatch

This is all about two – more or less – undocumented features; the GFA-BASIC _DispID() function and a special dot-curly operator, the .{dispID} syntax.

An object’s layout in memory is, when using a BASIC Object variable data type:

MemObj vtable (array of function pointers)
AddrOf vtable AddrOf QueryInterface()
RefCount% AddrOf AddRef()
…. AddrOf Release()
…. AddrOf GetTypeInfoCount()
… data AddrOf GetTypeInfo()
  AddrOf GetIDsOfNames()
  AddrOf Invoke()
  AddrOf ComPropertyMethod1()
  AddrOf ComPropertyMethod2()

After the following commands the BASIC Object variable oIE holds a reference to an instance of Internet Explorer, an automation server and therefor guaranteed to support a dual interface.

Dim oIE As Object
Set oIE = CreateObject("InternetExplorer.Application")
Trace Hex(Long{V:oIE})
Set oIE = Nothing

An Object variable is actually an Int32 data type and holds the address returned by CreateObject.
Initially, the Object variable is zero (or Null) and is interpreted as Nothing. The following statement does nothing more then checking if the variable oIE holds a value (is not zero):

If oIE Is Nothing Then _
  Debug.Print "No Object assigned"

To view the contents of the integer oIE we first needs its address. In GB32 you can obtain an address of a variable in several ways. You may use VarPtr(oIE), or V:oIE, or *oIE. After obtaining the variable address it must be read, or peeked, to get the contents. Reading a Long or Int32 from some address is done using Long{addr}. The Trace statement uses the Hex function to convert the value to a hexadecimal format, the usual format for a memory address.

From the previous blog post Using OLEVIEW we learned how to process the calling of a property or method through late binding. To summarize, to execute a method or a property of the object an automation client can:

  1. Call GetIDsOfNames to "look up" the DispID for the method or property.
  2. Call Invoke to execute the method or property by using the DispID to index the array of function pointers.

All BASIC languages support this behavior behind the curtains. They provide the object dot-operator to call properties and methods through late binding. For instance, when you want to check to see if Internet Explorer is visible you may call the Visible property:

If oIE.Visible == True Then _
  Debug.Print "Is visible indeed"

After compiling this code the program will execute oIE’s interface-function GetIDsOfNames to "look up" the DispID for the property. It will then generate code to call Invoke to execute the method or property by using the DispID to index the array of function pointers (vtable). Calling Invoke is a bit of a hassle and is best left to the compiler.

Now what when the server gets new functions and new names. Unfortunately, you would need to recompile and redistribute the client application before it would be able to use the new properties and methods. In order to avoid this, you could use a ‘CallByName’ function to pass the new property and method names as strings, without changing the application.

In contrast with other programming languages GFA-BASIC features a function called _DispID(). This function allows you to call the objects GetIDsOfNames function to "look up" the DispID for the method or property. When you remember the blog post on Using OLEVIEW you might have noticed that every property and method is assigned a unique ID (integer value). Using _DispId(0bject,Name$) we can obtain exactly that unique value. For instance, this will display the ID value 402 in the Debug output window.

Trace _DispID(oIE, "Visible")

Obtaining the dispId of a method or property is only useful when you can use the integer value to call the IDispatch function Invoke(). Specifically for this purpose GFA-BASIC 32 provides us with a might piece of equipment; the dot-curly operator. To call Invoke using the dispId you can simply replace the name of the property or method with ‘{dispId}’.

Global Long dispIdVisible
dispIdVisible =  _DispID(oIE, "Visible")
Trace oIE.{dispIdVisible}
Trace oIE.{402}

How does VB6 do it?
If you’re interested, you should compare this elegance to the VB6 function CallByName. This function allows you to use a string to specify a property or method at run time. The signature for the CallByName function looks like this:

Result = CallByName(Object, ProcedureName, CallType, Arguments())

The first argument to CallByName takes the name of the object that you want to act upon. The second argument, ProcedureName, takes a string containing the name of the method or property procedure to be invoked. The CallType argument takes a constant representing the type of procedure to invoke: a method (vbMethod), a property let (vbLet), a property get (vbGet), or a property set (vbSet). The final argument is optional, it takes a variant array containing any arguments to the procedure.

Due to the elegant syntax, GB detects how to invoke the method or property. The parameters of a property or method don’t go in a Variant array. Due to the dot-curly syntax the parameters are specified as any other property or method call. The only thing you need to do yourself is retrieving the dispID, but this is of great advantage since now you are able to store the ID to use it over and over. The CallByName() function each time has to obtain dispID for the name passed.

Dlg 3D On is for Dialogs only

GFA-BASIC 16 (for Windows 3.1) offered the command Dlg 3D On. to get more appealing 3D effects for dialog boxes and controls. This command was invoked before a dialog box was defined and/or created, which was the same thing in GB16. Usually the command Dlg 3D On was placed at the start of the program so that all dialogs would benefit from the 3D effect. In the background the 16-bit system CTL3D.DLL was loaded, was responsible for the painting.

What is CTL3D?
The 16-bit CTL3D.DLL hooks into dialog creation and control creation and "subclasses" the standard windows controls to give them a more appealing 3D effect. To draw 3D effects the background of the dialog boxes was painted gray, or more precisely, painted using the COLOR_BTNFACE color. That made the 3D effects possible in the first place.
This technique was first used by Microsoft Excel version 4.0. The Excel team shared the technology with the rest of the industry. Since then, the use of CTL3D has become a de facto standard and is commonly used by professional Windows applications. GFA-BASIC 16 supported the use of this DLL directly using Dlg 3D On/Off.

Still present in GB32
Starting with Windows 95 a much more pleasing 3D look is provided by default. This made CTL3D unnecessary. Despite its absence in Windows 32-bits GFA-BASIC 32 still supports the the Dlg 3D command, for backwards compatibility. However, its implementation is quite different now. The 3D effect is not accomplished through a system DLL, but by setting the default background color of the dialog box to COLOR_BTNFACE.

Dlg 3D On only works for Dlg form Ocx objects, these are the forms created using the Dialog # / End Dialog commands and accessed with the object variable name Dlg_n, where n is an ordinal value between 0 and 31.

Starting with GB32 most attributes of windows and controls are managed through OCX properties and methods. Internally, all window management is routed through the COM wrappers of the system OCX controls. This is also true for the creation of Dialog # forms. The runtime runs exactly the same code as when you create an Ocx Form. Other (16-bits compatible) window commands like OpenW, ChildW, and ParentW are created by this code as well. However when a Form is created using the Dialog command, the runtime code converts the Dlg 3D and  DlgBase Xxx commands to the appropriate Form-Properties.

Dialog # id, x, y, w, h, tit$ [,flag [,height,font$] ]

The attributes of a dialog form may be set beforehand using the following commands: 

Command Meaning
Dlg 3D On Fills and sets background with COLOR_BTNFACE
Dlg 3D Off Use default Form background-color (default)
DlgBase Pixel Use x, y, w, h as pixels (default)
DlgBase Unit Use x, y, w, h as dialog base units
DlgBase InSide Use x, y, w, h as client size
DlgBase OutSide Use x, y, w, h as window outside (default)
DlgBase Font font$ Use font$ for all controls
DlgBase Bold Use a Bold version of font$
DlgBase Bold Off Use a Normal version of font$
Dlg Fill Fills and sets new background color

The font$ parameter overrules the DlgBase Font setting.
Afterwards the background color can be changed by using properties or by using the Dlg Fill command.

These Dlg commands are used in conjunction with Dialogs only.

30 November 2013

Using OLE/COM Object Viewer

Ever wondered how to get information about all properties and methods of the GFA-BASIC 32 OCX COM-objects?

To view GFA-BASIC OCX type library information, you can use the Microsoft OLE/COM Object Viewer utility that is included with the Microsoft Windows SDK kits.


The figure displays information from the GfaWin23.Ocx type library, a resource found in this DLL. More specifically, it shows the details for the Form Ocx and the CurrentX Get Property. You use the OLE-COM Object Viewer to view compiled type library information. The object viewer presents the COM classes in C/C++ syntax.

To view a type library with the OLE/COM Object Viewer:

  1. Find the OLE/COM Object Viewer application in the bin directory of the installation path.
  2. On the File menu, click View TypeLib, and browse to locate the type library you want to view (GfaWin23.Ocx)

Like the Object Browser that VB and Microsoft VBA use, the OLE/COM Object Viewer lists all the classes exposed in a type library, along with the methods and properties those classes support. For the programmer, the OLE/COM Object Viewer provides important information, such as function return types, argument types, and DISPIDs (which will be discussed shortly). You can use the information that the viewer provides in conjunction with the GB32 object model documentation.


Download SDK
The latest Windows Software Development Kit for Windows 8 (Windows SDK) contains headers, libraries, and a selection of tools that you can use when you create apps that run on Windows operating systems.
The Windows Development Kit (SDK)

I also advise to read Automating Microsoft Office 97 and Microsoft Office 2000 to refresh your memory on the binary layout of COM objects. You may take a look at the section “How an object can exposes its methods and properties”. It does so in two ways: by means of a dispatch interface and in its vtable. Also take a look at my blogs Build a COM object in GB32 (1) and    CreateObject.

A COM object exposing its functions through a vtable only, provide clients with early binding only. The compiler binds methods and property invocations to the vtable-function-pointers directly for more direct access and faster execution. An object that exposes its methods through both a dispinterface and its vtable supports a dual interface.

The DispID
You can examine type libraries in the OLE/COM Object Viewer to determine if an object provides a dual interface. An object that provides a dual interface specifies the dual attribute in its interface declaration. All GB32 OCX objects implement the IDispatch interface. It is this IDispatch interface that provides Automation clients with access to an object's content and functionality. An object's methods and properties collectively make up its dispatch interface (or dispinterface). Within the dispinterface, each method and property is identified by a unique member. This member is the function's dispatch identifier (or DispID).

A COM object can provide clients access to its functions using a dispinterface, an array of function names, and an array of function pointers that are indexed by DispIDs. In GB32 the execution of methods and properties through the dispatch interface is hidden behind the COM dot-operator on an Object data type. First see how GB32 executes properties and methods through early binding.

' Create new instance of the ImageList OCX.
' The Iml variable is of COM type (I)ImageList.
Dim Iml As New ImageList
' Access through early bindings; call the
' ImageHeight and ImageWidth directly through
' a function pointer.
Iml.ImageHeight = 16
Iml.ImageWidth = 16
Iml.Add  , "comp", LoadPicture(":MyComp")

See also: Dim As New

As you can see from OLE-VIEW, the IImageList interface is declared dual. So, the properties and methods are available at runtime as well (late binding). The GB32 compiler doesn’t put a reference to a function address, but stores the name of the method or property and the values of the parameters that must be passed. The compiler than inserts a call to Invoke() to have the program call the method or property at runtime by looking up the name of the function through GetIDsOfNames(). You may want to read the section on Binding in the same article Automating Microsoft Office 97 and Microsoft Office 2000

Note It is a VB/VBA convention to use the name of an interface a a new user-defined type and than skip the capital I from an interface name. So, IImageList in OLEVIEW becomes ImageList type in BASIC.

Now let us see how the method and properties of the ImageList type can be executed at runtime through late binding. The general BASIC Object data-type is an object consisting only of the IDispatch functions. The Object variable oIml doesn’t know about other interface functions ImageList supports. The compiler inserts code to execute the function .Count at runtime through the IImageList functions GetIDsOfNames and Invoke.

Dim oIml As Object      // An IDispatch object
Set oIml = Iml          // Assign to Object
Print oIml.Count        // late binding

To execute the Count property of the oIml object must call GetIDsOfNames to "look up" the DispID for the property. Subsequently, oIml calls Invoke to execute the property by using the DispID to locate the Count function address in the IImageList’s array of function pointers.

Next blog: GFA-BASIC 32 supports syntax and functions to look up the DispID and use Invoke.

06 October 2013

Debug is a runtime object

Closer examination of the Debug object reveals some interesting facts. Although the GFA-BASIC IDE offers some alternative actions to open the debug window, it is not an object owned by the IDE.

The Debug object is completely embedded (data and methods) in the GfaWin.Ocx, which is GFA-BASIC’s runtime. The Debug object is not dynamically created like other COM objects. You don’t use the Ocx command or a New clause in a Dim statement. The Debug object is a global (static) object located in the data section of the DLL. Other examples of static runtime objects are App, Screen, Printer, Forms, and Err.

Note – Most COM objects are – by nature – dynamically created at runtime. In GFA-BASIC they are either allocated using the Ocx (or OcxOcx) command, or with the New clause in a Dim statement. These commands create and allocate memory on runtime. Like the String datatype, a COM object is always stored and accessed by a pointer. A COM object variable occupies only 32 bits and points to a block of memory allocated from the free store. When the variable contains the value 0 (not pointing to a memory address) the object is said to be Nothing. There are some more functions that implicitly create dynamic COM objects, like LoadForm and LoadPicture. Each COM object created by a GFA-BASIC command is destroyed by GFA-BASIC, whether it is a static object or dynamic object.

The Debug object manages the window
Thee Debug object isn’t allocated at runtime, it is available all times. You can immediately start invoking properties and methods on the Debug object. Although the purpose of the debug output window is to display state information at runtime, the Debug object is mainly used to control or manage the debug output window. The debug output window is a modeless, top level, non-owned window with one child control; a standard EDIT control. Many properties and methods control the appearance and behavior of the debug output window and/or its edit control. For more information of the properties and methods look at the descriptions in the help-file or press a dot after the Debug keyword in the editor. Most of them speak for them selves.

Like your application can use the Debug object, the IDE can use the output window as well. The IDE uses the same static Debug object as your application. Any changes the IDE makes are reflected in your application, and vice versa. For instance, when the IDE hides the debug output window, your application must re-show it explicitly.
The IDE offers you two alternatives to show the output window.

  1. By selecting the IDE menu bar View | Toggle Output Window [Alt+3] at design time.
  2. By selecting the tray icon popup menu item at run-time.

Your application can provide its own means of operation to open the debug output window. The debug window could be used for logging, without actually showing the window.

So, whether your application or the IDE controls the debug output window, they both use the same static Debug object in the runtime. Therefor it is important to know what happens in the background.

The Debug thread
First of all, at the first opportunity – when one of the Debug object’s properties or methods is invoked – a new thread is created. As with all good threads it is not destroyed before the application ends; that is when the DLL runtime unloads from memory. When the GFA-BASIC IDE starts executing the thread isn’t started immediately. Only when your GFA-BASIC application, a GLL editor extension, or one of the IDE commands to show the debug window, are applied the thread is actually started.

The debug thread registers the DebugClass window class and creates an instance of the window class (top-level). Note that the window is displayed in the taskbar. Once the window is created the thread enters an infinite message retrieval loop (inside the thread) and handles the dispatching of messages to the DebugClass window procedure, located in the runtime. The window procedure itself is responsible for responding to the messages of the debug output window. One of the messages the window procedure must handle is the WM_SYSCOMMAND, because the debug window thread adds a system menu item to the window (Always on Top). The window procedure either responds by setting the top-level window to the top of the top-level-windows Z-order (HWND_TOPMOST), or by setting it to the bottom of the Z-order (HWND_BOTTOM), which by the way doesn’t mean that it will disappear immediately.

The position is saved automatically
Another message the thread’s window procedure handles is WM_EXITSIZEMOVE. This saves the (new) position of the ‘DebugClass’ window in the registry. It saves the position as a binary value from a RECT structure. It is saved under the a sub key name of ‘DebPos’ in ‘HKEY_CURRENT_USER/Software/GFA/Basic’. When this key doesn’t exist, it is created. When your customers application uses the debug window, the position will be saved in this registry key of your customers PC. Also note that your customer has the ‘Always on Top’ option available. This setting isn’t stored in the registry. (BTW the window position isn’t saved when the output window is in a minimized or maximized state.)

Give it an owner
I find the debug window - unowned toplevel - completely living on its own quite annoying. I think it should be owned by the main window (and thread) of the application that is using it. In case of GFABASIC this should be the Gfa_hWnd window, in case of a customer application, your main windows handle.

~SetWindowLong(Debug.hWnd, GWL_HWNDPARENT, Gfa_hWnd)
Assert GetWindow(Debug.hWnd, GW_OWNER) == Gfa_hWnd

As an example I added the Assert line. I was a little unsure what exactly setting GWL_HWNDPARENT would do and tested the result for what I expected it to do. Anyway, giving it an owner removes the Debug window from the taskbar and makes it behave like its owner. When the owner (Gfa_hWnd) is minimized, the debug output window is minimized. When the owner is (de-)activated the output window is de-activated.

Give it a different font
The edit control is the one and only child window of the debug output window. It has ID number 1 and its window handle is obtained using:

hEditCtrl = DlgItem(Debug.hWnd, 1)

Since it uses a non mono space font you might want to create your own font using API functions and then assign it to the edit control.

SendMessage hEditCtrl, WM_SETFONT, hFont, MakeWParam(1,0)


20 July 2013

What’s that Google+ Button Besides the Articles?

If you’ve been reading GFA-BASIC 32 articles for any length of time, you might have seen the “Recommend this on Google” button… I’m not a fan of plugging in every different crazy social network and putting widgets and buttons all over the blog.

So why do the Google+ button? Because Google uses these scores when they do their search rankings, and GFA-BASIC can use all the help it can get to keep these articles ranking well in Google.

So the next time you click that button, know that the community is thankful for your help!

25 June 2013

What to do with an OLE_COLOR?

An OCX/ActiveX control color property can be assigned any valid Win32 color reference. However, the OCX/COM libraries provide a special data type for color properties, the OLE_COLOR data type. This new type was invented to give VB-like programs an opportunity to differentiate between a normal Win32 color reference and system colors. These programs could then present a special color-selection dialog box that allowed the selection of system colors. The snapshot of the GB32 Ole-color selection is shown below.


RGB colors are of type COLORREF
Like an RGB-color value, an OLE_COLOR data type is internally represented as a 32-bit long integer. An RGB-color is referred to as a COLORREF value and is used with GDI device context functions. A COLORREF is simply defined as a 32-bit value used to specify an red, green, and blue components of a color requiring only 3 bytes. When specifying an explicit RGB color, the COLORREF value has the following hexadecimal form.


The low-order byte contains a value for the relative intensity of red, the second byte contains a value for green, and the third byte contains a value for blue. The high-order byte must be zero. The maximum value for a single byte is 0xFF.
To create a COLORREF color value, you can use the GB32 RGB() function. To extract the individual values for the red, green, and blue components of a color value, use the GetRValue, GetGValue, and GetBValue functions, respectively. For performance reasons these GFA-BASIC 32 functions are directly translated to assembly code; they are not implemented as function calls.

The OLE_COLOR type
When a COM object property (most often .ForeColor and .BackColor only) requires an OLE_COLOR color, you can either pass an RGB  value (COLORREF) or a COM specific formatted system color index value. A COM specific format has it’s high-byte set 0x80. An OLE_COLOR can have two formats only:

  • 0x00bbggrr (COLORREF value)
  • 0x800000xx, where xx is the index used by GetSysColor().

The object doesn’t do much with the OLE_COLOR value, it is more a kind of a storage type. For instance, you cannot pass an OLE_COLOR to a GDI device context handle. GDI doesn’t know what to do with a COM formatted system index color (0x800000xx). The OLE_COLOR value is simply saved in the private data of the COM object and remains unchanged until the application explicitly changes the value again. This way, the Get-color-property variant of the Put-color-property will return exactly the same value as was first put in.

How the OLE_COLOR is used
Since the format of the OLE_COLOR data type isn’t known to Win32 drawing functions, they must be converted to RGB colors first. Usually, the OLE_COLOR is converted on a just-in-time basis. Just before a painting operation is performed the OLE_COLOR (32-bit long integer) is tested for a high-byte value of 0x80. When the high-byte is indeed 0x80, the low-byte value is used as a parameter to the GetSysColor() API function, which in turn returns the RGB color value of the specified display element. See the code below.

Aside: Identifying display elements
Display elements are the parts of a window and the display that appear on the system display screen. These elements are identified using the API COLOR_* constants, like COLOR_BTNFACE, COLOR_WINDOW, etc. These API constants may also be used in the GFA-BASIC 32 function SysCol(idx), which is slightly easier to use and a bit faster due to caching.

Dim rgb% = SysCol(COLOR_WINDOW)

GFA-BASIC 32 also defines a set of OLE_COLOR constants to identify the system display elements. These constants are very much like the Windows API COLOR_* constants. However, instead starting their names with ‘COLOR_’ they start with ‘col’, like colBtnFace and colWindow. These GB32 OLE_COLOR constants have the format of 0x800000xx, where xx is the index for the display element. See the code below.

Convert an OLE_COLOR
When you want to use an OLE_COLOR value, make sure to convert the OLE_COLOR to a COLORREF (RGB) value first. This is the only color format Win32 understands. In GB32 you get hold of an OLE_COLOR when you use one the col* constants or retrieve a color from one of the Ocx-color properties. For instance, when you want to use the same color as the form’s background, you might very well end up with an OLE_COLOR with the high-byte set to 0x80.

Now, there are two possible ways to convert an OLE_COLOR to a COLORREF value.

1. Manually, in your code. For example this converts to an RGB-value:

Trace Hex(SysCol(colBtnFace))   ' =0 (SysCol: what is a colBtnFace?)
Trace Hex(colBtnFace)           ' =8000000F (an OLE_COLOR)
Trace Hex(OleToRGB(colBtnFace)) ' =F0F0F0 (the RGB value)
Trace Hex(OleToRGB(0x667788))   ' =667788 (no conversion)

Function OleToRGB(olecolor As Long) As Long Naked
  If (olecolor And 0xFF000000) == 0x80000000
    Return SysCol(olecolor And 0xFF)  ' LoByte
    Return olecolor                   ' RGB!

2. Use the system OLE function OleTranslateColor()

Declare Function OleTranslateColor Lib "oleaut32.dll" ( _
  ByVal OleColor As Long, _
  ByVal hPal As Handle, _
  ByRef ColorRef As Long) As Long

Dim rgb As Long Long

If OleTranslateColor(colBtnFace, Null, rgb) == S_OK Then _ Trace Hex(rgb)

The second option using OleTranlateColor() might be preferable because it can also return other GDI color formats, like a palette-index value. In addition in case of an error, it let you investigate the type of the error. See the SDK for more info.

More flexibility
You can use OLE_COLOR types with the GB32 graphic commands, though. All drawing statements, font statements, and color statements accept an OLE_COLOR type. GB32 converts the OLE_COLOR to a COLORREF before it invokes the corresponding GDI function.

Another nice page on GB32

Sometimes I scan the internet for GFA-BASIC 32 references. Recently I stumbled upon this site http://basic.mindteq.com/index.php?i=81 with a comment from Bruce Bell. He wrote a very nice summary of the GFA-BASIC 32 essentials. Chapeau!

23 June 2013

The Align Property of Command, Checkbox, and Option

The Align property of the Ocx controls Command, Checkbox and Option differ from other Ocx controls. The documentation for Align says that it indicates how an Ocx control is placed inside its parent or owner Ocx control, also called docking. Several predefined constants (basNoAlign (0), basTop (1), basBottom (2), basLeft (3), and basRight (4))  are provided to help using the correct docking value with Align.

The buttons are different
In GFA-BASIC32 the Windows BUTTON class controls (push)button, checkbox, and radio-button are implemented as Ocx Command, Ocx Checkbox, and Ocx Option, respectively. The position of the contents of the BUTTON control can be changed by applying a predefined BUTTON-style alignment value. These are defined in the winuser.h SDK include file:

#define BS_LEFT             0x00000100
#define BS_RIGHT            0x00000200
#define BS_CENTER           0x00000300
#define BS_TOP              0x00000400
#define BS_BOTTOM           0x00000800
#define BS_VCENTER          0x00000C00

These values can be applied using API functions or using the WinStyle property of the Ocx controls. In addition, these style bits can be set using the Align property of the BUTTON class Ocx controls (Command, Checkbox, and Option). However, the values that you can assign to Align are different than the values used with the docking purpose of Align. The documentation lacks proper explanation of using the Align property with buttons. (At least in the English help file.)So let me fill the gap.
The position of the contents of the BUTTON controls can be set using a value between 0 and 10, but not 3 and 7. There meaning - as described by the official GB32 documentation -and the corresponding button styles are listed below.

Value Position BUTTON Style Value
0 Center Normal H/V centered 0x00000000
1 Left BS_LEFT (vertical centered) 0x00000100
2 Right BS_RIGHT (vertical centered) 0x00000200
3 no meaning* BS_CENTER 0x00000300
4 Top BS_TOP 0x00000400
5 TopLeft BS_TOP | BS_LEFT 0x00000400 | 0x00000100
6 TopRight BS_TOP | BS_RIGHT 0x00000400 | 0x00000200
7 no meaning* BS_TOP | BS_CENTER 0x00000400 | 0x00000300
8 Bottom BS_BOTTOM 0x00000800
9 BottomLeft BS_BOTTOM | BS_LEFT 0x00000800 | 0x00000100
10 BottomRight BS_BOTTOM | BS_RIGHT 0x00000800 | 0x00000200

When one of the position values from the first column is passed to the Align property the value is shifted left 8 bits and then sent to the BUTTON control using

SendMessage(ocx.hWnd, BM_SETSTYLE, position, 1)
* The no meaning values 3 and 7 can be used in code, not in the Form Editor. When used in code, the internal GB32 function that implements Align will accept any value between 0 and 15! It simply shifts the value 8 bits left and sends it to the BUTTON control.

So, the value of the Align property is used to position the contents of a BUTTON control Ocx. The value is converted to a BS_* constant value as defined in the SDK and passed to the BUTTON control. In this particular case the Align property has a different meaning. Perhaps, it should be named ‘Alignment’ as with the Label Ocx controls.

19 May 2013

Mailinglist Is Back!

From Juergen, the man who provides the GFA-BASIC mailing list on his private server for the past 10-15(?) years:

Hi folks, my domain @liebenstein.de was for a time not available, because the domain was put mistakenly on a black list and out of name server listings. With that also the mailing list didn't work of course. Please excuse this, the list is now
available again.

Thanks, Juergen!

30 April 2013

GFABASIC Mailing-list gone?

Many of us now receive this notification since the 4th of April.

This page can't be displayed
  • Make sure the web address http://gfa-basic.liebenstein.de is correct.
  • Look for the page with your search engine.
  • Refresh the page in a few minutes.

The moderator Juergen, cannot be reached by his GB mailing list's e-mail address. Either he doesn't know the list in reachable or he unplugged it.
Questions can be send to this blog's e-mail address or at my personal address. I will make them public and when the mailing list remains off line I will start my own list.

07 April 2013

Favorite: On GoSub/GoTo/Call

One of my favorite programming constructs in GFA-BASIC is, and always has always been, the On value GoXxx statements. Although, I must admit, there was a time I doubt the usefulness and legality of this command, because C/C++ doesn’t offer such a branch instruction. At those times I was under the impression that it was a typical BASIC overkill command. However, it is definitely not, on the contrary! These statements let GFA-BASIC produce optimized branching code through the use of jump tables. C/C++ compilers can do this only when their ‘optimize to fast code’ - switch is set. Since C/C++ doesn’t support jump tables as a language construct, these compilers crunch together a switch/case block and try to turn it in a jump table just like GFA-BASIC does by default. These are the statements that produce highly optimized branching code without setting a compiler option.

On n GoSub label1, label2, …
On n GoTo label1, label2, …
On n Call Proc1, Proc2, …

My most favorite version is On GoSub. This allows for executing local subroutines labeled by a Label: and ended with a Return statement. This version is not compatible to C/C++, these compilers produce code compatible to GFA-BASIC’s On GoTo.

Not in an Editor Extension
As I mostly program editor extensions, I was surprised to got in problems with these branch statements. GFA-BASIC, like Visual C++, creates a jump table at the end of a function/procedure. However GFA-BASIC hard-wires the address of the jump table, with the presumption that the code starts at $400000 (hInstance). With dynamically loaded GLLs, that place was reserved for the IDE executable image (that is where the code is loaded). When the GLL reaches the execution of the On GoSub code it reads the execution address of the labels from the IDE’s code text section. To the GLL this code contains rubbish. When the GLL is loaded not all the addresses in the GLL code aren’t updated correctly.

As my goal is to create code as efficient as possible, I am a bit disappointed and maybe I will try to fix the GLL-loader.

07 February 2013

SetFont 0 or Null?

In 2002 Peter Harder wrote:  "SetFont 0" oder "SetFont ungueltiges_handle%" sorgen im Gegensatz zu GFA16 bei GB32 für einen Programmabbruch. Tückisch vor allem  dann, wenn dieses Problem beim Umschreiben eines GFA16-Programms ' erst beim Kunden auffällt; ein Hinweis in der Onlinehilfe auf  diesen Unterschied fehlt.

What is this about SetFont?
In previous versions of GB the statement SetFont 0  was often used to select a default stock object font in the current active device context. Peter’s remark suggests that this functionality is missing from GFA-BASIC 32. However, it isn’t actually missing, but the data type of the argument is a Variant, rather then an integer. The 0 value is automatically converted to a Numeric Variant (data subtype = basInt) with value 0. This means: 0 is a valid numeric value and is handled as if the font-handle with value 0 is passed to SetFont.

It throws an error
The SetFont library routine checks for a numeric value in the Variant and uses that value to select a stock object. However, the valid value 0 references the WHITE_BRUSH stock object and not a font. SetFont stops and throws an error. ( The error “Illegal Function call”, which, of course, should have been “Invalid Parameter”.)

Use Null instead
To have SetFont select a stock object, to be precise, the DEFAULT_GUI_FONT, the Variant argument of SetFont must be set to the VT_NULL variant subtype. This is done by using the Null constant.

SetFont Null

The Null keyword is used with a Variant to indicate that it intentionally contains no valid data.

But what if you have a variable that is holding a font handle? Well, in case the font handle is 0, you would want to pass a VT_NULL variant subtype, so you must convert it to Null. You could use the explicit Null constant as above, but you can also use an undocumented function Null(value), which is replaced by a simple Null.

Global font%
If font%==
SetFont Null(font%

19 January 2013

Runtime Update 1181

The update Build 1180 from last week caused some problems due to a new bug that manifested itself as a result of the fixes. The problem was the Form Close method. It invoked a function that was called again when the window was actually destroyed. At that point the contents of the variables were undefined and the Close method halted with an Access Violation error.

Download: GFAWin23.Ocx Runtime

14 January 2013

Using Fonts the old-way

The old-style font commands from GFA-BASIC for Windows 16 can still be used in GB32. However before using them you should be aware of an essential difference between GB32 and GB16. Beside this you should also know what the consequences are when applying the GB16 font commands.

The GB LOGFONT structure
In GB16 the font commands applies to one, and only one, internally maintained, global LOGFONT structure (user defined type). In GB32 there are multiple LOGFONT structures and none of them is a global variable. The LOGFONT structure is now part of a Form object and the font commands now work on the LOGFONT of the current active Form (Me)

The LOGFONT type is defined in wingdi.inc.g32 located in the Include directory of your GB32 installation.

' Logical Font (wingdi.h)
Global Const LF_FACESIZE = 32
Global Const LF_FULLFACESIZE = 64

  lfHeight As Long
  lfWidth As Long
  lfEscapement As Long
  lfOrientation As Long
  lfWeight As Long
  lfItalic As Byte
  lfUnderline As Byte
  lfStrikeOut As Byte
  lfCharSet As Byte
  lfOutPrecision As Byte
  lfClipPrecision As Byte
  lfQuality As Byte
  lfPitchAndFamily As Byte
  lfFaceName(LF_FACESIZE) As Byte
End Type

Regardless of the GB version, the members of the current LOGFONT variable are set and read using the same set of commands. In GB16 they are applied to the one global variable, but in GB32 they still set and read the LOGFONT members from the current active Form (Me).

GB-Command Description
FONT member value sets a value to a member
RFONT member variable reads a member value into a variable
variable$ = _Font$ copies all logfont-members into a string
_Font$ = variable$ sets all logfont-members from a string
Dlg Font sets all logfont members from a users font selection
Font To hfnt Creates a logical font from logfont
FreeFont hfnt Deletes a logical font
GetFont hfnt Obtains loglont values from a logical font
SetFont hfnt Selects the logical font into the window's DC

After filling the LOGFONT members (using Font name, _Font$, or Dlg Font) the Font To hfnt invokes the GDI function CreateFontIndirect() which returns a Windows handle to the font created. This functions allocates memory whose memory handle is returned in the hfnt variable (32-bits). This font memory must be released by the application explicitly using FreeFont hfnt.
The GDI fontmapper creates the font that best matches the values in the LOGFONT structure. However, they might be different from what was requested. To obtain the attributes of the GDI created font, the application would use GetFont hfnt. This reloads the LOGFONT values from the actual font handle.

What about SetFont?
In GB32 this commands invokes a series of complex procedures. In GB16 it was as simple as selecting the logical GDI font handle into the current device context. In addition, in GB16 the current device context could be manipulated using SetDC, which is obsolete in the 32-bits version. Of course, eventually, GB32 will select a font handle into a device context like in GB16, but GB32 goes the COM way. As such the GB command SetFont hfnt creates a hidden Font object and performs a Set Me.Font = hiddenFont (from hfnt).

Finally, any font the application created the old way using Font To must(!) be released explicitly when it is no longer in use. Meaning after that some other font has been set. (Either using SetFont or using the Form's property Font.)

13 January 2013

Removal of update Build 1180

Today, 13 January 2013, I temporarly have removed Ocx1180. The runtime OCX Build1180 (from 06-01-2013) because of reported runtime errors. This Build should have fixed memory leaks with Form.Picture and Image.Picture.

Hopefully, the update can be restored soon.