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
EndWith

' 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
Next

Do
  Sleep
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.