Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

How can I create a SuperCombo?

Combo Box

How can I create a SuperCombo?

by  ChrisRChamberlain  Posted    (Edited  )
SuperCombo is a "collection" of three base classes - Textbox, CommandButton and Grid, and a custom class, cusSuperCombo.

The example and code that follows is for the simplest version of SuperCombo - that is a single column grid, the [color blue].RecordSource[/color] of which is a lookup table. Only one instance of cmdSuperCombo and grdSuperCombo is required for this particular version, regardless of how many textboxes you wish to convert, plus the custom class, cusSuperCombo.

The code can be used as a foundation for far more sophisticated versions.

By adding or removing code in the [color blue].GotFocus()[/color], [color blue].InteractiveChange()[/color], [color blue].KeyPress()[/color] and [color blue].LostFocus()[/color] events of a textbox, any textbox on any form can be converted to or from a SuperCombo.

In the [color blue].GotFocus()[/color] event of the textbox, cmdSuperCombo and grdSuperCombo are "called" into position - when the textbox loses focus, they disappear.

The grid is accessed by the down arrow or mouse click. Once in the grid, Enter or a mouse click will select the record. Tab will take the user to the next control without replacing the textbox value with the value from the grid. Pressing enter in the textbox replaces the textbox value with the value from the grid.

If the default behaviour doen't suit, it can be easily modified.

In the [color blue].InteractiveChange()[/color] event of the textbox, the [color blue].mFindData()[/color] incremental search method of grdCombo is fired. (It's important to note that an indexed lookup table is required for this example)


Why use a SuperCombo?

Comboboxes are notoriously slow and unreliable where serious numbers of records are concerned. They can be visually intrusive - a SuperCombo only appears when the textbox gets focus.

Well constructed SuperCombos utilising incremental searches can greatly speed up the data entry process!

As the list part of the SuperCombo is a grid, it is up to a developer's imagination as to what the grid may contain - checkboxes, images, commandbuttons, memo fields etc.

The largely uncommented code is broken down into 2 sections, cusSuperCombo class code, and a demo form, (you need to substitute your own table), and should be fairly easy to follow and reassemble.

[color green]
**************************************************
*-- Class: cussupercombo (c:\supercombo9\supercombo.vcx)
*-- ParentClass: custom
*-- BaseClass: custom
*-- Time Stamp: 05/08/02 12:15:10 PM
*[/color][color blue]
DEFINE CLASS cussupercombo AS custom


Height = 24
Width = 24
nrecno = 0
Name = "cussupercombo"
nextrawidth = .F.
ccmdbuttonname = .F.
clookupfield = .F.
clookuptable = .F.
clookuptablefield = .F.
clookuptableindex = .F.
ctextboxname = .F.
cdisplayfield = .F.


PROCEDURE mcallgrid
LPARAMETERS TextBoxName,;
LookupTableField,;
LookupTableIndex,;
ExtraWidth,;
DisplayField,;
ColumnsCount

IF !EMPTY(TextBoxName) AND !EMPTY(LookupTableField)
WITH THIS
.cTextBoxName = TextBoxName[/color][color green] && Name of textbox[/color][color blue]

.cLookupTableField = LookupTableField [/color][color green]&& Table.field[/color][color blue]
.cLookupField = SUBS(.cLookupTableField,; [/color][color green]&& field[/color][color blue]
AT([.],.cLookupTableField) + 1,;
LEN(.cLookupTableField))
.cLookupTable = SUBS(.cLookupTableField ,; [/color][color green]&& Table[/color][color blue]
1,AT([.],.cLookupTableField) - 1)
IF !EMPTY(LookupTableIndex)
.cLookupTableIndex = LookupTableIndex [/color][color green]&& Index[/color][color blue]
ELSE
.cLookupTableIndex = []
ENDI

SET ORDER TO .cLookupField IN .cLookupTable

IF !EMPTY(ExtraWidth)[/color][color green]&& Extra pixels on width[/color][color blue]
.nExtraWidth = ExtraWidth
ELSE
.nExtraWidth = 0
ENDI
IF !EMPTY(DisplayField)
.cDisplayField = DisplayField
ELSE
.cDisplayField = []
ENDI
.nRecno = RECNO(.cLookupTable)

[/color][color green]* Get grid positions[/color][color blue]
lnLeft = [THISFORM.] ;
+ .cTextBoxName ;
+ [.Left]
lnTop = [THISFORM.] ;
+ .cTextBoxName ;
+ [.Top + THISFORM.] ;
+ .cTextBoxName ;
+ [.Height]
lnWidth = [THISFORM.] ;
+ .cTextBoxName ;
+ [.Width + 16]
IF !EMPTY(ExtraWidth)
lnWidth = [THISFORM.] ;
+ .cTextBoxName ;
+ [.Width + 16 + THIS.nExtraWidth]
ENDI
* Setup grid
DO CASE
CASE ColumnsCount = 1
WITH THISFORM.grdSuperCombo
.Left = EVAL(lnLeft)
.Top = EVAL(lnTop)
.Width = EVAL(lnWidth)
.Column1.Width = EVAL(lnWidth)
.RecordSource = THIS.cLookupTable
IF !EMPTY(THIS.cDisplayField)
.Column1.ControlSource = THIS.cDisplayField
ELSE
.Column1.ControlSource = THIS.cLookupTableField
ENDI

.Visible = .T.
ENDW
ENDC

[/color][color green]* Get cmdCOMBO positions[/color][color blue]
lnLeft = [THISFORM.] ;
+ .cTextBoxName ;
+ [.Left + THISFORM.] ;
+ .cTextBoxName ;
+ [.Width]
lnTop = [THISFORM.] ;
+ .cTextBoxName ;
+ [.Top + 2]

[/color][color green]* Setup cmdCOMBO[/color][color blue]
WITH THISFORM.cmdSuperCombo
.Left = EVAL(lnLeft)
.Top = EVAL(lnTop)
.Visible = .T.
ENDW
ENDW
ENDI
ENDPROC


PROCEDURE mfinddata
LPARAMETERS TextBoxValue

WITH THIS
lcAlias = ALIAS()
lcOrder = ORDER()
[/color][color green]*[/color][color blue]
SELE (.cLookupTable) [/color][color green]&& Select lookup table[/color][color blue]
IF EMPTY(.cLookupTableIndex)
SET ORDER TO TAG (.cLookupField) [/color][color green]&& Select table order[/color][color blue]
ELSE
SET ORDER TO TAG (.cLookupTableIndex) [/color][color green]&& Select table order[/color][color blue]
ENDI
[/color][color green]*[/color][color blue]
lcField = .cLookupTableField [/color][color green]&& Check out field type
*[/color][color blue]
DO CASE
CASE VARTYPE(&lcField) = [D]
SEEK DTOS(TextBoxValue)
CASE VARTYPE(&lcField) = [C]
SET NEAR ON
SEEK UPPE(ALLT(TextBoxValue))
SET NEAR OFF
ENDC
[/color][color green]*[/color][color blue]
.nRecNo = RECN(.cLookupTable)
THISFORM.grdSuperCombo.Refresh()
[/color][color green]*[/color][color blue]
IF !EMPTY(lcAlias) [/color][color green]&& Select original table and order[/color][color blue]
SELE (lcAlias)
ENDI
[/color][color green]*[/color][color blue]
IF !EMPTY(lcOrder)
SET ORDER TO TAG (lcOrder)
ENDI
ENDW
ENDPROC


ENDDEFINE
[/color][color green]*
*-- EndDefine: cussupercombo
**************************************************
[/color][color blue]
PUBLIC oform1

SET CLASSLIB TO c:\supercombo9\supercombo.vcx ADDITIVE

oform1=NEWOBJECT("form1")
oform1.Show
RETURN

[/color][color green]
**************************************************
*-- Form: form1 (c:\supercombo9\form3.scx)
*-- ParentClass: form
*-- BaseClass: form
*-- Time Stamp: 05/08/02 01:12:11 PM
*[/color][color blue]
DEFINE CLASS form1 AS form


Top = 0
Left = 0
Height = 251
Width = 489
DoCreate = .T.
Tag = "Grid"
BorderStyle = 2
Caption = "Form1"
WindowState = 0
Name = "Form1"


ADD OBJECT command1 AS commandbutton WITH ;
Top = 204, ;
Left = 384, ;
Height = 27, ;
Width = 84, ;
Caption = "Close", ;
TabIndex = 5, ;
Name = "Command1"


ADD OBJECT text1 AS textbox WITH ;
Height = 23, ;
Left = 12, ;
TabIndex = 1, ;
Top = 24, ;
Width = 100, ;
Name = "Text1"


ADD OBJECT text2 AS textbox WITH ;
Height = 23, ;
Left = 132, ;
TabIndex = 2, ;
Top = 24, ;
Width = 100, ;
Name = "Text2"


ADD OBJECT cussupercombo AS cussupercombo WITH ;
Top = 84, ;
Left = 12, ;
Height = 24, ;
Width = 24, ;
Name = "cusSuperCombo"


ADD OBJECT grdsupercombo AS grid WITH ;
ColumnCount = 1, ;
DeleteMark = .F., ;
GridLines = 0, ;
HeaderHeight = 0, ;
Height = 121, ;
Left = 348, ;
RecordMark = .F., ;
ScrollBars = 2, ;
TabIndex = 6, ;
TabStop = .F., ;
Top = 72, ;
Width = 126, ;
Name = "grdSuperCombo", ;
Column1.Width = 131, ;
Column1.Name = "Column1"


ADD OBJECT form1.grdsupercombo.column1.header1 AS header WITH ;
Caption = "Header1", ;
Name = "Header1"


ADD OBJECT form1.grdsupercombo.column1.text1 AS textbox WITH ;
BorderStyle = 0, ;
Margin = 0, ;
ForeColor = RGB(0,0,0), ;
BackColor = RGB(255,255,255), ;
Name = "Text1"


ADD OBJECT cmdsupercombo AS commandbutton WITH ;
Top = 72, ;
Left = 324, ;
Height = 20, ;
Width = 16, ;
Picture = "smalldnarrow.bmp", ;
Caption = "", ;
TabIndex = 7, ;
TabStop = .F., ;
Name = "cmdSuperCombo"


PROCEDURE Load
SET SAFE OFF
SET CLASSLIB TO supercombo ADDITIVE
ENDPROC

PROCEDURE command1.Click
THISFORM.Release
ENDPROC

PROCEDURE text1.LostFocus
WITH THISFORM
DO CASE
CASE LASTKEY() = 9 ;
OR LASTKEY() = 13 ;
OR LASTKEY() = 15
DODEFAULT()
IF THIS.Name # THISFORM.cusSuperCombo.cTextBoxName
.cmdSuperCombo.Left = 1000
.grdSuperCombo.Left = 1000
ENDI
CASE LASTKEY() = 24 ;
AND .cmdSuperCombo.Left # 1000
.grdSuperCombo.SetFocus()
ENDC
ENDW
ENDPROC


PROCEDURE text1.GotFocus
WITH THIS
IF !USED([make])
USE ADDBS(GETENV([TEMP])) ;
+ [make] ;
IN 0 && Lookup table
ENDI
ENDW
THISFORM.cusSuperCombo.mCallGrid(THIS.Name,[make.make],[],0,[],1)
[/color][color green]*!* Change TABLENAME.field parameter to suit[/color][color blue]
ENDPROC


PROCEDURE text1.InteractiveChange
WITH THISFORM
IF .grdSuperCombo.Left # 1000
.cusSuperCombo.mFindData(THIS.Value)
ENDI
ENDW
ENDPROC


PROCEDURE grdsupercombo.Init
WITH THIS
.SetAll([DynamicBackColor] ,;
"IIF(RECNO() = THISFORM.cusSuperCombo.nRecNo ,;
RGB(0,0,128) ,;
RGB(255,255,255))" ,;
[Column])
.SetAll([DynamicForeColor] ,;
"IIF(RECNO() = THISFORM.cusSuperCombo.nRecNo ,;
RGB(255,255,255) ,;
RGB(0,0,0))" ,;
[Column])
.Refresh()
ENDW
ENDPROC


PROCEDURE grdsupercombo.AfterRowColChange
LPARAMETERS nColIndex

THISFORM.cusSuperCombo.nRecno = RECN()
THIS.Refresh()
ENDPROC


PROCEDURE text1.KeyPress
LPARAMETERS nKeyCode, nShiftAltCtrl

WITH THIS
DO CASE
CASE nKeyCode = 5 [/color][color green]&& Up arrow[/color][color blue]
*
CASE nKeyCode = 9 [/color][color green]&& Tab[/color][color blue]
.Parent.Parent.Visible = .F.
EVAL([THISFORM.] ;
+ THISFORM.cusSuperCombo.cTextBoxName ;
+ [.SetFocus()])
KEYBOARD [{TAB}]
CASE nKeyCode = 13 [/color][color green]&& Enter[/color][color blue]
.Parent.Parent.Visible = .F.
lcValue = ([THISFORM.] ;
+ THISFORM.cusSuperCombo.cTextBoxName ;
+ [.Value = THIS.Value])
&lcValue
EVAL([THISFORM.] ;
+ THISFORM.cusSuperCombo.cTextBoxName ;
+ [.SetFocus()])
KEYBOARD [{TAB}]
CASE nKeyCode = 24 && Dn arrow
[/color][color green]*[/color][color blue]
ENDC
ENDW
ENDPROC


PROCEDURE text1.Click
lcValue = ([THISFORM.] ;
+ THISFORM.cusSuperCombo.cTextBoxName ;
+ [.Value = THIS.Value])
&lcValue

EVAL([THISFORM.] ;
+ THISFORM.cusSuperCombo.cTextBoxName ;
+ [.SetFocus()])

KEYBOARD [{TAB}]

WITH THISFORM
.cmdSuperCombo.Left = 1000
.grdSuperCombo.Left = 1000
ENDW
ENDPROC


PROCEDURE cmdsupercombo.Click
WITH THISFORM.grdSuperCombo
IF .Visible = .T.
.Visible = .F.
ELSE
.Visible = .T.
ENDI
ENDW
ENDPROC


ENDDEFINE[/color][color green]
*
*-- EndDefine: form1
**************************************************[/color]
FAQ184-2483 - answering getting answered.​
Chris [pc2]
[link http://www.pdfcommander.com]PDFcommander.com[/link]
[link http://www.pdfcommander.co.uk]PDFcommander.co.uk[/link]
Register to rate this FAQ  : BAD 1 2 3 4 5 6 7 8 9 10 GOOD
Please Note: 1 is Bad, 10 is Good :-)

Part and Inventory Search

Back
Top