FT-V01

ActiveX Controls for the FoxPro Developer

Andrew MacNeill
AKSEL

Overview

Note: This document is not a full guide to the ActiveX controls session. Instead, it highlights different features of several different ActiveX controls in Visual FoxPro, including some that were included in the session.

Characteristics of a Good Control

Development today requires that ActiveX controls are robust, small and single-minded. Many FoxPro developers also have a general dislike for Visual Basic controls however this should not always influence the decision. The reasons to stay away from Visual Basic controls are 100% valid: the overhead is usually huge and can cause some compatibility problems. Howver consider that many Windows environments today will have Visual Basic applications running on them and so the overhead and compatibility issues have already been dealt with. Just something to consider…

Microsoft ListView

The Microsoft ListView allows developers to present a list in four different ways: as large icons, smaller icons, a list of items only or a detailed view of items and additional information. If this sounds like Windows Explorer, that’s because Explorer uses ListView for its right pane.

Like the TreeView control, ListView allows you to associate images with an item in the list, by using the accompanying ImageList control. This note focuses on features that treat the ListView primarily as an enhanced list.

The ListView uses two major collections, ListItems to access the rows and ColumnHeaders to access the column headers.

How To Use It

Drop the ListView on a form. Drop the ImageList control on the form as well. If you want to use both large and small icons, drop two image lists on the form. You can set a number of the properties with the Property sheet but putting your settings in code ensures you are in control (see Gotchas below).

The code below runs in the form’s Init method to ensure that both the ListView and ImageList controls have been instantiated. An alternative to this is to subclass the ListView and ImageLists into a single control.

THISFORM.ListView.Icons = THISFORM.LargeImages.Object

THISFORM.ListView.SmallIcons = THISFORM.SmallImages.Object

Adding and Displaying Items

Use the Add method of the ListItems collection to populate the ListView. When an item is added, it returns an index. The Add method takes 5 parameters of which only one is required. Set the View property to 0,1,2 or 3 to show Large Icons, Small Icons, List or Details respectively.

THISFORM.ListView.ListItems.Add(,, “Johnson”)

THISFORM.ListView.ListItems.Add(1, “CUSTX”,”Smith”, 5, 5)

THISFORM.ListView.View = 3 && Displays items as a detailed list

 

Parameter

Description

Index

Determines the order in which the item appears. Optional.

Key

A unique identifier for the new item. The key cannot start with a digit. Optional.

Text

The text to be displayed.

Large Icon

The index number or name of the icon in the imagelist, specified in ListView.Icons.

Small Icon

The index number or name of the icon in the imagelist, specified in ListView.SmallIcons.

Adding to a ListView. The Add method takes 5 parameters, but only Text is required.

Using Multiple Columns

When the View property is set to 3-Detail, columns appear in the ListView. Use the Add method of the ColumnHeaders collection to set up the columns.

Parameter

Description

Index

The relative position of the column.

Key

A unique identifier for the column.

Text

The text to be displayed as the column header.

Width

The width of the column in pixels.

Alignment

0 – Text is left-aligned (default);

1 – Text is right-aligned;

2 – Text is centered.

Icon

The key or number referring to the image in the ColumnHeaderIcons imagelist.

Adding Columns. You can set the column width and the determine alignment within the column.

You can change different attributes of an item using the ListItems collection.

 

Property

Description

Text

The text of the item

Key

The unique identifier of the item

SubItems

A property array for additional information shown in the columns

ToolTipText

The tip that appears when the user holds the mouse over the item

Selected

Indicates if the item is selected

Ghosted

Indicates if the item appears dimmed or unavailable

Icon
SmallIcon

Indicates the index of the image in the ImageList control

Dealing with items. Each item has its own properties that you can manipulate.

In Detail view, the first column shows the "main" text for an item, that is, the text specified in the call to Add. As with many ActiveX controls, the first column added is in position 0. Use the SubItems property array of ListItem to add content to the columns. The code below adds city and phone number columns to the ListView along with some content. Set the Text property of ListItem to change the text of the the first column. Set the FullRowSelect property to .T. to highlight the entire row. If set to False, only the text in the first column is selected.

THISFORM.ListView.ColumnHeaders.Add(,”Name”,”Name”)

THISFORM.ListView.ColumnHeaders.Add(,”City”,”City”)

THISFORM.ListView.ColumnHeaders.Add(,”Phone”,”Phone”)

THISFORM.ListView.ListItems(1).SubItems(1) = “Ottawa”

THISFORM.ListView.ListItems(1).SubItems(2) = “(613) 555-5555”

THISFORM.ListView.ListItems(1).Text = “Andrew”

Which Item Did The User Select?

Use the ItemClick event to interact with the ListView control. The event method receives a reference to the selected ListItem object. The SelectedItem property also points to the currently selected ListItem object.

Sorting

The ListView makes sorting very easy. Set the Sorted property to .T. and set the SortKey property to an integer that refers to the Subitem to be sorted. If you’ve used the ListView before, you might think of SortKey as being related to the columns. In fact, it’s related to Sub-items since columns may be re-ordered by the user. In the example above, if I want to sort by city, SortKey is set to 1 (remember that the first column is item 0). By default, the SortOrder property is 0, putting the list in ascending order. Set the SortOrder to 1 to order the list in descending order.

Code may be placed in the ColumnClick event to control how the listview is sorted. The code below re-orders the list each time the user clicks on the column header. Note the use of the subitemindex property to indicate how to sort the list.

Method: ListView.ColumnClick

PARAMETERS column

IF column.subitemindex = THIS.SortKey

   THIS.SortOrder = IIF(THIS.SortOrder = 1, 0 , 1)

ELSE

   THIS.SortKey = column.subitemindex

   THIS.SortOrder = 0

ENDIF

Editing the List

By default, users can edit the text for an item in the list. Set the LabelEdit property to .F. and the ListView does not permit editing. To take advantage of the editing feature, use the AfterLabelEdit event to update your table as shown below.

Method: ListView.AfterLabelEdit

PARAMETERS cancel, newstring

** Assumes the order is set properly

SEEK THIS.SelectedItem.Key

REPLACE name WITH newString

Checkboxes

Version 6.0 of the ListView control added checkboxes for the items in the list. Set the Checkboxes property to .T. and every item displays a checkbox beside it (see figure 1). When the user checks the checkbox, the NodeCheck event fires. The event is passed a pointer to the item. Set the Checked property of the item to .T. to mark the checkbox in code:

THISFORM.ListView.ListItem(1).Checked = .T.

Check the List. Microsoft’s ListView control v 6.0 sports checkboxes to make it easier to select items in a row.

Note: As with many controls, when you set properties in the ListView property sheet, they don’t always stay set. If you use the ListView regularly, your best bet is to sub-class it and place your default property settings in the Init method.

Microsoft TreeView version 6.0

A tree control organizes information in a hierarchy. Each branch on the tree may have several other branches, which may have its own branches and so forth, all leading to the lowest level of detail. You can see several uses of a tree control in Windows - Explorer groups files by folders, the FoxPro project manager groups files by type. In figure 1, customers are grouped by state. As the tree control has become more visible in Windows, its use in applications have grown as well.

Microsoft's TreeView control uses collections to simplify the number of methods and properties programmers need to work with. This is the component used for providing tree lists in Windows and in Visual FoxPro, including the Class Browser and Component Gallery.

A TreeView is a collection of Nodes and that's what it displays. The properties of the TreeView control itself specify the look and feel of the entire Tree. Each node has its own properties, as well.

The TreeView requires an ImageList control, which must be part of the form. See Adding Pictures below.

You can change the way the entire TreeView behaves with properties such as Style, BorderStyle and Indentation. Table 1 shows the different Style property settings that affect the TreeView appearance.

 

Style

Description

0

Text only.

1

Image and text.

2

Plus/minus icons and text.

3

Plus/minus icons, image and text.

4

Lines and text

5

Lines, image and text

6

Lines, plus/minus icons and text

7

Lines, plus/minus icons, images and text. This is the default setting.

TreeView Style - You can change the way a TreeView looks to best suit your own needs.

When viewing a list with Lines, set the LineStyle property to 0 to show lines between the parent node and the child node. Set LineStyle to 1 if you want to show a line from the Root node to each parent and each child. Setting LineStyle to 1 adds an extra level of indentation.

Set the Sorted property to True to sort the nodes alphabetically in the list.

By default, users can modify the text in each node. To make the text read-only, set the LabelEdit property to 1. See Controlling Nodes below for details on using this property.

To change the font of the TreeView, set the various properties of the contained Font object, like this:

THISFORM.TreeView.Font.Name = "Verdana"

THISFORM.TreeView.Font.Size = 8

Adding Nodes

Use the Add method of the Nodes collection to add a node to the TreeView.

THISFORM.TreeView.Nodes.Add(,,"KeyData", "Customers", 1)

THISFORM.TreeView.Nodes.Add("Customers",4,"Brooks","Brooks Brothers",1)

The parameters passed to the Add method are described below.

 

Parameter Name

Description

Reference Key

The index or key of the node that the new node is related to.

Relative Index

A number that identifies the relation to the Reference Key:

0 – First. The new node is the first in the list.  The Reference Key may be omitted when using this option

1 – Last. The new node is placed last in the list.  The Reference Key may be omitted when using this option

2 – Next (default). The new node is placed after the Parent node.

3 – Previous. The new node is placed before the parent node.

4 – Child. New node is placed as a child of the parent node

Key

A unique identifier for the new key. The Key cannot start with a number.

Text

The text to be displayed.

Image Index/Name

The index number or key name of the image to be displayed. The image is retrieved from the associated Image List.

Selected Image Index/Name

The index number or key name of the image to be displayed when the user selects the node. The image is retrieved from the associated image list.

AddMethod: Adding nodes to the TreeView. You can omit any parameter you don't need.

The Nodes collection is used to reference individual node. Each of the parameters passed to Add can be accessed and set as a property of the new node.

THISFORM.TreeView.Nodes(1).Text = "Smith & Sons"

THISFORM.TreeView.Nodes(1).Key = "Wow"

THISFORM.TreeView.Nodes(1).Image = 1

THISFORM.TreeView.Nodes(1).SelectedImage = 2

To expand a node, set the Expanded property of the node to True.

THISFORM.TreeView.Nodes(1).Expanded = .T.

Each node has properties that refer to its place in the TreeView. The Root, Parent, Child, FirstSibling, Next, Previous and LastSibling properties all point to the other nodes displayed around a node.

Adding Pictures

The TreeView control relies on the ImageList control to provide the various images that are displayed. The following code links the two together:

THISFORM.TreeView.ImageList = THISFORM.ImageList.Object

You must link the ImageList to the TreeView before you specify any images for the TreeView so the code above is best used in the Form's Init method.

Add images to the list using the ImageList's property sheet or with code like:

THISFORM.ImageList.ListImages.Add( , "Customer",LOADPICTURE("CUSTOMER.BMP"))

The ImageList needs an object pointer to the image, not the image name. VFP's LOADPICTURE() function creates such a pointer. The parameters passed to the ImageList's Add method are described below.

ListImages Add Parameters

Description

Index

An index specifying where the image is placed in order. If not specified, the image is placed at the end of the list. (optional)

Key

The unique key for the image being added (optional).

Image

An object pointer to the image (identified with LoadPicture).

Adding Images to an ImageList. An ImageList must have images in place before they can be used.

Where to Place Code

Since the TreeView is linked to the ImageList control on the same form, it's useful to place the code that fills the TreeView in methods on the form itself or to subclass the TreeView and create a Fill method. Another solution is to create a class containing both the TreeView and the ImageList. The following code adds nodes to a tree based on the Customer table.

SELECT cstate, custid, custname ;

FROM Customer ORDER BY cstate ;

INTO CURSOR tmp

LOCAL lcState, lcKey

lcState = " "

lcKey = " "

SCAN

   IF NOT cstate = lcState

      ** Add a root node

      lcstate = cstate

      THISFORM.TreeView.Nodes.Add(,,lcstate,lcState,1)

   ENDIF

  

THISFORM.TreeView.Nodes.Add(lcState, 4, ;

 custid, custname,2)

ENDSCAN

 

Data-driven TreeView. States are the parents, with each branching to a list of customers in the state.

Controlling Nodes

Once nodes are added to the tree, you need to deal with them. The Treeview provides the methods and events for interacting with the nodes.

The NodeClick event fires when the user clicks on a node in the TreeView. It is passed a single parameter, a reference to the node object.

Method TreeView.NodeClick

PARAMETERS node

LOCAL lcKey, lcText

lcKey = node.key

lcText = node.text

MESSAGEBOX("You selected customer id " + lcKey)

 

If the LabelEdit property is 0 (automatic), users may modify the text of each node. When the user starts editing a node, the BeforeLabelEdit event fires. Use the SelectedItem property to determine which node is being edited. When the user hits enter, the AfterLabelEdit event fires. The following code updates the custname field of the Customer table.

Method TreeView.AfterLabelEdit

PARAMETERS Cancel,newstring

LOCAL lcKey

lcKey = THIS.SelectedItem.Key

UPDATE Customer SET custname = newstring ;

WHERE custid = lcKey

 

To cancel the edit, set the Cancel parameter to True. For example, the following code allows only users named Andrew to edit:

Method TreeView.BeforeLabelEdit

PARAMETETER cancel

** Only I am allowed to edit the label

IF NOT "ANDREW"$UPPER(SYS(0))

cancel = .T.

ENDIF

One problem I've noted with the TreeView occurs when you call modal forms from the form containing the TreeView. The Border around the TreeView control disappears. This is primarily a cosmetic problem but it is annoying. When the form is cleared, the border returns. This problem occurs even when the form is not placed on top of the current form.

DBI Technologies List

 (ctlist.ocx)

Where the ListView enhances a list to be more visual, the List control from dbi Technologies looks more like a traditional list. However, it has some useful features not found in the ListView.

How To Use It

Drop the ctlist control on the form. At first glance, it looks like a regular list control. Like the native Visual FoxPro control, use the AddItem method to add information to the list. The difference here is that if you want to use multiple columns, you can specify all the data for an item at one time by separating the information with semi-colons:

list.list.AddItem("4;Andrew;MacNeill;AKSEL;(877) 825-9191")

 

The ListCount and ListIndex properties function like those of the native List control. ListCount returns the number of items in the list. Set the ListIndex or Selected property to highlight the desired row number. Unlike native FoxPro controls, the items are numbered from 0.

THISFORM.list.ListIndex = 0   && Highlights first row

THISFORM.list.Selected = 5    && Highlights sixth row

Use the SelectedBackColor and SelectedForeColor properties to specify the color setting of a selected row. Set the MultiSelect property to .T. to allow the selection of multiple rows.

Once an item has been added, use the ListText property to change the text of the whole column or the ListColumnText to change individual columns.

THISFORM.list.listText(2) = “4;Andrew;MacNeill;AKSEL Software;Andrew@aksel.com”

THISFORM.list.listcolumntext(0,2) = "Andrew;"

If you are using multiple columns, you have to put a semi-colon after each text item. If you don’t, other columns are cleared. The BreakChar property lets you specify the delimiter character you prefer. This is useful if you have semi-colons in your data.

Although you have to refer to your row with an index number, you can still store key information with the ctList control. Set the ListCargo property for character data or the ListData property for an integer value. Most of the ctList properties use an index parameter to specify the row (see below).

If you have more information to display, such as notes, use the ListSubText property to hold text that is displayed directly under the item. The subtext will not be displayed until you set the ListSubHeight property to a value above 0 as shown below:

THISFORM.list.ListSubText(5) = "Met with him the other week"

THISFORM.list.ListSubHeight(5) = 20

Set the MultiLine property of the ctList control to .T. to allow individual data items to occupy more than one row. Then, put CHR(13) in the text of any column to force that row to take up more than one line.

Property Name

Description

ColumnBackColor (nrow, ncolumn)

ColumnForeColor (nrow, ncolumn)

Control the foreground or background color of a column

ColumnCheckAlign (nrow, ncolumn)

Specifies the alignment of the checkbox in the column

0 – Left

1 – Right

2 – Centered (default)

ColumnCheckBox  (nrow, ncolumn)

Specifies the type of checkbox displayed in the column

0 – none

1 – 2-d checkbox

2 – 3-d checkbox

ColumnLock (ncolumn)

Lock the column width so it cannot be changed by the user

ColumnSortable (ncolumn)

Indicates whether the data in the column can be sorted

ColumnText (ncolumn)

The text displayed on the column header

ColumnTextAlign(nColumn)

Specifies the alignment of the text in the column

0 – Left

1 – Right

2 - Centered

ColumnWidth(nColumn)

The width of the column

ListCargo(nRow)

Hidden text value for a row

ListData(nRow)

Hidden integer value for a row

ListColumnCheck(nRow, ncolumn)

The value of the checkbox for the row and column (1 = selected)

ListColumnText (nrow,ncolumn)

The text of the row and column

ListFontBold (nrow)

The bold font setting of the row

ListSubHeight (nrow)

The height of the subtext for a row

ListSubText (nrow)

The subtext for a row

ListText (nrow)

The entire contents of the text for a row (columns separated with a semi-colon)

The power of array properties. The ctList control uses arrays to set the different features of each row and column.

Displaying Column Headers and Titles

The native FoxPro list control allows you to use columns but doesn't offer column headers. With the ctList control, column headers are easy.

Set the ShowHeader property to .T.. Use the AddColumn method to specify the caption and the width of each column as shown below:

THISFORM.list.ShowHeader = .T.

THISFORM.list.AddColumn("ID",50)

THISFORM.list.AddColumn("First Name",100)

THISFORM.list.AddColumn("Last Name",100)

THISFORM.list.AddColumn("Company",100)

THISFORM.list.AddColumn("Phone",100)

The ctList control also includes a TitleText property that appears above the column headers. Set the ShowTitle property to .T. to display the Title. Set the TitleBackColor and TitleForeColor properties to control the display of the title as well.

Sorting

To sort the ctList control, set the SortColumn property to the index of the desired column. Set the property to –1 to sort by the ListData property. Set the property to –2 to sort by the ListCargo. Set the SortDirection property to 1 to sort in descending order. Set the SortOnCase property to .F. to ignore case when sorting.

Displaying Images

The ctList control has a built-in ImageList control. Set the UseImageList property to .T. to enable its use. The AddImage method loads images into the ImageList. Once loaded, set the ListColumnPicture property to the index of the desired image. Unlike the ListView, you can display images in any of the columns.

THISFORM.list.UseImageList = .T.

THISFORM.list.AddImage(LOADPICTURE("CUSTOMER.BMP"))

THISFORM.list.ListColumnPicture(0,1)=1

THISFORM.list.ListColumnPicture(0,3)=1

Is It A Grid or a List?

The ctList control provides a number of properties that apply to the individual columns. Set ColumnBackColor to color individual columns in dbi. Set AlternateColor to .T. to give your list a ledger feel. By default, the odd rows receive a pale yellow, but you can set the BackColorEven and BackColorOdd properties to the desired colors.

 

Is it a Grid or a List? By changing a few properties, the ctList control looks more and more like a read-only grid.

The ctList control supports checkboxes in any column. This code adds a 3-D checkbox to the second column:

THISFORM.list.columncheckbox(2) = 2

Handling Events

The ctList control supports a similar range of events as the ListView. You can write code for Change, CheckClick, ColumnResize, ItemClick, ItemDblClick and RightClick events. Each of the Click events is passed the row and column where the click took place.

bbListView Control

The bbListView control looks like a basic list but behaves like a grid or a list view. However, whereas a list view is generally slow in loading information, the bbListView has methods that make loading information almost instant. Performance aside, the properties and events of the bbListView appear to be designed around the needs of using a list. It supports pictures (with 20 built-in images) for each row and column as well as headers. Automatic sorting and incremental searching round out a well-thought-out feature list.

Place the bbListView control on a form. It looks just like a regular list. Specify the number of columns and rows. Once these have been added, you can manually add items or fill the list with an array. Filling from an array is easy. Create an array and then call FillFromArray passing the array as a reference.

SELECT custname,street,city,state,phone FROM Customer INTO ARRAY laTmp

WITH THISFORM

   .bbList.Columns.Add(ALEN(laTmp,2))  && Adds three columns

   .bblist.Rows.Add(ALEN(laTmp,1))

   .bbList.Columns.FillFromArray(1,@laTmp)

ENDWITH

 

The performance received with the bbListView is closer to a standard FoxPro control. Using the FillFromArray method, I was able to load in a table of over 20,000 records in under 5 seconds.

You can also use the ListItem object to manually add items, changing the Text property. This approach offers more flexibility but will definitely be slower.

THISFORM.bbList.ListItem(1,1).Text = "Name"  && First Column

THISFORM.bbList.ListItem(1,2).Text = "State" && Second Column

Since the control is not data-bound, you must fill in the header names and widths manually.

WITH THISFORM.bblist

   .ColumnHeaders(1).Text = "Customer Name"

   .ColumnHeaders(2).Text = "Address"

   .ColumnHeaders(3).Text = "City"

   .ColumnHeaders(4).Text = "State"

   .ColumnHeaders(5).Text = "Phone"

   .Columns(1).Width = 100

   .Columns(2).Width = 200

   .Columns(3).Width = 100

   .Columns(4).Width = 80

   .Columns(5).Width = 100

ENDWITH

 

Users may resize each column in the bbListView. To turn this off, set the ResizeAble property to false for each individual column.

THISFORM.bblist.Columns(1).Resizeable = .F.

You can also set a column's MinimalWidth and MaximalWidth property to control how much the user can resize. If the MinimalWidth and MaximalWidth property are equal, then the column is not resizeable.

Sorting and searching the list

No list would be complete without the ability to sort. The bbListView control can sort up to 5 columns simultaneously. Instead of having to build a complicated sort within your array or table, call the SortListItems method with multiple parameters.

THISFORM.bbList.SortListItems(4,3)

 

This code sorts the list by the 4th column and then by the 3rd column (see figure 1). To sort in descending order, change the index value to *-1. So SortListItems(-4) would sort by state in descending order.

To search the list, set IncrementalSearch to true. The IncrementalSearchTimeout property sets the amount of time for the incremental search in milliseconds. This is useful for supporting users who like to have more time for searching. By default, searching is performed using the first column. Change the KeyPressBoundColumn to the desired column to search.

THISFORM.bbList.IncrementalSearch = .T.

THISFORM.bbList.KeyPressBoundColumn = 3

THISFORM.bblist.IncrementalSearchTimeout = 5000

This code changes the search to be based on the 3rd column and allows users up to 5 seconds before the incremental search is reset.

With most list controls, numeric items appear as text and are sorted accordingly. Set the TreatContentAsNumber property to .T. and the bbListView will sort the content of the column as a numeric value.

Multiple Line Mode

The MultiLineMode property displays information in multiple lines for entire columns, rows or individual listitems.

Set MultiLineMode to 1 to create new lines whenever a carriage return is in the text. Set the property to 2 to refit the text whenever horizontal width isn't enough to show the whole thing.

To use MultiLineMode property, set the RowHeight property to a value that will support showing multiple lines. By default, RowHeight is set to 15.

THISFORM.bbList.RowHeight = 20

THISFORM.bbList.Rows.Height = 15

MultiLineMode may be changed for individual columns, rows and list items.

** Change column 3 to show multiple lines

THISFORM.bbList.Columns(3).MultiLineMode = 2

** Change the first column of the second customer to show multiple lines

THISFORM.bbList.ListItem(2,1).MultiLineMode = 2

 

The bbListView control can also display pictures with any of the objects in the list. Most ActiveX controls that offer pictures require the developer to load the images into an ImageList or manually before using them. The bbListView allows you to specify your own images but also provides 20 standard images that you can access (see table 1). Set the PictureIndex property of the object to the index of the desired picture. Set the ContentType of the object to 2 to only display the image or 3 to display both the image and the text.

THISFORM.bbList.Pictures(1).Load(5,10) && Loads pre-defined image # 10

THISFORM.bbList.Pictures(2).Load(3,"C:\CHECK.ICO")

THISFORM.bbList.Columnheaders(2).PictureIndex = 1

THISFORM.bbList.Columnheaders(2).ContentType = 3

THISFORM.bbList.ListItem(1,3).PictureIndex = 2

THISFORM.bbList.ListItem(1,3).ContentType = 3

 

Set the PictureAlignment and PictureVAlignment properties to change the horizonal and vertical positioning of the image when being displayed.

One other great feature is the ability to rotate the column headers. Set the Orientation property to a value from 0-3 to rotate the text of the column header. When rotating the text, be sure to set the Height of the Column header to an adequate size.

THISFORM.bbList.ColumnHeaders.Height = 40

THISFORM.bbList.ColumnHeaders(4).Orientation = 1

 

The bbListView is great for displaying information in all types of ways. The State is rotated so it doesn't take up too much space.

Internal Picture Index

Description

1

(empty)

2

Checked box

3

Unchecked Box

4

Down arrow (dark blue)

5

Up Arrow (dark blue)

6

Down arrow (light blue)

7

Up Arrow (light blue)

8

A-Z sorting descending

9

Z-A sorting

10

Yellow flag

11

Red flag

12

Green flag

13

Purple flag

14

Blue flag

15

Green checkmark

16

Red x

17

Mail

18

Green diamond

19

Red circle

20

Person

These images are included within the control and can be loaded with bbList.Pictures(1).Load(5,nIndex). There's no need to look for pictures to do this.

The bbListView also allows you to manipulate colors for each row and column. Rows, Columns and ListItems all have BackColor, ForeColor, SelectedForeColor and SelectedBackColor properties that can be changed to highlight information. However, since the control is not data-bound, the colors must be set programmatically.

** Change all of column 3 to this color

THISFORM.bbList.Columns(3).BackColor = RGB(172,172,172)

** Change all of row 2

THISFORM.bbList.Rows(2).BackColor = 12615808

Handling Events

One of the challenges of using any control is making it work interactively with users as well as within your own code. While a lot of the setup, such as pictures and coloring, may be done when initializing the control, some features are best left to the users. The bbListView offers a wide range of events where code may be placed (see below.

A good example is automatic sorting. The following code placed in the OnHeaderLClick method makes it easy for a user to change the sort order of their list.

Method Init

** Load the images

with THIS

  .Pictures(1).Load(5,4)

  .Pictures(2).Load(5,5)

endwith

Method OnHeaderLClick

LPARAMETERS ncolumnindex, lonText, lonpicture, nxcoord, nycoord

  if nColumnIndex=0

    return

  endif

  if (this.columns(nColumnIndex).ColumnHeader.pictureindex=1  and ;

      this.columns(nColumnIndex).ColumnHeader.contenttype=3) or ;

     this.columns(nColumnIndex).ColumnHeader.contenttype=1

    this.columns(1).ColumnHeader.contenttype=1

    this.columns(2).ColumnHeader.contenttype=1

    this.columns(3).ColumnHeader.contenttype=1

    this.columns(nColumnIndex).ColumnHeader.contenttype=3

    this.columns(nColumnIndex).ColumnHeader.pictureindex=2

    this.SortListItems(nColumnIndex)

  else

    this.columns(1).ColumnHeader.contenttype=1

    this.columns(2).ColumnHeader.contenttype=1

    this.columns(3).ColumnHeader.contenttype=1

    this.columns(nColumnIndex).ColumnHeader.contenttype=3

    this.columns(nColumnIndex).ColumnHeader.pictureindex=1

    this.SortListItems(nColumnIndex*-1)

  endif 

 

Events

Fires when

AfterRowChanged (nNewRow)

User moves to a new row. The NewRow parameter is the index of the new row.

OnColumnResize (nColumn, nNewWidth)

User changes the size of a column.

OnEndOfItemEdit

User has hit enter when editing an item or clicked outside of the edit box.

OnHeaderLClick

OnHeaderLDoubleClick

OnHeaderRClick

OnHeaderRDoubleClick

User clicked one of the column headers. These methods all receive the same parameters:

nColIndex – numeric index of the column

lOnText – True if the user clicked on the text of the header

lOnImage – True if the user clicked on the Image of the header

nXCoord – X coordinate of where the user clicked

nYCoord – Y coordinate of where the user clicked

 

OnItemLClick

OnItemLDoubleClick

OnItemRClick

OnItemRDoubleClick

User clicked one of the items in the list. These methods all receive the same parameters:

nRowIndex – numeric index of the row

nColIndex – numeric index of the column

lOnText – True if the user clicked on the text of the item

lOnImage – True if the user clicked on the image of the item

nXCoord – X coordinate of where the user clicked

nYCoord – Y coordinate of where the user clicked

OnItemNotFound

No item was found during an incremental search.

OnItemSelection

User selects an item by double-clicking it or pressing enter.

This method receives a single parameter:

NRowIndex – the row of the item

OnEditKeyPress

OnEditKeyRelease

User presses or releases a key while editing.

OnKeyPress

OnKeyRelease

User presses or releases a key while viewing the list.

There aren't many events but they allow a developer to build powerful list-oriented applications.

What about Editing?

The bbListView control supports in-place editing as well. Call the StartItemEdit() method of a ListItem to start editing. Editing ends when the user clicks outside of the item or hits Enter. At that time, the OnEndOfItemEdit event fires, allowing you to update the table or source of information. Since there is no property setting to turn this feature on or off, you must add the functionality in manually.

One difficulty with the bbListView control is the use of fonts. There is no specific property for individual properties. Fonts are controlled through a property named LogicalFonts. This property is a collection of font settings that you can set. The default font for the list is LogicalFonts(1). The following code changes the default font for the bbListView.

WITH THISFORM.bblistView

   .LogicalFonts(1).Name = "Arial"

   .LogicalFonts(1).Size = 10

   .LogicalFonts(1).Bold = .T.  

   .Refresh()

ENDWITH

You can define up to 100 different font styles in bbListView. Once defined, you can change a particular list item or column's style by changing the LogicalFontIndex.

** This resets the second column to using the font style of

** LogicalFonts(3)

THISFORM.bbListView.Columns(2).LogicalFontIndex = 3

 

Eclipse Cabinet Control

The Eclipse Cabinet control makes file compression a breeze. It stores information into the standard CAB format which is also great because the format is known more to developers than it is to users who usually prefer the zip format.  The EclipseCabinet control is also a great example of a FREE control that developers can start using easily.

Compressing Files

LOCAL loCompress

loCompress = CREATEOBJECT(“EclipseCabinet99.ecCompress”)

loCompress.FileName = “MYFILE.CAB”)

loCompress.FILES.ADD("MASTERS.TXT")

loCompress.Compress( )

Extracting Files

LOCAL loExtract

loExtract = CREATEOBJECT(“EclipseCabinet99.ecExtract”)

loExtract.FileName = “MYFILE.CAB”)

loExtract.ExtractAll(“C:\Extracted Files\”) && to the directory

Freeware vs. Buyware Products

Should you even consider looking at free or shareware controls? Absolutely. I had a conversation with a friend who was absolutely aghast at the idea that we should look at freeware products. The reasons mentioned were very valid: limited support, no definition upgrade path, you get what you paid for. But the arguments FOR supporting freeware products, indeed ANY control are the same: does it work for your application or not?

That, regardless of where you got the control from, should be the ruling decision maker.