When using a large table or cursor (over 500 records) as the RowSource for
a Combo Box, you may start to see a slow down in the Combo Box performance.
This article shows how to create a control that has the basic Combo Box
functionality but does not have the same performance slow down that the
standard Combo Box has when working with a large table.
The fastest control for working with a large number of records is the Grid.
However, there are times when there is not enough space on a form for a
grid or when the developer needs the functionality of a Combo Box but
without the performance overhead that the standard Combo Box has. The
following example shows how to create a custom Combo Box using a Grid, Text
Box, and Command Button. If you are not familiar with creating or using
visual classes, please see chapter 10 of the Microsoft Visual FoxPro
Developer's Guide.
- Create a new class named NewPopup based on a Container, and save it in
Mylib.
- Add the following new properties and methods to the NewPopup container:
cSearchString as a Property
tOutTime as a Property
Pop as a Method
Search as a Method
- Set the following properties for the NewPopup container:
Width = 128
Height = 185
BackStyle = 0
BorderWidth = 0
tOutTime = .NULL.
- Add a Text Box to the container and set the following properties:
Height = 26
Left = 2
ReadOnly = .T. && If you want to be able to edit the data in
** the text box leave this property set to .F.
Top = 2
Width = 111
- Enter the following code in the KeyPress Event for Text1:
IF nKeyCode = 160
This.Parent.Command1.Click()
** Makes the grid appear when you press the ALT+DOWNARROW key
ENDIF
- Add a Command Button to the container and set the following properties:
Top = 2
Left = 112
Height = 26
Width = 13
FontBold = .F.
FontName = Wingdings
FontSize = 6
Caption = ALT + 0234
** When you hold down the ALT key and press the NUMBER keys, it
** inserts a down arrow character for the Caption
- Enter the following code in the Click Event for Command1:
This.Parent.Grid1.Visible = .T. && Make the Grid visible
This.Parent.Zorder(0)
** Places the container in front of other objects
This.Parent.Grid1.Column1.Text1.SetFocus
IF !ISNULL(This.Parent.tOutTime)
KEYBOARD '{Enter}'
** Forces the Grid to Activate
** Without this, the grid would not work properly when you
** enter it the second time.
ENDIF
- Add a Grid to the container and set the following properties:
ColumnCount = 1
DeleteMark = .F.
GridLines = 0
GridLineWidth = 0
HeaderHeight = 0
Height = 156
Left = 2
MousePointer = 1
ReadOnly = .F.
RecordMark = .F.
ScrollBars = 2
Top = 27
Visible = .F.
Width = 123
- Enter the following code in the AfterRowColChange Event of Grid1:
This.Parent.Text1.Value = This.Column1.Text1.Value
- Set the following properties for Column1 in Grid1:
Width = 124
Sparse = .F.
- Set the following properties for Text1 in Column1 of Grid1:
BorderStyle = 0
Format = K
HideSelection = .F.
MousePointer = 1
SpecialEffect = 1
- Enter the following code in the Click Event of Text1 in Column1 of
Grid1:
This.Parent.Parent.Parent.Pop()
- Enter the following code in the KeyPress Event of Text1 in Column1 of
Grid1:
IF nKeyCode = 13 && Then hit the ENTER key
This.Parent.Parent.Parent.Pop()
ENDIF
IF (nKeyCode > 48 AND nKeyCode < 58) OR ;
(nKeyCode > 64 AND nKeyCode < 123)
** Calls the search method if you hit a letter or numeric key
This.Parent.Parent.Parent.Search(nKeyCode)
ENDIF
- Enter the following code in the GotFocus Event of the NewPopup
Container:
SET BELL OFF
- Enter the following code in the Init Event of the NewPopUp Container:
This.Grid1.HeaderHeight = 0
** When you modify an instance of the class in a Form and modify
** some of the grid setting, it will change the HeaderHeight property
** back to a default size. This line of code will set the
** HeaderHeight back to 0 at run time
This.Zorder(1)
** Moves the container behind any controls that it may be on top of
nFieldlen = FSIZE(This.Grid1.Column1.ControlSource)
** resize the grid based on the field size and font
IF This.Width < (nFieldlen * ;
FONTMETRIC(6,This.Grid1.FontName,This.Grid1.FontSize,"B"))+12
This.Width = (nFieldlen * ;
FONTMETRIC(6,This.Grid1.FontName,This.Grid1.FontSize,"B"))+12
This.Grid1.Width = (nFieldlen * ;
FONTMETRIC(6,This.Grid1.FontName,This.Grid1.FontSize,"B"))+10
This.Grid1.Column1.Width = (nFieldlen * ;
FONTMETRIC(6,This.Grid1.FontName,This.Grid1.FontSize,"B"))
ENDIF
- Enter the following code in the LostFocus Event of the NewPopUp
Container:
SET BELL ON
This.Grid1.Visible = .F.
This.ZOrder(1)
** Moves the container behind any object it is over
- Enter the following code in the Pop Method of the NewPopUp
Container:
This.Text1.SetFocus
This.Grid1.Visible = .F.
This.ZOrder(1)
** Moves the container behind any object it is over
- Enter the following code in the Search Method of the NewPopUp
Container:
**Does an incremental search of the table in the grid
LPARAMETERS nKeyPress
cField = This.Grid1.Column1.ControlSource
nRecord=RECNO()
tInTime = DateTime()
IF !ISNULL(This.tOutTime)
IF (tInTime - This.tOutTime)<= 1
This.cSearchString = This.cSearchString + CHR(nKeyPress)
LOCATE FOR UPPER(LEFT(&cField,LEN(This.cSearchString))) = ;
UPPER(This.cSearchString)
ELSE
This.cSearchString=""
This.cSearchString = CHR(nKeyPress)
LOCATE FOR UPPER(LEFT(&cField,1)) = UPPER(This.cSearchString)
ENDIF
IF FOUND()
This.Grid1.Refresh()
ELSE
GO nRecord
This.Grid1.Refresh()
ENDIF
ELSE
This.cSearchString=""
This.cSearchString = CHR(nKeyPress)
LOCATE FOR UPPER(LEFT(&cField,1)) = UPPER(This.cSearchString)
IF FOUND()
This.Grid1.Refresh()
ELSE
GO nRecord
This.Grid1.Refresh()
ENDIF
ENDIF
This.tOutTime = DateTime()
- Save and close the class.
- Create a form and add the NewPopUp container to the form.
- Set the RowSource of the Grid1 in the NewPopUp container to the table
of your choice.
- Set the ControlSource of Column1 of Grid1 in the NewPopUp container.
- Save and run the Form. Click the Command Button to display the Grid,
and then type the first letter of something you wish to find. Make a
selection by either clicking on your choice or using the ARROW key
to highlight your choice and then pressing the ENTER key. You will see
the Grid disappear and the value of your choice appear in the text box.