The Seeker Control
by Peter Rorlick [dBVIPS], co-founder of  Montreal Business Software. He has been developing xbase solutions since 1981.

Whatís a Seeker?

A Seeker is a custom control class that was written by Ken Chan a few years ago.  You can put a Seeker control (an object of the Seeker class) on any form.  It looks like an entryfield, but itís not for data entry.  This control lets the user do incremental searching in a rowset or table.

Seeker.CC is distributed with Visual dBASE 7, and an earlier version of Seeker.CC is available for VdB 5.x in Ken Mayerís dUFLP5 library.

Whatís incremental searching?

Suppose you have a grid showing different types of fruit in alphabetical order ó Apples, Bananas, Blueberries, Cherries, and so on.  The idea is that if you type a B, the row pointer moves to Bananas, then you type an L and the pointer moves to Blueberries ó because Blueberries is the first row that matches BL.

Itís not hard to imagine how such a mechanism could be extremely useful ó or even vital ó if, for example, you had to find Rorlick, Peter in a very long list of names.  All youíd need to do would be to type RORL and youíd probably already be pointing at the row you were looking for.  Thatís much more efficient than using a scrollbar (particularly the VdB7 gridís scrollbar!) to find a precise location amongst thousands of rows.

How can I use a Seeker?

Letís create a sample form right now that employs a Seeker.  First, in the Command window, type:
set procedure to "C:\Program Files\Borland\Visual dBASE\custom\" additive

This will tell dBASE where to find the source code thatís needed for this custom control.  It also loads the custom class definition into memory and ensures that the Seeker will appear on the component palette in the Form Designer.

Next, weíll prepare the data for our sample form.  Again in the Command window, type:
cd "C:\Program Files\Borland\Visual dBASE\Samples\Mugs\Tables"

In the Navigator, click on the Tables tab, right-click on Customer.dbf, and select the Design Table menu option.  Now click on the Structure menu, and select the Manage Indexes option.

Weíre going to add a new index tag to the table, so click on the New button.  Click on the Specify with expression radio button, and in the Index key expression field, type in:
left(upper(trim(Customer->"Last Name")+','+Customer->"First Name")+space(20),40)

In the Index name field, type in: UpperName.  Click on the OK button.  Click the Close button.  Click the X button to close the Table Designer, and click on Yes to save the changes.

Why did we bother to create a new index tag?  For two reasons: First, so that weíll be able to work with the customer names in true alphabetical order.  And second, the Seeker requires that the active index must be upper-case. Note that we use the LEFT() function to ensure that every index key value is exactly the same length, otherwise the index will not behave properly.

Now letís start designing a new form.  Click on File...New...Form, then click on Designer.  Drag Customer.dbf from the Navigator onto the form design surface.  Click on the SQL icon that just appeared on the form. At this point the Inspector should be showing you the properties of the Customer1 query.  If you donít see the inspector, press F11 and click on the Properties tab.  In the Inspector, click on the word ďObjectĒ thatís shown for the Rowset property.  Now click on the I-button, which drills down to inspect the properties of the rowset.  Set the indexName property to UPPERNAME.

From the Standard tab of the Component palette, drag a grid onto the form.  Resize the grid (you can drag its bottom right corner) to make it bigger.  In the inspector, set the gridís Datalink property to Customer1.  Now click on the Custom tab of the Component palette, and drag a Seeker onto the form.  You might want to resize the form, and move and resize the objects on it so that they look something like this:

Press F2 to save and run the form.  Youíll have to give it a name, so save it as SeekerTest.wfm.  Type some stuff into the Seeker, and see how it behaves.  Type in MAXWELL,M and watch what happens to the row pointer as you type each key.

How does it work?

The Seeker class inherits from the native EntryField class, and it has a Key event handler that intercepts all non-navigational keystrokes while the entryfield has focus.  Every keystroke that is typed into the entryfield is processed through the Key() method, which performs a seek in the appropriate table or rowset.  In truth, itís not important to know how Seeker works.  But if youíre really interested in understanding whatís under the hood, add the line SET STEP ON at the start of the Key() method in Seeker.CC, and run SeekerTest.wfm again. When you type anything into the Seeker, the debugger will be invoked, and you can step through the lines as they get executed.

Things to remember

An even better Seeker

At the end of this article, there is a link to download the ZSeeker.CC, written by this author.  ZSeeker enhances Ken Chanís original Seeker, by adding a few improvements:

In my applications, almost every grid is accompanied by a Seeker.  Itís so useful and so easy to include, thereís no reason why you shouldnít use it often.  Users love the Seeker control ó and no wonder ó I canít imagine a more efficient way to locate a row.  After a while, youíll find yourself using other software, and youíll catch yourself saying, ďDarn it, why doesnít this thing have a Seeker?Ē

To download the ZSeeker,  click here
(itís a 1.5 Kb zipped file)