Function CompareDates(ByVal lngParam1 As ListItem, ByVal lngParam2 As ListItem, ByVal iCol As Long) As LongWhy does it need to be declared as ByVal, rather than as ByRef? Because it isn't all that simple (understatement). Some data types force GFA-BASIC 32 to generate pointer code by default, these include user-defined-types (Type) and Ocx/COM objects. GFA-BASIC 32 generates pointer-to code for the ListItem COM object by default. When the parameter would be declared ByRef, the value passed by Windows would force GFA-BASIC to generate code that uses lngParam as a pointer to a Listitem pointer. Hence Excpetion Errors! Ok enough for now, but its not end!
31 March 2009
Local p1 As Register Pointer To Double ' double *p1;The syntax control accepts it, but the compiler doesn't put p1 in a register. Schade (unfortunately). On the other hand the speed increase would be minimal, it is the difference of using a register directly: mov dpt [esi], value ; set first long pointed to in esi and of first copying the pointer to eax from the its (stack) position: mov eax, dpt 116[ebx] ; move pointer content mov dpt [eax], value ; set first long to value GFA also optimizes te code by keeping the pointer in eax when the pointer is accessed multiple times in a row (see for yourself). Now we are where I want it to be. The compiler generates assembler code to access the data of a variable declared with Pointer [To] through a pointer, like C. For instance the second long eax points to is accessed using mov dpt 4[eax], value ; set second long And this is completely different from the code used to access a non-pointer variable. As a conclusion I will summarize how to treat a pointer in GFA compared to C:
' Declare and initialize a double Dim dbl As Double = 3.1 ' double dbl = 3.1; ' Declare an unitialized pointer to double Dim p As Pointer To Double ' double *p; ' Initialize the pointer Pointer(p) = V:dbl ' p = &dbl; ' Assign a value to dbl through p: p = 7.2 ' *p = 7.2
In the next post I discuss the ByRef and Pointer commands.
30 March 2009
' GFA32 argument ByRef, not by value! Sub ListView1_ColumnClick(ColumnHeader As ColumnHeader) Dim lngItem As Long ' Note: ' ColumnHeaders collection is 1-based ' ListItem.SubItems(iCol) is 0-based ' ListView.Sort iCol is 0-based Dim iSubItem As Long = ColumnHeader.Index - 1 ' 1-based 'Handle User click on column header If ColumnHeader.Text = "Name" Then 'User clicked on Name header 'ListView1.Sorted = True 'Use default sorting to sort the 'ListView1.SortKey = 0 'items in the list ListView1.Sort iSubItem, 0 ' 0-based Else 'ListView1.Sorted = False 'User clicked on the Date header 'Use our sort routine to sort by date SendMessage ListView1.hWnd, LVM_SORTITEMS, iSubItem, ProcAddr(CompareDates) End If 'Refresh the ListView before writing the data ListView1.Refresh ' MS/VB 'Loop through the items in the List to print them out in sorted order. 'NOTE: You are looping through the ListView control because when 'sorting by date the ListItems collection won't be sorted. For lngItem = 1 To ListView1.ListItems.Count 'ListView_GetListItem lngItem, ListView1.hWnd, strName, dDate 'Print ListView1.ListItems(lngItem).AllText Next ' GFA32 - The ListItems collection is sorted as well. Dim li As ListItem For Each li In ListView1.ListItems Print li.AllText Next End SubTo show the differences with VB the code is heavily commented. The clue is located in the next code line:
SendMessage ListView1.hWnd, LVM_SORTITEMS, iSubItem, ProcAddr(CompareDates)The .hWnd property returns the window handle of the ListView Ocx. The wParam argument specifies the corrected column number and the lParam argument holds the pointer to the function to compare two ListView items. The CompareDates function is declared as:
Function CompareDates(ByVal lngParam1 As ListItem, _ ByVal lngParam2 As ListItem, ByVal iCol As Long) As LongThe first two long integer arguments receive the lParam member of the LV_ITEM structure, which is in GFA-BASIC 32 a pointer to a ListItem object. The compare function is a callback function. It is called from inside Windows and never from a GFA-BASIC 32 statement. GFA-BASIC 32 cannot check the function parameters against the data types passed when called. When the program is executing the lParam members are simply copied to the first arguments of the compare function. Because we know the value points to a ListItem object, we cast the 32-bits value to a Listitem. The GFA-BASIC 32 compare function is much simpler, convert the text of the ListItems to apropriate data type and compare:
Function CompareDates(ByVal lngParam1 As ListItem, _ ByVal lngParam2 As ListItem, ByVal iCol As Long) As Long Dim dDate1 As Date, dDate2 As Date ' MS/VB way: 'Obtain the item names and dates corresponding to the 'input parameters °ListView_GetItemData lngParam1, hWnd, strName1, dDate1 °ListView_GetItemData lngParam2, hWnd, strName2, dDate2 ' GFA32 way. The LV_ITEM.lParam is passed to the compare ' function. The lParam contains the address of the ListItem ' object, which we intelligently casted to a ListItem object! dDate1 = ValDate(lngParam1.SubItems(iCol)) dDate2 = ValDate(lngParam2.SubItems(iCol)) 'Compare the dates 'Return 0 ==> Less Than ' 1 ==> Equal ' 2 ==> Greater Than If dDate1 < dDate2 Then CompareDates = 0 ElseIf dDate1 = dDate2 Then CompareDates = 1 Else CompareDates = 2 End If End Function
28 March 2009
- A ListItem object is directly connected to a LV_ITEM structure. A pointer to the ListItem Ocx object, as it is implemented by GFA-BASIC 32, is stored in the lParam parameter of the LV_ITEM structure.
- When you add an item to the ListView, a ListItem COM object is created and a pointer is stored in the LV_ITEM structure. Then the LV_ITEM is inserted into the ListView control. The ListItem is NOT added to som internal array of ListItems, because GFA-BASIC doesn't maintain a hash table for the ListItems collections.
- A ListItems collection object only provides a way to access these items. A ListItems collection is used to count the number of items in a ListView and to obtain and remove a single ListItem object. When you invoke the .Remove method of the ListItems collection the ListView's item is removed and the ListItem COM object stored in the lParam is destroyed.
18 March 2009
16 March 2009
09 March 2009
- a numberic value specifying the index
- or a string specifying the key used to store the item
06 March 2009
- Members can be added before or after an existing member based on the latter’s key value as well as its index value.
- Members can be retrieved based on either their key value or their index value.
- Members can be deleted based on either their key value or their index value.
05 March 2009
GFA-BASIC has a long history. The first version was released in 1985 for the Atari ST, followed by a version for the Amiga. Then GFA-BASIC was developed for for the Intel processors: GFA-BASIC for MSDOS, GFA-BASIC for Windows 3.1, and the most recent GFA-BASIC 32 for Windows 95 and later.
GFA-BASIC 32 is no longer divided in an interpreter and a stand-alone compiler. When run from the IDE the code is first compiled to machine code and then executed. The compiler is optimized for producing fast machine code, so that GFA-BASIC 32 programs execute at high speed. The command library of GFA-BASIC 32 is partly compatible to Visual Basic and 16-bit GFA-BASIC. Much of the functionality of the 16-bit version is retained, but due to an entirely new concept of creating and handling of windows and dialog boxes, GFA-BASIC 32 is also quite different and much more compatible to VB in that area. Other incompatibilities are due to the 32 bits operating system; an integer is now 32-bits wide rather than the 16-bits in GFA-BASIC 16-bit, for instance. When porting application from 16-bits GFA-BASIC, GFA-BASIC 32 will automatically convert 16-bit code to the new 32-bit syntax.
GFA-BASIC 32 files are single project files. Code, forms (windows and dialog boxes), data, resource info are all contained in one file; the .g32 file. To create modular programs part of the code can be compiled in a library file (.lg32) and included into the project file.
New in the text-editor
An odd number of parenthesis in a code line are auto-completed to match all required parenthesis.The underscore character ( _ ) can be used to split "logical" lines of source code across physical lines in the source code file. The underscore character must be preceded by at least one white space character. The effect of using a line continuation character is for "visual" appearance only - the compiler itself treats lines split this way as only one contiguous line of code. The colon character (:) can be used to separate multiple statements on a single (logical) line of source code.
Subs and functions can be folded of course. Procedures can have optional parameters and the code is automatically indented and formatted.
Keyboard macros for repetitive action keystrokes can be recorded and played back.
Extending the IDE
The Integrated Development Environment can be extended through the use of add-ins, called editor extensions. More than 100 special Gfa_Xxx functions and statements provide access to manipulating the environment.
Besides the well-known Sub, Procedure, and Function subroutines, you can now also use GoSub and Return anywhere in a procedure, but GoSub and the corresponding Return statement must be in the same procedure. A subroutine can contain more than one Return statement, but the first Return statement encountered causes the flow of execution to branch back to the statement immediately following the most recently executed GoSub statement. Using a GOSUB to perform a repetitive task is almost always faster then performing a call to a Sub or Function, since there is no overhead in setting up a stack frame for a GoSub.
New data types
New data types are Large (64-bit), Date, Currency, Variant, Object, Pointer and Handle. Integer and Long are now 32-bits. Variables declared without specifying a type explicitly are a Variant data type by default.
Const and Enum
A constant is a variable whose value is fixed at compile-time, and cannot change during program execution (hence, it remains constant). A constant is defined using the Const keyword. The Enum keyword is used to define a sequence of constants whose values are incremented by one.
Array, Hash and Collection
Arrays elements can be inserted and deleted. The array can be sorted using quick sort or shell sort. The Hash is a one dimensional array whose index is of type string. The array can be of any type, Int/String/Date/etc. A Hash array is dynamic and is not dimensioned prior to its use. Values are added or assigned to existing elements. A hash can be examined, sorted, saved and loaded. Elements can be accessed by numeric index as well. Access to hash elements are very fast. The Hash is used with Split, Join, Eval and the regular expression functions reMatch, reSub.
The Collection is a one dimensional variant array whose index is of type variant. A collection is dynamic and is not dimensioned prior to its use. Values are added or assigned to existing elements. The collection is mainly targeted at OLE objects.
Many new operators and functions
GFA-BASIC 32 now also supports Iif() and an implicit conditional form (?:). It uses a question mark after the condition to be tested, and specifies two alternatives, one to be used if the condition is met and one if it is not. The alternatives are separated by a colon.
Also new is the string concatenation operator & as used in VB by default. This may lead to strange results, because the numeric operands are automatically converted to strings: "Number" & 7 => "Number 7" and 12 & 6 => " 12 6".
For string functions the $-postfix is no longer mandatory, as in Chr$(0) which becomes Chr(0). The return value from a $-free string functions is NOT a Variant as in VB, but a real (ANSI) string. New are the Pascal compatible character constants #number that can be used in place of Chr(number). The following "Line1" #13#10 "Line2" #13#10 is the same as "Line1" + Chr(13) + Chr(10) + "Line2" + Chr(13, 10).
In 16 Bit GFA-BASIC the & - operator is the same as And (as in 'C'), meaning 12 & 6 = 4 <=> 12 And 6 = 4 (%1100 & %0110 = %0100). In GFA-BASIC 32 a new And operator is added, the %&. So, in GFA-BASIC 32 is 12 %& 6 = 4 (%1100 And %0110 = %0100).
Another quirk (coming from VB) is the additional space before the numbers when converted to a string this way. You can prevent the automatic conversion of numeric values to strings when using the & operator in the properties dialog box.
Alternatively, GFA-BASIC 32 offers the operator $ as a replacement for the & concatenation operator.
Comparison and assignment operators
In contrast with 16 Bit GFA-BASIC the expression x == y is now the same as x = y and x := y. The comparison == operator from16 Bit GFA-BASIC should now be replaced by NEAR. Alternatively, you can use a forced floating point comparison like If a = 1!.
Direct memory access
For direct memory access a whole range of variants of Peek and Poke are available (PeekCur, PokeStr, etc, etc.).
Memory move and manipulation commands are provided (MemMove, MemOr, MemAnd, MemFill, etc).
’Bits and bytes’ swap and make functions (BSwap8, MakeLiHo, etc, etc).
Bits rotate and shift is supported.
Port access is supported (Port Out, Port In).
Besides to the normal arithmetic functions, GFA-BASIC 32 offers Matrix functions and many more (advanced) mathematical functions.
For runtime expression evaluation GFA-BASIC 32 includes Eval().
Special file functions
Special file functions are for checksums (Crc32, Crc16, CheckSum, etc), file encryptions (Crypt), file compression (Pack/UnPack). Others are MimeEncode/MimeDecode, MemToMime/MimeToMem, and UUToMem/MemToUU.
Win32 API functions are built-in
GFA-BASIC 32 supports more than 1000 WinAPI-Functions, functions that can be used as any other GFA-BASIC 32 function. Only the Standard-API-Functions from User, Kernel und GDI are implemented, other not often used API-Functions like for instance WinSock-Functions are to be declared explicitly as in VB.
The type of the parameters of the built-in API-Functions are not checked upon compiling. Each parameter is assumed to be a 32-bit integer. A string can be passed to an API function, but is always copied to one of the 32 internal 1030-Byte buffer BEFORE the address of the buffer is passed. A user defined Type (As type) is always passed by reference, so that its address is passed (automatically V: ). To be on the safe side, keep things in your own hand and pass the addresses explicitly using Varptr or V:.
These rules don’t apply to DLL functions introduced with the Declare statement. Here GFA-BASIC 32 behaves like VB and the rules for calling such APIs must be respected. For a thorough article on using see Visual Basic Programmers Guide Chapter 10 - The Windows API and Other Dynamic-Link Libraries.
Some WinAPI function names are already in use by GFA-BASIC 32 as statement or built-in function names and are therefore renamed. GetObject() becomes GetGdiObject(), LoadCursor becomes LoadResCursor. Obsolete functions are not implemented, obviously.
Built-in Win32 API constants
As with the built-in API functions from User, Kernel and GDI, their accompanying constants are built-in. (1400 API-Constants from the 16 Bit-Version and more then 900 Constants from Win32-APIs are implemented. Obsolete constants are not implemented, obviously.
Graphic commands take floating point values now. After scaling (set with ScaleMode) the coordinates are passed as integers to the GDI system. Scaling provides much more flexibility and is VB compliant.
Most graphic commands can be used in VB format: Line (x, y)-(z, t),, BF or PBox x, y, z, t.
The Color-command is now the same as RgbColor in 16 Bit GFA-BASIC. Additionally, a table with the 16 standard colors can be used: Color QBColor(i) or a shortcut QBColor i.
The windows now have an AutoRedraw property so that output is captured (some performance decrease) to a second bitmap as well. A redraw of the window is then performed by copying the contents of the bitmap to the screen.
CreateObject creates and returns a reference to an ActiveX object. After the object reference is assigned to a variable of type Object you can use the object's properties, methods, and events. Other COM functions like _DispId and GUID are included. GFA-BASIC 32 includes many COM objects, both for controls and windows as well as for other features.
App and Screen Object
The App OLE object specifies information about the application's title, version information, the path and name of its executable file and Help files, and whether or not a previous instance of the application is running. In addition it provides methods to create shortcuts. It has many properties returning information that are otherwise hard to find. The Screen Object returns the current capabilities of the display screen your code is executing on. The Screen object has much more properties than the VB counterpart.
Contains information about runtime errors or helps in generating useful errors. Although the VB compliant On Error Goto structure is supported, the Try/Catch/EndCatch error-handling is preferred.
CommDlg, Printer Ocx object
An OCX wrapper about the common dialog box functions. The Printer Object provides full(!) printer support for your application.
Picture and Font OLE Objects
OLE Object types to create and manipulate fonts and pictures. Since these types are OLE-type compatible, a Font or Picture instance can be assigned to a property of an OCX control or form.
Windows and dialogs
Windows and dialogs are all Forms now and their events are handled the same way as in VB. All standard and common controls are implemented using an OCX object wrapper. In general, all GUI objects are now OCX objects and are manipulated through properties, methods and events. The old GetEvent/Menu() structure is now obsolete.
You can still use third party controls by using the old CONTROL statement. The notification messages are then handled in the window procedure of the parent; an form event sub as well!
Assembler and DisAssembler
GFA-BASIC 32 provides an inline assembler and a disassembler object (DisAsm).
Interested? Use the download link in the Links section of this site.