AzraSound
asked on
Combobox auto-selecting entries
i have a rather automated system set up for a current program i am constructing. one of the forms serves as somewhat of a property list (it can be thought of as similar to the property list used in the VB IDE). it is simply a flexgrid which allows for in-place editing, and depending on the type of data being entered, either a textbox, or combobox, or even another grid will appear.
the problem arises from the fact that there is certain data we must store which we offer a combobox list of suggested, or recommended, values, but that the user has the ability to override with their own custom value if they wish. using a combobox seems acceptable since it allows for selection from our list, plus, gives the user the ability to manually type in their own value (with style set to DropDown Combo). however, if they enter a value that starts with one of the values in the list, that list item is automatically selected and takes the place of their custom value as the combobox's text when the combobox drpos down. for example:
Private Sub Form_Load()
With Combo1
.AddItem "12.34"
.AddItem "23.45"
.AddItem "34.56"
.Text = "3"
End With
End Sub
now if you run the program, "3" shows in the combobox, but once you dropdown, "34.56" becomes selected and shows as the new value. is there an elegant way around this? perhaps a property or API call I am not familiar with? changes in the UI will most likely not be allowed.
P.S. i will add points to this for a good solution - just looking for ideas first
the problem arises from the fact that there is certain data we must store which we offer a combobox list of suggested, or recommended, values, but that the user has the ability to override with their own custom value if they wish. using a combobox seems acceptable since it allows for selection from our list, plus, gives the user the ability to manually type in their own value (with style set to DropDown Combo). however, if they enter a value that starts with one of the values in the list, that list item is automatically selected and takes the place of their custom value as the combobox's text when the combobox drpos down. for example:
Private Sub Form_Load()
With Combo1
.AddItem "12.34"
.AddItem "23.45"
.AddItem "34.56"
.Text = "3"
End With
End Sub
now if you run the program, "3" shows in the combobox, but once you dropdown, "34.56" becomes selected and shows as the new value. is there an elegant way around this? perhaps a property or API call I am not familiar with? changes in the UI will most likely not be allowed.
P.S. i will add points to this for a good solution - just looking for ideas first
Azra: I posted a points question for you on 6/30...
this may work:
you can call it from keypress event or from change
Public Sub TypeAheadCombo(ljCombo As ComboBox)
Dim lviIndex As Integer
Dim lvsKeyString As String
Dim lviKeyLen As Integer
lvsKeyString = ljCombo.Text
lviKeyLen = Len(lvsKeyString)
If lviKeyLen > 0 Then
With ljCombo
lviIndex = SrchComboList(.hWnd, lvsKeyString, False)
If lviIndex <> Item_Not_Found Then
'.SetFocus
.ListIndex = -1
.ListIndex = lviIndex
.SelStart = lviKeyLen
.SelLength = Len(.Text) - lviKeyLen
End If
End With
End If
End Sub
Public Function SrchComboList(hWnd As Long, _
lvsFind As String, _
Optional fExact As Boolean = False) As Long
'Finds an entry in a combo box that matches the specified prefix.
'This search is not case-sensitive.
'Returns:
'if found - a valid listindex
'Else -1
Dim lvlSearchType As Long
If Len(lvsFind) = 0 Then
SrchComboList = Item_Not_Found
Exit Function
End If
Select Case fExact
Case True
lvlSearchType = CB_FINDSTRINGEXACT
Case False
lvlSearchType = CB_FINDSTRING
End Select
SrchComboList = SendMessageByString(hWnd, lvlSearchType, -1, lvsFind)
End Function
Private Declare Function SendMessageByString Lib "user32" Alias "SendMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As String) As Long
you can call it from keypress event or from change
Public Sub TypeAheadCombo(ljCombo As ComboBox)
Dim lviIndex As Integer
Dim lvsKeyString As String
Dim lviKeyLen As Integer
lvsKeyString = ljCombo.Text
lviKeyLen = Len(lvsKeyString)
If lviKeyLen > 0 Then
With ljCombo
lviIndex = SrchComboList(.hWnd, lvsKeyString, False)
If lviIndex <> Item_Not_Found Then
'.SetFocus
.ListIndex = -1
.ListIndex = lviIndex
.SelStart = lviKeyLen
.SelLength = Len(.Text) - lviKeyLen
End If
End With
End If
End Sub
Public Function SrchComboList(hWnd As Long, _
lvsFind As String, _
Optional fExact As Boolean = False) As Long
'Finds an entry in a combo box that matches the specified prefix.
'This search is not case-sensitive.
'Returns:
'if found - a valid listindex
'Else -1
Dim lvlSearchType As Long
If Len(lvsFind) = 0 Then
SrchComboList = Item_Not_Found
Exit Function
End If
Select Case fExact
Case True
lvlSearchType = CB_FINDSTRINGEXACT
Case False
lvlSearchType = CB_FINDSTRING
End Select
SrchComboList = SendMessageByString(hWnd, lvlSearchType, -1, lvsFind)
End Function
Private Declare Function SendMessageByString Lib "user32" Alias "SendMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As String) As Long
Hey AZ!
If you need a quick patch that works, I've got one for you.
Place a textbox without a border on the combo. Align it accordingly so that it is not noticable, and the numbers of both the textbox and combobox line up. Then in code add the following
Private Sub Combo1_Change()
Text1.Text = Combo1.Text
End Sub
Private Sub Combo1_Click()
Text1.Text = Combo1.Text
End Sub
It will look and feel like your combo, but will not change the value when you hit the dropdown method.
Thoughts?
If you need a quick patch that works, I've got one for you.
Place a textbox without a border on the combo. Align it accordingly so that it is not noticable, and the numbers of both the textbox and combobox line up. Then in code add the following
Private Sub Combo1_Change()
Text1.Text = Combo1.Text
End Sub
Private Sub Combo1_Click()
Text1.Text = Combo1.Text
End Sub
It will look and feel like your combo, but will not change the value when you hit the dropdown method.
Thoughts?
ASKER
thanks Dave! under normal conditions, this would definitely be a suitable solution, but due to the nature of the UI, this is a bit difficult. because i have this "property list" of a bit more than 50 entries, i have a bit of code in place for dynamically positioning a textbox, or combobox, or even another grid depending on the type of data that particular "property", or piece of data, holds. i do see how i can go back and rewrite a lot of the UI code to use this textbox workaround, which i think i would just do for every combobox entry since it shouldnt affect any of those entries that do not suffer from this problem. if nothing better appears, i guess i will just have to do this. keep the suggestions coming!
you will save yourself a lot of time and your company a lot of money(paying you to figure this out) by just buying one. I have used true dbcombo and like it. sheridan also has one.
Can you make .Text at least 2 chars long by adding space? i.e. replace:
.Text = "3"
with:
.Text = ""
.SelText = " 3"
.Text = "3"
with:
.Text = ""
.SelText = " 3"
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
>>I have used true dbcombo and like it. sheridan also has one.
do they offer some sort of property that turns this "feature" on/off? can you give me some costs for these components?
>>Can you make .Text at least 2 chars long by adding space?
very interesting idea ameba! i'll play with it and see if it'll work.
do they offer some sort of property that turns this "feature" on/off? can you give me some costs for these components?
>>Can you make .Text at least 2 chars long by adding space?
very interesting idea ameba! i'll play with it and see if it'll work.
> keep the suggestions coming!
OK, add ImageCombo control (MS Windows Common Controls)
Private Sub Form_Load()
With ImageCombo1.ComboItems
.Add , , "12.34"
.Add , , "23.45"
.Add , , "34.56"
ImageCombo1.Text = "3"
End With
End Sub
OK, add ImageCombo control (MS Windows Common Controls)
Private Sub Form_Load()
With ImageCombo1.ComboItems
.Add , , "12.34"
.Add , , "23.45"
.Add , , "34.56"
ImageCombo1.Text = "3"
End With
End Sub
Open a form in a new vb project and add a combo box "Combo1" and paste these code
Option Explicit
Private Const CB_FINDSTRING = &H14C
Private Const CB_ERR = -1
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Public Sub AutoMatch(cbComboBox As ComboBox, KeyAscii As Integer)
Dim Idx As Long, pos As Integer
Dim strSearch As String
With cbComboBox
If KeyAscii = vbKeyBack Then
If .SelStart > 1 Then
strSearch = Mid(.Text, 1, .SelStart - 1)
Else
strSearch = ""
.Text = ""
End If
Else
strSearch = Mid(.Text, 1, .SelStart) & Chr(KeyAscii)
End If
'Call SendMessage to get the Index of an item (if any)
Idx = SendMessage(.hwnd, CB_FINDSTRING, -1, ByVal strSearch)
'If idx equals CB_ERR, then the search failed
If Idx > CB_ERR Then 'Store the caret position
pos = Len(strSearch)
.Text = .List(Idx)
.ListIndex = Idx ' Re-highlight the trailing text
.SelStart = pos
.SelLength = Len(.Text) - pos
KeyAscii = 0
End If
End With
End Sub
Private Sub Combo1_KeyPress(KeyAscii As Integer)
Call AutoMatch(Combo1, KeyAscii)
End Sub
Private Sub Form_Load()
With Combo1
.AddItem "Shaheen"
.AddItem "Shelly"
.AddItem "Jaimie"
.AddItem "Patrick"
.AddItem "Rose"
.AddItem "Rob"
.AddItem "Chris"
.AddItem "Peter"
End With
End Sub
Option Explicit
Private Const CB_FINDSTRING = &H14C
Private Const CB_ERR = -1
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Public Sub AutoMatch(cbComboBox As ComboBox, KeyAscii As Integer)
Dim Idx As Long, pos As Integer
Dim strSearch As String
With cbComboBox
If KeyAscii = vbKeyBack Then
If .SelStart > 1 Then
strSearch = Mid(.Text, 1, .SelStart - 1)
Else
strSearch = ""
.Text = ""
End If
Else
strSearch = Mid(.Text, 1, .SelStart) & Chr(KeyAscii)
End If
'Call SendMessage to get the Index of an item (if any)
Idx = SendMessage(.hwnd, CB_FINDSTRING, -1, ByVal strSearch)
'If idx equals CB_ERR, then the search failed
If Idx > CB_ERR Then 'Store the caret position
pos = Len(strSearch)
.Text = .List(Idx)
.ListIndex = Idx ' Re-highlight the trailing text
.SelStart = pos
.SelLength = Len(.Text) - pos
KeyAscii = 0
End If
End With
End Sub
Private Sub Combo1_KeyPress(KeyAscii As Integer)
Call AutoMatch(Combo1, KeyAscii)
End Sub
Private Sub Form_Load()
With Combo1
.AddItem "Shaheen"
.AddItem "Shelly"
.AddItem "Jaimie"
.AddItem "Patrick"
.AddItem "Rose"
.AddItem "Rob"
.AddItem "Chris"
.AddItem "Peter"
End With
End Sub
ASKER
yeah, ImageCombo doesnt look like it has this problem, but it also looks like its using a ListView for its dropdown. but i am also using some APIs to allow for autocompletion, changing the dropdown height/width, etc, so it probably isnt very practical to change to an ImageCombo.
the idea to prepend with a single space appears promising...i will need to do some more tests against some input data and saving to an output file to make sure it isnt going to cause any new problems.
the idea to prepend with a single space appears promising...i will need to do some more tests against some input data and saving to an output file to make sure it isnt going to cause any new problems.
ASKER
for those posting auto-completion code, please read my question carefully and realize that this is not what i am looking for...thanks.
Did u try mine. What is ur question. Can u elaborate it?
ASKER
>>What is ur question. Can u elaborate it?
start a new project, add a combobox to your form, and paste this code:
Private Sub Form_Load()
With Combo1
.AddItem "12.34"
.AddItem "23.45"
.AddItem "34.56"
.Text = "3"
End With
End Sub
now run the project. when the form shows up, the number "3" shows in the combobox. click the arrow to dropdown the combobox's contents, and "34.56" will appear highlighted and become the combobox's new text value (before it is manually selected - this is the default behavior of a combobox). i do NOT want this to happen. i want to be able to have the number "3" remain as the combobox's text even after its list of items are dropped down.
start a new project, add a combobox to your form, and paste this code:
Private Sub Form_Load()
With Combo1
.AddItem "12.34"
.AddItem "23.45"
.AddItem "34.56"
.Text = "3"
End With
End Sub
now run the project. when the form shows up, the number "3" shows in the combobox. click the arrow to dropdown the combobox's contents, and "34.56" will appear highlighted and become the combobox's new text value (before it is manually selected - this is the default behavior of a combobox). i do NOT want this to happen. i want to be able to have the number "3" remain as the combobox's text even after its list of items are dropped down.
Hi AzraSound,
Maybe a bad suggestion here: use timer to change the combobox's text when drop-down?
Maybe a bad suggestion here: use timer to change the combobox's text when drop-down?
sheridan's you can turn it off and on
price is 295 usd
it has a data combo, grid, option buttons, command buttons and enhanced dbcombo. they specalize in databinding, but you can use the additem property just like a regular combo.
price is 295 usd
it has a data combo, grid, option buttons, command buttons and enhanced dbcombo. they specalize in databinding, but you can use the additem property just like a regular combo.
ASKER
this is the most painless and cheapest solution, and appears to work well. thanks to all others for their input.
Thanks.
Yes, I tried ImageCombo control and it doesn't work with Size_Combo function, so dropdown height/width cannot be set very easy.
Maybe you can disable small combo button, or provide your own button, or just tell users
to use keyboard keys (arrows, F4), since that small button has autosearch 'feature'
Here is the code (I modified my combo wrapper class which allows strings for ItemData, and few other 'corrections' - e.g. original combo doesn't raise Click when needed)
' Form1, add 2 textboxes
Option Explicit
Private WithEvents wcb As cwCbo
Private Sub Form_Load()
' our combo
Set wcb = New cwCbo
Set wcb.Combo = Combo1
With wcb
.AddItem "12.34", "0"
.AddItem "23.45", "1"
.AddItem "34.56", "2"
Combo1.Text = "3"
End With
' normal combo
With Combo2
.AddItem "12.34"
.AddItem "23.45"
.AddItem "34.56"
.Text = "3"
End With
Show
Print "To open dropdown press:", " down arrow, F4 or up arrow"
Print "To close, press:", " F4, Enter, or Escape"
End Sub
Private Sub Form_Unload(Cancel As Integer)
Set wcb = Nothing
End Sub
Private Sub wcb_Clicked(ItemData As String)
Caption = Combo1.Text
End Sub
' class cwCbo, wrapper for combobox
'
' Usage
'------------------------- ----
' in form declarations:
' Private WithEvents wcb As cwcbo
' in Form_Load:
' Set wcb = New cwCbo
' Set wcb.Combo = Combo1
' in Form_Unload:
' Set wcb = Nothing
'------------------------- ----
Option Explicit
Private Declare Function LockWindowUpdate Lib "user32" (ByVal hwndLock As Long) As Long
Private Declare Function SendMessageAny Lib "user32" Alias "SendMessageA" (ByVal hwnd _
As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Private Declare Function SendMessageString Lib "user32" Alias "SendMessageA" (ByVal hwnd _
As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As String) As Long
Private Const CB_GETDROPPEDSTATE = &H157
Private Const CB_SHOWDROPDOWN = &H14F
Private Const CB_FINDSTRING = &H14C
Private Const CB_FINDSTRINGEXACT = &H158
Private Const CB_ADDSTRING = &H143
Private Const WM_SETREDRAW = &HB
'
Public WithEvents Combo As VB.ComboBox
Public Event Clicked(ItemData As String)
Private loading As Boolean
Private oldText As String
Private keys() As String
Private numitems As Long
Private hwnd As Long
Private Sub Combo_Click()
On Error Resume Next
If loading = False Then
If SendMessageAny(Combo.hwnd, CB_GETDROPPEDSTATE, 0&, 0&) = 0 Then
If Combo.ListIndex > -1 Then RaiseEvent Clicked(keys(Combo.ListInd ex))
End If
End If
End Sub
Private Sub Combo_KeyDown(KeyCode As Integer, Shift As Integer)
Dim lret As Long, sav As String, savpos As Long, savlen As Long
On Error Resume Next
If KeyCode = vbKeyF4 Or KeyCode = vbKeyDown Or KeyCode = vbKeyUp Then
If Shift = 0 Then
sav = Combo.Text
savpos = Combo.SelStart
savlen = Combo.SelLength
If SendMessageAny(Combo.hwnd, CB_GETDROPPEDSTATE, 0&, 0&) = 0 Then
KeyCode = 0
SetCB True, sav, savpos, savlen
ElseIf KeyCode = vbKeyF4 Then
KeyCode = 0
SetCB False, sav, savpos, savlen
SelectIfExact
End If
End If
ElseIf KeyCode = vbKeyEnd Then
If Shift = 2 Then
Combo.ListIndex = Combo.ListCount - 1
KeyCode = 0
End If
ElseIf KeyCode = vbKeyHome Then
If Shift = 2 Then
Combo.ListIndex = 0
KeyCode = 0
End If
ElseIf KeyCode = vbKeyReturn Then
sav = Combo.Text
savpos = Combo.SelStart
savlen = Combo.SelLength
lret = SendMessageAny(Combo.hwnd, CB_GETDROPPEDSTATE, 0&, 0&)
If lret = 1 Then
KeyCode = 0
SetCB False, sav, savpos, savlen
End If
SelectIfExact
ElseIf KeyCode = vbKeyEscape Then
lret = SendMessageAny(Combo.hwnd, CB_GETDROPPEDSTATE, 0&, 0&)
If lret = 1 Then
KeyCode = 0
SetCB False, oldText, 0, Len(oldText)
End If
SelectIfExact
End If
End Sub
Public Sub SetCB(ShowDropped As Boolean, Text As String, Start As Long, Length As Long)
Dim lret As Long
loading = True
Redraw False
lret = SendMessageAny(Combo.hwnd, CB_SHOWDROPDOWN, ShowDropped, 0&)
Combo.Text = Text
Combo.SelStart = Start
Combo.SelLength = Length
Redraw True
loading = False
If ShowDropped Then oldText = Text
End Sub
Public Sub SelectIfExact()
If Combo.ListIndex > -1 Then
RaiseEvent Clicked(keys(Combo.ListInd ex))
Else
Combo.ListIndex = SendMessageString(Combo.hw nd, CB_FINDSTRINGEXACT, -1, Combo.Text)
End If
End Sub
Public Sub Clear()
Erase keys
numitems = 0
Combo.Clear
End Sub
Public Sub AddItem(ByVal Text As String, Key As String)
On Error Resume Next
numitems = numitems + 1
If numitems Mod 100 = 1 Then
If hwnd = 0 Then hwnd = Combo.hwnd
ReDim Preserve keys(numitems + 100)
End If
keys(numitems - 1) = Key
'Combo.AddItem Text ' non-API version
SendMessageString hwnd, CB_ADDSTRING, 0&, Text ' API version
End Sub
Public Property Get ItemData() As String
If Combo.ListIndex > -1 Then ItemData = keys(Combo.ListIndex)
End Property
Public Sub Redraw(NewRedraw As Boolean)
If hwnd = 0 Then hwnd = Combo.hwnd
SendMessageAny hwnd, WM_SETREDRAW, -NewRedraw, 0&
End Sub
Yes, I tried ImageCombo control and it doesn't work with Size_Combo function, so dropdown height/width cannot be set very easy.
Maybe you can disable small combo button, or provide your own button, or just tell users
to use keyboard keys (arrows, F4), since that small button has autosearch 'feature'
Here is the code (I modified my combo wrapper class which allows strings for ItemData, and few other 'corrections' - e.g. original combo doesn't raise Click when needed)
' Form1, add 2 textboxes
Option Explicit
Private WithEvents wcb As cwCbo
Private Sub Form_Load()
' our combo
Set wcb = New cwCbo
Set wcb.Combo = Combo1
With wcb
.AddItem "12.34", "0"
.AddItem "23.45", "1"
.AddItem "34.56", "2"
Combo1.Text = "3"
End With
' normal combo
With Combo2
.AddItem "12.34"
.AddItem "23.45"
.AddItem "34.56"
.Text = "3"
End With
Show
Print "To open dropdown press:", " down arrow, F4 or up arrow"
Print "To close, press:", " F4, Enter, or Escape"
End Sub
Private Sub Form_Unload(Cancel As Integer)
Set wcb = Nothing
End Sub
Private Sub wcb_Clicked(ItemData As String)
Caption = Combo1.Text
End Sub
' class cwCbo, wrapper for combobox
'
' Usage
'-------------------------
' in form declarations:
' Private WithEvents wcb As cwcbo
' in Form_Load:
' Set wcb = New cwCbo
' Set wcb.Combo = Combo1
' in Form_Unload:
' Set wcb = Nothing
'-------------------------
Option Explicit
Private Declare Function LockWindowUpdate Lib "user32" (ByVal hwndLock As Long) As Long
Private Declare Function SendMessageAny Lib "user32" Alias "SendMessageA" (ByVal hwnd _
As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Private Declare Function SendMessageString Lib "user32" Alias "SendMessageA" (ByVal hwnd _
As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As String) As Long
Private Const CB_GETDROPPEDSTATE = &H157
Private Const CB_SHOWDROPDOWN = &H14F
Private Const CB_FINDSTRING = &H14C
Private Const CB_FINDSTRINGEXACT = &H158
Private Const CB_ADDSTRING = &H143
Private Const WM_SETREDRAW = &HB
'
Public WithEvents Combo As VB.ComboBox
Public Event Clicked(ItemData As String)
Private loading As Boolean
Private oldText As String
Private keys() As String
Private numitems As Long
Private hwnd As Long
Private Sub Combo_Click()
On Error Resume Next
If loading = False Then
If SendMessageAny(Combo.hwnd,
If Combo.ListIndex > -1 Then RaiseEvent Clicked(keys(Combo.ListInd
End If
End If
End Sub
Private Sub Combo_KeyDown(KeyCode As Integer, Shift As Integer)
Dim lret As Long, sav As String, savpos As Long, savlen As Long
On Error Resume Next
If KeyCode = vbKeyF4 Or KeyCode = vbKeyDown Or KeyCode = vbKeyUp Then
If Shift = 0 Then
sav = Combo.Text
savpos = Combo.SelStart
savlen = Combo.SelLength
If SendMessageAny(Combo.hwnd,
KeyCode = 0
SetCB True, sav, savpos, savlen
ElseIf KeyCode = vbKeyF4 Then
KeyCode = 0
SetCB False, sav, savpos, savlen
SelectIfExact
End If
End If
ElseIf KeyCode = vbKeyEnd Then
If Shift = 2 Then
Combo.ListIndex = Combo.ListCount - 1
KeyCode = 0
End If
ElseIf KeyCode = vbKeyHome Then
If Shift = 2 Then
Combo.ListIndex = 0
KeyCode = 0
End If
ElseIf KeyCode = vbKeyReturn Then
sav = Combo.Text
savpos = Combo.SelStart
savlen = Combo.SelLength
lret = SendMessageAny(Combo.hwnd,
If lret = 1 Then
KeyCode = 0
SetCB False, sav, savpos, savlen
End If
SelectIfExact
ElseIf KeyCode = vbKeyEscape Then
lret = SendMessageAny(Combo.hwnd,
If lret = 1 Then
KeyCode = 0
SetCB False, oldText, 0, Len(oldText)
End If
SelectIfExact
End If
End Sub
Public Sub SetCB(ShowDropped As Boolean, Text As String, Start As Long, Length As Long)
Dim lret As Long
loading = True
Redraw False
lret = SendMessageAny(Combo.hwnd,
Combo.Text = Text
Combo.SelStart = Start
Combo.SelLength = Length
Redraw True
loading = False
If ShowDropped Then oldText = Text
End Sub
Public Sub SelectIfExact()
If Combo.ListIndex > -1 Then
RaiseEvent Clicked(keys(Combo.ListInd
Else
Combo.ListIndex = SendMessageString(Combo.hw
End If
End Sub
Public Sub Clear()
Erase keys
numitems = 0
Combo.Clear
End Sub
Public Sub AddItem(ByVal Text As String, Key As String)
On Error Resume Next
numitems = numitems + 1
If numitems Mod 100 = 1 Then
If hwnd = 0 Then hwnd = Combo.hwnd
ReDim Preserve keys(numitems + 100)
End If
keys(numitems - 1) = Key
'Combo.AddItem Text ' non-API version
SendMessageString hwnd, CB_ADDSTRING, 0&, Text ' API version
End Sub
Public Property Get ItemData() As String
If Combo.ListIndex > -1 Then ItemData = keys(Combo.ListIndex)
End Property
Public Sub Redraw(NewRedraw As Boolean)
If hwnd = 0 Then hwnd = Combo.hwnd
SendMessageAny hwnd, WM_SETREDRAW, -NewRedraw, 0&
End Sub
>' Form1, add 2 textboxes
should be:
' Form1, add 2 ComboBoxes :-)
should be:
' Form1, add 2 ComboBoxes :-)
ASKER
thanks for that ameba. when i have some time, i will see if i can incorporate it into the project.
I have set up an Auto-Select combobox that drills down the values in the combo, shows you how many values you've typed in, responds to the backspace and any other keys you define and will also find by first character if the same key is pressed twice at the beginning. I just have partial code, and the comboboxes are particular to my app, however I believe you can get the idea.
using System;
using System.Windows.Forms;
namespace drillcombo
{
public class drillcombo : System.Windows.Forms.Form
{
public string currentcbo = ""; //current combobox
public int combokeycnt = 0; //number of acceptable keystrokes entered
public DateTime combolastkeyed = ( DateTime.Now ); //last time a key was entered
private void InitialzeComponent()
{
//example event declaration
this.cbosub.KeyDown += new KeyEventHandler(combo_KeyD own);
this.cbosub.KeyPress += new KeyPressEventHandler(this. combo_KeyP ress);
}
//Actual combobox code
private void combo_KeyDown(object sender, System.Windows.Forms.KeyEv entArgs e)
{
//GetCombo() converts sender into the actual combox that sent it.
//if new combobox, reset key count.
if ( GetCombo(sender).Name != currentcbo )
{
combokeycnt = 0;
}
//get the actual combobox being used so we don't have to make so many calls
//to GetCombo()
System.Windows.Forms.Combo Box cbodummy = GetCombo( sender );
//if item is not a combobox, exit, we don't need it.
if ( cbodummy == null )
return;
//Reset key count if wait between keys has been longer than 10 seconds.
if (combokeycnt != 0 && (combolastkeyed.Subtract(D ateTime.No w)).Second s > 10 )
{
combokeycnt = 0;
}
//Reset the time between keys
combolastkeyed = DateTime.Now;
//If backspace, decrement the count and reduce the combo selection length
if (e.KeyCode == Keys.Back && combokeycnt != 0)
{
combokeycnt--;
cbodummy.SelectionLength = combokeycnt;
}
else //otherwise get the keydata
{
string keychar = "";
//if the (string)KeyData has length 1, pass it.
if (e.KeyData.ToString().Leng th == 1)
{
keychar = e.KeyData.ToString().ToLow er();
}
else //otherwise filter out the values we can use and return for anything else
{
switch ( e.KeyCode )
{
case Keys.Space:
keychar = " ";
break;
case Keys.OemMinus:
keychar = "-";
break;
case Keys.Oemcomma:
keychar = ",";
break;
case Keys.OemSemicolon:
keychar = ";";
break;
default:
return;
}
}
//Append key value to the text entered so far determined by getting the
//combokeycount from the currently selected text in the combobox
string findchars = cbodummy.Text.Substring( 0, combokeycnt ) + keychar;
//if first letter is a repeat, jump to the next index that starts with
//that same letter. Reset combokeycount to check only first letter
if ( findchars.Length == 2 && cbodummy.Text.Substring(0, 1) == keychar )
{
findchars = keychar;
combokeycount = 0;
}
//find the string in the combo list
int combindex = cbodummy.FindString( findchars );
//if comboindex != -1 (failure), select the found item and increase the
//selection length
if ( combindex >= 0 )
{
combokeycnt++;
GetCombo(sender).SelectedI ndex = combindex;
GetCombo(sender).Selection Length = combokeycnt;
}
}
//Handling the keys to prevent actuall typing into the combobox is done
//in the KeyPress event
}
private void combo_KeyPress(object sender, System.Windows.Forms.KeyPr essEventAr gs e)
{
//Verify it's a combobox and then handle the key so no value actually goes
//into the combo.
if (GetCombo( sender ) != null)
e.Handled = true;
}
private System.Windows.Forms.Combo Box GetCombo(object sender)
{
//takes the sender object and returns which combo it is. Brute force,
//I know, but it works. Tried a swtich and it didn't, so...
if ( sender == this.cbocomp )
{
return this.cbocomp;
}
else if ( sender == this.cbocreate)
{
return this.cbocreate;
}
else if ( sender == this.cboproduct)
{
return this.cboproduct;
}
else if ( sender == this.cbosub)
{
return this.cbosub;
}
else
{
return null;
}
}
}
}
I hope this makes sense. Let me know if there are any questions.
Ross Elbling
Just having fun programming
using System;
using System.Windows.Forms;
namespace drillcombo
{
public class drillcombo : System.Windows.Forms.Form
{
public string currentcbo = ""; //current combobox
public int combokeycnt = 0; //number of acceptable keystrokes entered
public DateTime combolastkeyed = ( DateTime.Now ); //last time a key was entered
private void InitialzeComponent()
{
//example event declaration
this.cbosub.KeyDown += new KeyEventHandler(combo_KeyD
this.cbosub.KeyPress += new KeyPressEventHandler(this.
}
//Actual combobox code
private void combo_KeyDown(object sender, System.Windows.Forms.KeyEv
{
//GetCombo() converts sender into the actual combox that sent it.
//if new combobox, reset key count.
if ( GetCombo(sender).Name != currentcbo )
{
combokeycnt = 0;
}
//get the actual combobox being used so we don't have to make so many calls
//to GetCombo()
System.Windows.Forms.Combo
//if item is not a combobox, exit, we don't need it.
if ( cbodummy == null )
return;
//Reset key count if wait between keys has been longer than 10 seconds.
if (combokeycnt != 0 && (combolastkeyed.Subtract(D
{
combokeycnt = 0;
}
//Reset the time between keys
combolastkeyed = DateTime.Now;
//If backspace, decrement the count and reduce the combo selection length
if (e.KeyCode == Keys.Back && combokeycnt != 0)
{
combokeycnt--;
cbodummy.SelectionLength = combokeycnt;
}
else //otherwise get the keydata
{
string keychar = "";
//if the (string)KeyData has length 1, pass it.
if (e.KeyData.ToString().Leng
{
keychar = e.KeyData.ToString().ToLow
}
else //otherwise filter out the values we can use and return for anything else
{
switch ( e.KeyCode )
{
case Keys.Space:
keychar = " ";
break;
case Keys.OemMinus:
keychar = "-";
break;
case Keys.Oemcomma:
keychar = ",";
break;
case Keys.OemSemicolon:
keychar = ";";
break;
default:
return;
}
}
//Append key value to the text entered so far determined by getting the
//combokeycount from the currently selected text in the combobox
string findchars = cbodummy.Text.Substring( 0, combokeycnt ) + keychar;
//if first letter is a repeat, jump to the next index that starts with
//that same letter. Reset combokeycount to check only first letter
if ( findchars.Length == 2 && cbodummy.Text.Substring(0,
{
findchars = keychar;
combokeycount = 0;
}
//find the string in the combo list
int combindex = cbodummy.FindString( findchars );
//if comboindex != -1 (failure), select the found item and increase the
//selection length
if ( combindex >= 0 )
{
combokeycnt++;
GetCombo(sender).SelectedI
GetCombo(sender).Selection
}
}
//Handling the keys to prevent actuall typing into the combobox is done
//in the KeyPress event
}
private void combo_KeyPress(object sender, System.Windows.Forms.KeyPr
{
//Verify it's a combobox and then handle the key so no value actually goes
//into the combo.
if (GetCombo( sender ) != null)
e.Handled = true;
}
private System.Windows.Forms.Combo
{
//takes the sender object and returns which combo it is. Brute force,
//I know, but it works. Tried a swtich and it didn't, so...
if ( sender == this.cbocomp )
{
return this.cbocomp;
}
else if ( sender == this.cbocreate)
{
return this.cbocreate;
}
else if ( sender == this.cboproduct)
{
return this.cboproduct;
}
else if ( sender == this.cbosub)
{
return this.cbosub;
}
else
{
return null;
}
}
}
}
I hope this makes sense. Let me know if there are any questions.
Ross Elbling
Just having fun programming
ASKER
I have a question...why are you posting C# code in a Visual Basic (non .NET) thread?
Yeah. Doh! I thought I limited my search to C# only. Please disregard actual code and look at the ideas instead, if they apply.
see EE Guidelines, Asking Questions http:/help.jsp#hi46
or use this short version (ameba's guidelines :)
How do I ask a question
1) Select the right TA http:/allTopics.jsp
2) Click "Ask a question" (or "Ask an expert") link and follow instructions
or use this short version (ameba's guidelines :)
How do I ask a question
1) Select the right TA http:/allTopics.jsp
2) Click "Ask a question" (or "Ask an expert") link and follow instructions
ASKER
Just giving you a hard time...no worries.
None at all. 8^)>