Help using Stefan Berglund class module, please?
Author |
Message |
Ed from A #1 / 12
|
 Help using Stefan Berglund class module, please?
While searching for information on search-list-as-you-type feasability and code, I came across a 2002 newsgroup thread that included a post from Stefan Berglund: http://www.*-*-*.com/ In his post, Stefan gave code for a class module that would allow the search as you type or type ahead functionality in a combo box. It works great!! I would like to see about modifying it a bit. What I would like to do is to have four combo boxes, each populated with a different list, and what I type affecting the list in each of the four combo boxes. I would then click a button to indicate which of the four selections I wanted. I'm very unfamiliar with a lot of what's happening in Stefan's code (that's why I used his rather than writing my own!!). It would seem that all I would need to do is in the Form_Load code iterate through each combobox and set class objects to each of the combos: Private Sub Form_Load() Set m_clsCombo1 = New clsControlCombo Set m_clsCombo1.Control = Combo1 Set m_clsCombo2 = New clsControlCombo Set m_clsCombo2.Control = Combo12 etc. End Sub But then I am not sure about -- how do I get what I type into each combobox simultaneously? -- and will Stefan's code run in each combobox simultaneously without causing a conflict that I wouldn't be able to decipher or resolve? Any input is greatly appreciated. Ed Using VB6SP2 Learning Edition in WinXPSP2. Note: this is only for personal use, and not for distrubution to anyone else.
|
Sat, 11 Dec 2010 00:34:28 GMT |
|
 |
Mike #2 / 12
|
 Help using Stefan Berglund class module, please?
Quote: > While searching for information on search-list-as-you-type feasability > and code, I came across a 2002 newsgroup thread that included a post > from Stefan Berglund: > http://groups.google.com/group/microsoft.public.vb.general.discussion... > In his post, Stefan gave code for a class module that would allow the > search as you type or type ahead functionality in a combo box. It > works great!! > I would like to see about modifying it a bit. What I would like to do > is to have four combo boxes, each populated with a different list, and > what I type affecting the list in each of the four combo boxes. I > would then click a button to indicate which of the four selections I > wanted. > I'm very unfamiliar with a lot of what's happening in Stefan's code > (that's why I used his rather than writing my own!!). It would seem > that all I would need to do is in the Form_Load code iterate through > each combobox and set class objects to each of the combos: > Private Sub Form_Load() > Set m_clsCombo1 = New clsControlCombo > Set m_clsCombo1.Control = Combo1 > Set m_clsCombo2 = New clsControlCombo > Set m_clsCombo2.Control = Combo12 > etc. > End Sub > But then I am not sure about > -- how do I get what I type into each combobox simultaneously? > -- and will Stefan's code run in each combobox simultaneously without > causing a conflict that I wouldn't be able to decipher or resolve? > Any input is greatly appreciated.
I'm not really sure what you're asking. A class module is basically a template for creating an object. That's it. In the above code, you're creating a new object from this class for each of the 2 comboboxes. So, each object (referenced by the variables m_clsCombo1 and m_clsCombo2, respectively) is distinct from one another. -- Mike Microsoft Visual Basic MVP
|
Sat, 11 Dec 2010 04:09:56 GMT |
|
 |
Steve Gerrar #3 / 12
|
 Help using Stefan Berglund class module, please?
Quote:
> But then I am not sure about > -- how do I get what I type into each combobox simultaneously?
If you are typing in Combo1, use the Combo1_Change event to assign the text of Combo1 to the other three combos. Don't do the same thing in the other three, though. That would get you into an event loop. If you need that, you can use a flag to block it from looping. Quote: > -- and will Stefan's code run in each combobox simultaneously without > causing a conflict that I wouldn't be able to decipher or resolve?
Yes, although simulataneous is in the eye of the beholder.
|
Sat, 11 Dec 2010 12:20:13 GMT |
|
 |
Ed from A #4 / 12
|
 Help using Stefan Berglund class module, please?
Mike: Quote: >> So, each object (referenced by the variables >> m_clsCombo1 and m_clsCombo2, respectively) >> is distinct from one another.
Thank you for the explanation. As I said, there's a lot in this that goes way over my head. I always apreciate the help I receive to understand things. Steve: Quote: >> If you are typing in Combo1, use the >> Combo1_Change event to assign the text of >> Combo1 to the other three combos.
In Stefan's class module is a Control_Change sub: Private Sub Control_Change() With Control If (Len(.Tag) = 0 And Not mbCancel) Then Dim strText As String strText = .Text Dim lngID As Long lngID = FindComboMatch(Control, strText) If (lngID >= 0) Then .Tag = "x" .Text = .List(lngID) .SelStart = Len(strText) .SelLength = Len(.Text) .Tag = "" End If End If End With End Sub I'm assuming this _Change event would be separate from the Combo1_Change or Combo2_Change events? And there's no conflicts caused by running the class module Combo_Change and the Combo1_Change at the same time? Quote: > Don't do the same thing in the other three, though. > That would get you into an event loop. If you need >> that, you can use a flag to block it from looping.
Would it be better to have a fifth control, like a textbox, and use that _Change event to populate all four combos? Also, in Stefan's class there is a Control_KeyDown sub. If I am populating the combos by pulling the text from another control, the second combo will never see the _KeyDown event, will it? Can I / should I assign these events to other subs and call them for each combo as I populate it? Ed
|
Sat, 11 Dec 2010 21:45:11 GMT |
|
 |
Larry Serflate #5 / 12
|
 Help using Stefan Berglund class module, please?
Quote: > Would it be better to have a fifth control, like a textbox, and use > that _Change event to populate all four combos? > Also, in Stefan's class there is a Control_KeyDown sub. If I am > populating the combos by pulling the text from another control, the > second combo will never see the _KeyDown event, will it? Can I / > should I assign these events to other subs and call them for each > combo as I populate it?
It would probably be better to decide how you want it to respond, and then add the code necessary to do that. From what you said earlier: "I would like to see about modifying it a bit. What I would like to do is to have four combo boxes, each populated with a different list, and what I type affecting the list in each of the four combo boxes. I would then click a button to indicate which of the four selections I wanted." I have to wonder why you are using 4 combo boxes. It would seem one larger list might suffice, or four separate listsboxes with a textbox as that fifth input control. Another (wierd) approach would have all the text portions of the 4 combo boxes respond identically. No matter which you type in, they all react as if someone was typing in them. But, at this point, I would suggest a better description of the entire task would be benificial. There may be 'more user friendly' ways to do what you want. As it is, it is hard to imagine why you would want entry from one control to affect 3 others.... LFS
|
Sun, 12 Dec 2010 00:46:00 GMT |
|
 |
Ed from A #6 / 12
|
 Help using Stefan Berglund class module, please?
Hi, Larry. Quote: > But, at this point, I would suggest a better description of the entire > task would be benificial. There may be 'more user friendly' ways > to do what you want. As it is, it is hard to imagine why you would > want entry from one control to affect 3 others....
Sorry - very bad newbie habit. I have four separate lists. (The lists are the titles and first lines of two differrent categories of songs. There may be duplicates between the lists, but they would belong to a different category.) I want to populate some kind of control with each list - total four controls, one list. I used the ComboBox because that's what Stefan's code used. (I told you I wasn't real swift on my own here!) I would like to type an entry and have each of the four controls bring up the matches as I type. My intention was that when one of the four controls had a match for what I wanted, I would type the number 1, 2, 3 or 4 (since my list items do not contain numbers) and that would tell the program which control to work with. Stefan's code works great for one combo box. I just got a brain cramp trying to see how it would work to make four separate controls search four separate lists as I type. Did that shed any more light on this? Ed
Quote:
> > Would it be better to have a fifth control, like a textbox, and use > > that _Change event to populate all four combos? > > Also, in Stefan's class there is a Control_KeyDown sub. ?If I am > > populating the combos by pulling the text from another control, the > > second combo will never see the _KeyDown event, will it? ?Can I / > > should I assign these events to other subs and call them for each > > combo as I populate it? > It would probably be better to decide how you want it to respond, > and then add the code necessary to do that. ?From what you said > earlier: > "I would like to see about modifying it a bit. ?What I would like to do > is to have four combo boxes, each populated with a different list, and > what I type affecting the list in each of the four combo boxes. ?I > would then click a button to indicate which of the four selections I > wanted." > I have to wonder why you are using 4 combo boxes. ?It would seem > one larger list might suffice, or four separate listsboxes with a textbox > as that fifth input control. > Another (wierd) approach would have all the text portions of the 4 > combo boxes respond identically. ?No matter which you type in, > they all react as if someone was typing in them. > But, at this point, I would suggest a better description of the entire > task would be benificial. ?There may be 'more user friendly' ways > to do what you want. ?As it is, it is hard to imagine why you would > want entry from one control to affect 3 others.... > LFS
|
Sun, 12 Dec 2010 03:14:16 GMT |
|
 |
Steve Gerrar #7 / 12
|
 Help using Stefan Berglund class module, please?
Quote:
> In Stefan's class module is a Control_Change sub: > I'm assuming this _Change event would be separate from the > Combo1_Change or Combo2_Change events? And there's no conflicts > caused by running the class module Combo_Change and the Combo1_Change > at the same time?
Both event handlers will run. One of the features of events is that more than one object can receive and respond to an event. Quote: > Would it be better to have a fifth control, like a textbox, and use > that _Change event to populate all four combos?
It's not necessary, but I like the idea. It would make it clearer to a user what is actually going on, and where they are supposed to type. Quote: > Also, in Stefan's class there is a Control_KeyDown sub. If I am > populating the combos by pulling the text from another control, the > second combo will never see the _KeyDown event, will it? Can I / > should I assign these events to other subs and call them for each > combo as I populate it?
Looking at the code at your original link, I would say no. It is fussing around with someone typing a backspace in the combo, which would not happen in any but the one you are typing in - or none, if you use the textbox idea. I think you should slap together a test project, with two combos and two instances of the class hooked to them. Add three or four items to each combo, then run it and try it and see what happens.
|
Sun, 12 Dec 2010 09:55:13 GMT |
|
 |
Larry Serflate #8 / 12
|
 Help using Stefan Berglund class module, please?
Quote: > I have four separate lists. (The lists are the titles and first lines > of two differrent categories of songs. (...) > I would like to type an entry and have each of the four controls > bring up the matches as I type.
You certainly could do that if you want, and I also think having that extra textbox would be a good idea. The trouble I am seeing is that early on (when you've only typed a few characters) there is a potential for multiple matches in any single list. I just wonder how you're going to show them, in a Combobox. What Style property are you using for those Combos? Here is another way to look at that problem. What if you had one (in memory) list that contained the title, first line, and genre (category) indicator that you could search through. Then, instead of 4 combo boxes, you use one listbox and 2 checkboxes. You could use the checkboxes to indicate the category you want searched (one or the other or both) and do a manual search as the user types. The results of the search could be shown in the listbox. If you want to allow the user to scroll a list to select a title, you could use a second listbox instead of that in memory list (sorted set to true). What do you think? LFS
|
Sun, 12 Dec 2010 19:59:18 GMT |
|
 |
Ed from A #9 / 12
|
 Help using Stefan Berglund class module, please?
Thanks for{*filter*} in with me, Steve. I'll expand on my project this weekend and let you know if it smokes! (I learned that principle as an electronics tech in a previous era - everthing electrical runs on smoke, and if you ever let the smoke out it will never run again!) Ed
Quote:
> > In Stefan's class module is a Control_Change sub: > > I'm assuming this _Change event would be separate from the > > Combo1_Change or Combo2_Change events? ?And there's no conflicts > > caused by running the class module Combo_Change and the Combo1_Change > > at the same time? > Both event handlers will run. One of the features of events is that more than > one object can receive and respond to an event. > > Would it be better to have a fifth control, like a textbox, and use > > that _Change event to populate all four combos? > It's not necessary, but I like the idea. It would make it clearer to a user what > is actually going on, and where they are supposed to type. > > Also, in Stefan's class there is a Control_KeyDown sub. ?If I am > > populating the combos by pulling the text from another control, the > > second combo will never see the _KeyDown event, will it? ?Can I / > > should I assign these events to other subs and call them for each > > combo as I populate it? > Looking at the code at your original link, I would say no. It is fussing around > with someone typing a backspace in the combo, which would not happen in any but > the one you are typing in - or none, if you use the textbox idea. > I think you should slap together a test project, with two combos and two > instances of the class hooked to them. Add three or four items to each combo, > then run it and try it and see what happens.
|
Sun, 12 Dec 2010 21:49:50 GMT |
|
 |
Ed from A #10 / 12
|
 Help using Stefan Berglund class module, please?
Hi, Larry. The "user" for this will only be me. I am a musician in my church worship team. We have songs divided into two general categories. I can not play without the music in front of me. I have a 3-inch binder full of the songs, but it can take me half a song to riffle thorugh and find it! So my thought is to scan in each song (they're all only a single page) and make a list of title and first line for each category - four lists. The lists are loaded into arrays at ary1(x,1) which are then used to populate the combo boxes. Loaded at ary1(x,2) is the file path for that song. As a song is called out, I can begin typing either the title or first line - when I see it come up in one of the combos (and I know which one I will be looking for), I will use the numbers 1 - 4 to tell the program to capture the ListItem number for that combo. That then will give me which array and which position for the path to load the song. Hopefully much faster (and a bit more cool!!) that riffling through a thick binder! The check boxes and other options to narrow down the list would be good for something production, or where there's a bit more time, perhaps. But I'd rather not fumble with a mouse - just type a few letters and then a number and load the file. Ed
Quote:
> > I have four separate lists. ?(The lists are the titles and first lines > > of two differrent categories of songs. (...) > > I would like to type an entry and have each of the four controls > > bring up the matches as I type. > You certainly could do that if you want, and I also think having that > extra textbox would be a good idea. ?The trouble I am seeing is that > early on (when you've only typed a few characters) there is a potential > for multiple matches in any single list. ?I just wonder how you're going to > show them, in a Combobox. ?What Style property are you using for those > Combos? > Here is another way to look at that problem. ?What if you had one > (in memory) list that contained the title, first line, and genre (category) > indicator that you could search through. ?Then, instead of 4 combo > boxes, you use one listbox and 2 checkboxes. ?You could use the > checkboxes to indicate the category you want searched (one or the > other or both) and do a manual search as the user types. ?The results > of the search could be shown in the listbox. ?If you want to allow > the user to scroll a list to select a title, you could use a second listbox > instead of that in memory list (sorted set to true). > What do you think? > LFS
|
Sun, 12 Dec 2010 22:01:00 GMT |
|
 |
Mike William #11 / 12
|
 Help using Stefan Berglund class module, please?
Quote: > The check boxes and other options to narrow down the > list would be good for something production, or where > there's a bit more time, perhaps. But I'd rather not fumble > with a mouse - just type a few letters and then a number > and load the file.
I'm not sure how you've arranged the display of items in the ComboBox but have you considered a slightly different approach, perhaps a TextBox and an accompanying ListBox. You can then begin to type some characters into the TextBox, with the ListBox (Sorted True) showing a scrollable list of entries that match the characters you have so far typed. Even typing just the first character, or perhaps the first two or three characters, will rapidly get you to the approximately correct place in the ordered List and you can then simply use the up / down arrows on the keyboard to rapidly scroll to the exact entry you require. If you arrange things properly you will not need to keep clicking from TextBox to ListBox, just simply "type and scroll". The following is a rather hastily modified version of some code I've just included in a program I'm writing for my daughter. I've had to modify it before posting because in my case I was using various user selectable tabstops and performing various conversions between tabs and spaces for a specific purpose, but hopefully I've got it converted properly for your own use. It seems to work okay anyway. Start a new test project and place one TextBox and one ListBox onto the Form. Set the Sorted property of the ListBox to True in the properties window at design time. Then paste in the following code. When the Form loads (and after is has populated the ListBox with some random strings) you should be able to simply type one or two (or more) characters at the keyboard and immediately use the up and down arrows opn the keyboard to scroll the list when it is somewhere near your desired selection. Then just press the Enter key to show the selection in the Form's Caption bar. You should be able to modify this to handle more than one ListBox. Mike Option Explicit 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 Private Const LB_FINDSTRING = &H18F Private Sub Form_Load() Randomize Timer ScaleMode = vbPixels Text1.Text = "" Text1.Move 10, 10, 240, 20 List1.Move 10, 32, 240, 200 Dim n As Long, p As Long, s1 As String Me.Show Caption = "Please wait . . ." Enabled = False DoEvents For n = 1 To 16000 s1 = Space$(Rnd * 12 + 12) For p = 1 To Len(s1) Mid$(s1, p, 1) = Chr$(Rnd * 25 + 97) Next p List1.AddItem s1 Next n Caption = "Ready" Enabled = True End Sub Private Sub List1_DblClick() If List1.ListIndex >= 0 Then Caption = List1.List(List1.ListIndex) Else Caption = "Chosen record does not exist" End If End Sub Private Sub List1_KeyPress(KeyAscii As Integer) If KeyAscii = 13 Then If List1.ListIndex >= 0 Then Caption = List1.List(List1.ListIndex) Else Caption = "Chosen record does not exist" End If End If End Sub Private Function FindMatch(ByVal ctl As ListBox, _ ByVal s1 As String, ByVal row1 As Long) As Long Dim index As Long On Error Resume Next index = SendMessage(ctl.hwnd, LB_FINDSTRING, _ row1, ByVal s1) FindMatch = index End Function Private Sub List1_MouseDown(Button As Integer, Shift As Integer, x As Single, y As Single) Text1.Text = List1.List(List1.ListIndex) Text1.SelStart = 0 Text1.SelLength = Len(Text1.Text) Text1.SetFocus End Sub Private Sub Text1_KeyDown(KeyCode As Integer, _ Shift As Integer) Dim index As Integer, p As Long If KeyCode = 13 Then If List1.ListIndex >= 0 Then Caption = List1.List(List1.ListIndex) Else Caption = "Chosen record does not exist" End If End If DoEvents p = Text1.SelStart Select Case KeyCode Case 37 Text1.SelStart = p Case 9, 32 To 36, Is > 40 index = FindMatch(List1, _ Left$(Text1.Text, p), -1) List1.ListIndex = index If index >= 0 Then List1.Selected(index) = True Text1.Text = List1.List(List1.ListIndex) Text1.SelStart = p Text1.SelLength = Len(Text1.Text) - p End If Case 38 KeyCode = 0 If List1.ListIndex > 0 Then List1.ListIndex = List1.ListIndex - 1 Text1.Text = List1.List(List1.ListIndex) Text1.SelStart = 0 Text1.SelLength = Len(Text1.Text) End If Case 40 KeyCode = 0 If List1.ListIndex < List1.ListCount - 1 Then List1.ListIndex = List1.ListIndex + 1 Text1.Text = List1.List(List1.ListIndex) Text1.SelStart = 0 Text1.SelLength = Len(Text1.Text) End If End Select End Sub Private Sub Text1_KeyPress(KeyAscii As Integer) If KeyAscii = 9 Then KeyAscii = 0 End If End Sub
|
Sun, 12 Dec 2010 22:53:40 GMT |
|
 |
Ed from A #12 / 12
|
 Help using Stefan Berglund class module, please?
Thanks, Mike. I'll give this a shot and compare it with the other to see which I can use best. (Meaning: which one gets me in the least trouble!!) 8>) Ed
Quote:
> > The check boxes and other options to narrow down the > > list would be good for something production, or where > > there's a bit more time, perhaps. ?But I'd rather not fumble > > with a mouse - just type a few letters and then a number > > and load the file. > I'm not sure how you've arranged the display of items in the ComboBox but > have you considered a slightly different approach, perhaps a TextBox and an > accompanying ListBox. You can then begin to type some characters into the > TextBox, with the ListBox (Sorted True) showing a scrollable list of entries > that match the characters you have so far typed. Even typing just the first > character, or perhaps the first two or three characters, will rapidly get > you to the approximately correct place in the ordered List and you can then > simply use the up / down arrows on the keyboard to rapidly scroll to the > exact entry you require. If you arrange things properly you will not need to > keep clicking from TextBox to ListBox, just simply "type and scroll". The > following is a rather hastily modified version of some code I've just > included in a program I'm writing for my daughter. I've had to modify it > before posting because in my case I was using various user selectable > tabstops and performing various conversions between tabs and spaces for a > specific purpose, but hopefully I've got it converted properly for your own > use. It seems to work okay anyway. > Start a new test project and place one TextBox and one ListBox onto the > Form. Set the Sorted property of the ListBox to True in the properties > window at design time. Then paste in the following code. When the Form loads > (and after is has populated the ListBox with some random strings) you should > be able to simply type one or two (or more) characters at the keyboard and > immediately use the up and down arrows opn the keyboard to scroll the list > when it is somewhere near your desired selection. Then just press the Enter > key to show the selection in the Form's Caption bar. You should be able to > modify this to handle more than one ListBox. > Mike > Option Explicit > 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 > Private Const LB_FINDSTRING = &H18F > Private Sub Form_Load() > Randomize Timer > ScaleMode = vbPixels > Text1.Text = "" > Text1.Move 10, 10, 240, 20 > List1.Move 10, 32, 240, 200 > Dim n As Long, p As Long, s1 As String > Me.Show > Caption = "Please wait . . ." > Enabled = False > DoEvents > For n = 1 To 16000 > s1 = Space$(Rnd * 12 + 12) > For p = 1 To Len(s1) > ? Mid$(s1, p, 1) = Chr$(Rnd * 25 + 97) > Next p > List1.AddItem s1 > Next n > Caption = "Ready" > Enabled = True > End Sub > Private Sub List1_DblClick() > If List1.ListIndex >= 0 Then > ? Caption = List1.List(List1.ListIndex) > Else > ? Caption = "Chosen record does not exist" > End If > End Sub > Private Sub List1_KeyPress(KeyAscii As Integer) > If KeyAscii = 13 Then > ? If List1.ListIndex >= 0 Then > ? ? Caption = List1.List(List1.ListIndex) > ? Else > ? ? Caption = "Chosen record does not exist" > ? End If > End If > End Sub > Private Function FindMatch(ByVal ctl As ListBox, _ > ?ByVal s1 As String, ByVal row1 As Long) As Long > Dim index As Long > On Error Resume Next > index = SendMessage(ctl.hwnd, LB_FINDSTRING, _ > ? ? ? row1, ByVal s1) > FindMatch = index > End Function > Private Sub List1_MouseDown(Button As Integer, Shift As Integer, x As > Single, y As Single) > Text1.Text = List1.List(List1.ListIndex) > Text1.SelStart = 0 > Text1.SelLength = Len(Text1.Text) > Text1.SetFocus > End Sub > Private Sub Text1_KeyDown(KeyCode As Integer, _ > ? Shift As Integer) > Dim index As Integer, p As Long > If KeyCode = 13 Then > ? If List1.ListIndex >= 0 Then > ? ? Caption = List1.List(List1.ListIndex) > ? Else > ? ? Caption = "Chosen record does not exist" > ? End If > End If > DoEvents > p = Text1.SelStart > Select Case KeyCode > Case 37 > ? Text1.SelStart = p > Case 9, 32 To 36, Is > 40 > ? index = FindMatch(List1, _ > ? ? Left$(Text1.Text, p), -1) > ? List1.ListIndex = index > ? If index >= 0 Then > ? ? List1.Selected(index) = True > ? ? Text1.Text = List1.List(List1.ListIndex) > ? ? Text1.SelStart = p > ? ? Text1.SelLength = Len(Text1.Text) - p > ? End If > Case 38 > ? KeyCode = 0 > ? If List1.ListIndex > 0 Then > ? ? List1.ListIndex = List1.ListIndex - 1 > ? ? Text1.Text = List1.List(List1.ListIndex) > ? ? Text1.SelStart = 0 > ? ? Text1.SelLength = Len(Text1.Text) > ? End If > Case 40 > ? KeyCode = 0 > ? If List1.ListIndex < List1.ListCount - 1 Then > ? ? List1.ListIndex = List1.ListIndex + 1 > ? ? Text1.Text = List1.List(List1.ListIndex) > ? ? Text1.SelStart = 0 > ? ? Text1.SelLength = Len(Text1.Text) > ? End If > End Select > End Sub > Private Sub Text1_KeyPress(KeyAscii As Integer) > If KeyAscii = 9 Then > ? KeyAscii = 0 > End If > End Sub
|
Mon, 13 Dec 2010 21:33:57 GMT |
|
|
|