PlanetSquires Forums

Please login or register.

Login with username, password and session length
Advanced search  
Pages: [1] 2

Author Topic: ? on combo box autocompletion  (Read 1026 times)

Paul D. Elliott

  • Guest
? on combo box autocompletion
« on: July 12, 2004, 02:54:40 PM »

The following is some code I pulled from the PB forums to handle
autocompletion in combo boxes. However it won't let me exit the control.
I've tried TAB and ENTER but find that I must use the mouse to get to the
next control. Can anyone help and tell me what needs to be fixed?

Thanks.


Code: [Select]
Function LOGIN_CBUSER_CBN_EDITCHANGE (ControlIndex As Long, hWndForm As Dword, hWndControl As Dword, _
         idComboBox As Dword) As Long
  Static  fNoUpdate   As Long                 ' used to prevent recursion(-1, 0)
  Local   lCaretPos   As Long                 ' current position of caret
  Local   ilList      As Long                 ' index of match in combobox
  Local   szItem      As Asciiz * %MAX_PATH   ' scratch pad

  If Not fNoUpdate Then
      ' Note: the following autocompletes the text
      ' 1. Get the text the user typed
      ' 2. Try to find a match from the predefined strings
      ' 3. Save the current position of the caret
      ' 4. Retrieve the matching text from the combobox
      ' 5. Set flag to prevent recursion
      ' 6. Replace the text in the edit control with the matching text
      ' 7. Select all text from the old position of the caret to the end
      ' 8. Reset flag      
      ' changed lParam to hWNdControl
      ' changed lpszItem to VarPtr(szItem)
      SendMessage hWndControl, %WM_GETTEXT, %MAX_PATH - 1, ByVal VarPtr(szItem)
      ilList = SendMessage(hWndControl, %CB_FINDSTRING, -1, ByVal VarPtr(szItem))
      If ilList <> %CB_ERR Then
        lCaretPos = LoWrd(SendMessage(hWndControl, %CB_GETEDITSEL, ByVal %Null, ByVal %Null))
        SendMessage hWndControl, %CB_GETLBTEXT, ilList, ByVal VarPtr(szItem)
        fNoUpdate = -1
        SendMessage hWndControl, %WM_SETTEXT, 0, ByVal VarPtr(szItem)
        SendMessage hWndControl, %CB_SETEDITSEL, 0, MakLng(lCaretPos, -1)
      End If
    End If
    fNoUpdate = 0
End Function

 

[/code]
Logged

Roger Garstang

  • Guest
? on combo box autocompletion
« Reply #1 on: July 12, 2004, 03:00:37 PM »

Not sure how much it helps, but in a app I made some time back I had a combo box with port numbers and descriptions and made an autocomplete for it like this:

Code: [Select]
CONTROL GET TEXT CBHNDL, %IDC_PORT TO portString
SELECT CASE CBCTLMSG
Case %CBN_EDITCHANGE
 'You wouldn't need this following IF Block
 If Val(portString) > 65535 Or Val(portString) < 1 Then
   portString = ""
   Control Set Text CbHndl, %IDC_PORT, portString
 End If
 lengthPortString = Len(portString)
 If lengthPortString > previousSize Then
   Control Send CbHndl, %IDC_PORT, %CB_SELECTSTRING, -1, VarPtr(portString) To searchResult
   If searchResult = %CB_ERR Then Control Set Text CbHndl, %IDC_PORT, portString
   Control Send CbHndl, %IDC_PORT, %CB_SETEDITSEL, 0, MakDwd(lengthPortString,-1)
 End If
 previousSize = Len(portString) ' STATIC DWORD

Of course in FF you'd need to convert the lines into SendMessage's and:
CBCTLMSG= HIWRD(wParam)

And you'd need something to prevent looping back in the callback.
Code: [Select]
IF preventLoop = 0 THEN
  preventLoop = 1
  {The code above}
  preventLoop = 0
END IF
Logged

Roger Garstang

  • Guest
? on combo box autocompletion
« Reply #2 on: July 12, 2004, 03:53:41 PM »

Here is the converted code in FF:

I made just a blank form with a Combo named Port

Code: [Select]
Function FORM1_PORT_CBN_EDITCHANGE (ControlIndex As Long, hWndForm As Dword, hWndControl As Dword, idComboBox As Dword) As Long
 Local searchResult As Long
 Local lengthComboString As Dword
 Local comboString As String
 Static previousSize As Dword
 Static preventLoop As Dword
 
If preventLoop = 0 Then
    preventLoop = 1
    comboString= FF_Control_GetText(HWND_FORM1_PORT)

    lengthComboString = Len(comboString)
    If lengthComboString > previousSize Then
        searchResult= SendMessage(HWND_FORM1_PORT, %CB_SELECTSTRING, -1, StrPtr(comboString))
        If searchResult = %CB_ERR Then FF_Control_SetText(HWND_FORM1_PORT, comboString)
    End If
    SendMessage(HWND_FORM1_PORT, %CB_SETEDITSEL, 0, MakDwd(lengthComboString,-1))
    previousSize = lengthComboString
    preventLoop = 0
End If  
End Function

Function FORM1_WM_CREATE (hWndForm As Dword) As Long
    FF_ComboBox_AddString HWND_FORM1_PORT, "7 Echo"
    FF_ComboBox_AddString HWND_FORM1_PORT, "9 Discard"
    FF_ComboBox_AddString HWND_FORM1_PORT, "11 Active Users"
    FF_ComboBox_AddString HWND_FORM1_PORT, "13 Daytime"
    FF_ComboBox_AddString HWND_FORM1_PORT, "17 Quote of Day"
    FF_ComboBox_AddString HWND_FORM1_PORT, "20 FTP data"
    FF_ComboBox_AddString HWND_FORM1_PORT, "21 FTP control"
    FF_ComboBox_AddString HWND_FORM1_PORT, "22 SSH"
    FF_ComboBox_AddString HWND_FORM1_PORT, "23 Telnet"
    FF_ComboBox_AddString HWND_FORM1_PORT, "25 SMTP"
    FF_ComboBox_AddString HWND_FORM1_PORT, "37 Time"
    FF_ComboBox_AddString HWND_FORM1_PORT, "43 Whois"
    FF_ComboBox_AddString HWND_FORM1_PORT, "53 DNS"
    FF_ComboBox_AddString HWND_FORM1_PORT, "70 Gopher"
    FF_ComboBox_AddString HWND_FORM1_PORT, "79 Finger"
    FF_ComboBox_AddString HWND_FORM1_PORT, "80 WWW"
    FF_ComboBox_AddString HWND_FORM1_PORT, "110 POP3"
    FF_ComboBox_AddString HWND_FORM1_PORT, "119 Happy99"
    FF_ComboBox_AddString HWND_FORM1_PORT, "135 epmap"
    FF_ComboBox_AddString HWND_FORM1_PORT, "137 Netbios Name"
    FF_ComboBox_AddString HWND_FORM1_PORT, "138 Netbios Datagram"
    FF_ComboBox_AddString HWND_FORM1_PORT, "139 Netbios Session"
    FF_ComboBox_AddString HWND_FORM1_PORT, "445 MS DS LANMAN Messages"
    FF_ComboBox_AddString HWND_FORM1_PORT, "1214 KaZaA"
    FF_ComboBox_AddString HWND_FORM1_PORT, "1243 Sub 7"
    FF_ComboBox_AddString HWND_FORM1_PORT, "1433 MS SQL"
    FF_ComboBox_AddString HWND_FORM1_PORT, "1434 MS SQL"
    FF_ComboBox_AddString HWND_FORM1_PORT, "1719 Elthe Phone"
    FF_ComboBox_AddString HWND_FORM1_PORT, "1720 Elthe Phone"
    FF_ComboBox_AddString HWND_FORM1_PORT, "5631 PCanywhere Remote"
    FF_ComboBox_AddString HWND_FORM1_PORT, "5632 PCanywhere Ping"
    FF_ComboBox_AddString HWND_FORM1_PORT, "5634 Old Gnutella"
    FF_ComboBox_AddString HWND_FORM1_PORT, "6346 Gnutella"
    FF_ComboBox_AddString HWND_FORM1_PORT, "6347 Gnutella 2"
    FF_ComboBox_AddString HWND_FORM1_PORT, "6699 Napster"
    FF_ComboBox_AddString HWND_FORM1_PORT, "6667 Sub 7"
    FF_ComboBox_AddString HWND_FORM1_PORT, "6711 Sub 7"
    FF_ComboBox_AddString HWND_FORM1_PORT, "6712 Sub 7"
    FF_ComboBox_AddString HWND_FORM1_PORT, "6713 Sub 7"
    FF_ComboBox_AddString HWND_FORM1_PORT, "6776 Sub 7"
    FF_ComboBox_AddString HWND_FORM1_PORT, "8787 BackOriface"
    FF_ComboBox_AddString HWND_FORM1_PORT, "8879 BackOriface"
    FF_ComboBox_AddString HWND_FORM1_PORT, "12345 Amitis.B"
    FF_ComboBox_AddString HWND_FORM1_PORT, "16959 Sub 7"
    FF_ComboBox_AddString HWND_FORM1_PORT, "17300 Kuang2 Virus"
    FF_ComboBox_AddString HWND_FORM1_PORT, "53001 Remote Shutdown"
    FF_ComboBox_AddString HWND_FORM1_PORT, "54320 BackOriface"
    FF_ComboBox_AddString HWND_FORM1_PORT, "54321 BackOriface"
    FF_ComboBox_AddString HWND_FORM1_PORT, "65535 Linux Worm"  
End Function

I'm still looking into why the tabs won't work though...
Logged

Roger Garstang

  • Guest
? on combo box autocompletion
« Reply #3 on: July 12, 2004, 04:31:01 PM »

Looks like this isn't just a problem with autocomplete.  You are going to need to subclass the edit box "child" of the combo and get the keystroke messages.  All but VK_TAB you'd need to forward to the previous proc for the combo and VK_TAB you'd forward to the main window.
Logged

Paul D. Elliott

  • Guest
? on combo box autocompletion
« Reply #4 on: July 12, 2004, 04:34:09 PM »

Strange ( meaning ... I don't understand ).
I started out with a style of CBS_DropDown so that the list wouldn't
show up unless the user clicked & wanted it.  This is seeming to prevent
an exit of the combo box. If I change to CBS_DropDownList then the
first time the list shows and I can exit the field without problem. The next
time into the field, no list shows but the autocompletion is still working
and exits the field okay.

I'll have to check if this is normal for PB or something to do with FF.
Logged

Roger Garstang

  • Guest
? on combo box autocompletion
« Reply #5 on: July 12, 2004, 04:51:27 PM »

Complete code with subclassing:

Code: [Select]
Global gOldSubClassProc As Dword
   
Function FORM1_PORT_CBN_EDITCHANGE (ControlIndex As Long, hWndForm As Dword, hWndControl As Dword, idComboBox As Dword) As Long
 Local searchResult As Long
 Local lengthComboString As Dword
 Local comboString As String
 Static previousSize As Dword
 Static preventLoop As Dword
 
If preventLoop = 0 Then
    preventLoop = 1
    comboString= FF_Control_GetText(HWND_FORM1_PORT)

    lengthComboString = Len(comboString)
    If lengthComboString > previousSize Then
        searchResult= SendMessage(HWND_FORM1_PORT, %CB_SELECTSTRING, -1, StrPtr(comboString))
        If searchResult = %CB_ERR Then FF_Control_SetText(HWND_FORM1_PORT, comboString)
    End If
    SendMessage(HWND_FORM1_PORT, %CB_SETEDITSEL, 0, MakDwd(lengthComboString,-1))
    previousSize = lengthComboString
    preventLoop = 0
End If  
End Function
   
Function CbSubClassProc(ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long    ' Process our messages in this subclass procedure
    If wMsg= %WM_CHAR And wParam= %VK_TAB Then
        SendMessage(HWND_FORM1_PORT, wMsg, wParam, lParam)
        Function= %TRUE
    Else
        Function = CallWindowProc(gOldSubClassProc, hWnd, wMsg, wParam, lParam)
    End If
End Function

Function FORM1_WM_CREATE (hWndForm As Dword) As Long
    gOldSubClassProc = SetWindowLong(GetDlgItem(HWND_FORM1_PORT, 1001), %GWL_WNDPROC, CodePtr(CbSubClassProc))
    FF_ComboBox_AddString HWND_FORM1_PORT, "7 Echo"
    FF_ComboBox_AddString HWND_FORM1_PORT, "9 Discard"
    FF_ComboBox_AddString HWND_FORM1_PORT, "11 Active Users"
    FF_ComboBox_AddString HWND_FORM1_PORT, "13 Daytime"
    FF_ComboBox_AddString HWND_FORM1_PORT, "17 Quote of Day"
    FF_ComboBox_AddString HWND_FORM1_PORT, "20 FTP data"
    FF_ComboBox_AddString HWND_FORM1_PORT, "21 FTP control"
    FF_ComboBox_AddString HWND_FORM1_PORT, "22 SSH"
    FF_ComboBox_AddString HWND_FORM1_PORT, "23 Telnet"
    FF_ComboBox_AddString HWND_FORM1_PORT, "25 SMTP"
    FF_ComboBox_AddString HWND_FORM1_PORT, "37 Time"
    FF_ComboBox_AddString HWND_FORM1_PORT, "43 Whois"
    FF_ComboBox_AddString HWND_FORM1_PORT, "53 DNS"
    FF_ComboBox_AddString HWND_FORM1_PORT, "70 Gopher"
    FF_ComboBox_AddString HWND_FORM1_PORT, "79 Finger"
    FF_ComboBox_AddString HWND_FORM1_PORT, "80 WWW"
    FF_ComboBox_AddString HWND_FORM1_PORT, "110 POP3"
    FF_ComboBox_AddString HWND_FORM1_PORT, "119 Happy99"
    FF_ComboBox_AddString HWND_FORM1_PORT, "135 epmap"
    FF_ComboBox_AddString HWND_FORM1_PORT, "137 Netbios Name"
    FF_ComboBox_AddString HWND_FORM1_PORT, "138 Netbios Datagram"
    FF_ComboBox_AddString HWND_FORM1_PORT, "139 Netbios Session"
    FF_ComboBox_AddString HWND_FORM1_PORT, "445 MS DS LANMAN Messages"
    FF_ComboBox_AddString HWND_FORM1_PORT, "1214 KaZaA"
    FF_ComboBox_AddString HWND_FORM1_PORT, "1243 Sub 7"
    FF_ComboBox_AddString HWND_FORM1_PORT, "1433 MS SQL"
    FF_ComboBox_AddString HWND_FORM1_PORT, "1434 MS SQL"
    FF_ComboBox_AddString HWND_FORM1_PORT, "1719 Elthe Phone"
    FF_ComboBox_AddString HWND_FORM1_PORT, "1720 Elthe Phone"
    FF_ComboBox_AddString HWND_FORM1_PORT, "5631 PCanywhere Remote"
    FF_ComboBox_AddString HWND_FORM1_PORT, "5632 PCanywhere Ping"
    FF_ComboBox_AddString HWND_FORM1_PORT, "5634 Old Gnutella"
    FF_ComboBox_AddString HWND_FORM1_PORT, "6346 Gnutella"
    FF_ComboBox_AddString HWND_FORM1_PORT, "6347 Gnutella 2"
    FF_ComboBox_AddString HWND_FORM1_PORT, "6699 Napster"
    FF_ComboBox_AddString HWND_FORM1_PORT, "6667 Sub 7"
    FF_ComboBox_AddString HWND_FORM1_PORT, "6711 Sub 7"
    FF_ComboBox_AddString HWND_FORM1_PORT, "6712 Sub 7"
    FF_ComboBox_AddString HWND_FORM1_PORT, "6713 Sub 7"
    FF_ComboBox_AddString HWND_FORM1_PORT, "6776 Sub 7"
    FF_ComboBox_AddString HWND_FORM1_PORT, "8787 BackOriface"
    FF_ComboBox_AddString HWND_FORM1_PORT, "8879 BackOriface"
    FF_ComboBox_AddString HWND_FORM1_PORT, "12345 Amitis.B"
    FF_ComboBox_AddString HWND_FORM1_PORT, "16959 Sub 7"
    FF_ComboBox_AddString HWND_FORM1_PORT, "17300 Kuang2 Virus"
    FF_ComboBox_AddString HWND_FORM1_PORT, "53001 Remote Shutdown"
    FF_ComboBox_AddString HWND_FORM1_PORT, "54320 BackOriface"
    FF_ComboBox_AddString HWND_FORM1_PORT, "54321 BackOriface"
    FF_ComboBox_AddString HWND_FORM1_PORT, "65535 Linux Worm"  
End Function

Function FORM1_WM_DESTROY (hWndForm As Dword) As Long
    SetWindowLong(GetDlgItem(HWND_FORM1_PORT, 1001), %GWL_WNDPROC, gOldSubClassProc)
End Function
Logged

TechSupport

  • Guest
? on combo box autocompletion
« Reply #6 on: July 12, 2004, 04:53:06 PM »

This is not working because this type of combobox is composed of two controls; and edit control and listbox. I am modifying FireFly's code to subclass the edit control portion as well thus allowing FireFly to handle the keyboard movements.
Logged

Roger Garstang

  • Guest
? on combo box autocompletion
« Reply #7 on: July 12, 2004, 04:54:09 PM »

Hey Paul, I just posted the code you need...hehehe

This only needs done on CBS_DROPDOWN and CBS_SIMPLE style combos too.
Logged

Roger Garstang

  • Guest
? on combo box autocompletion
« Reply #8 on: July 12, 2004, 05:14:46 PM »

This would make a cool new control for FF.  Maybe even with an option in the property sheet to flip the list of the combo open or not like IE's url bar does. (CB_SHOWDROPDOWN If searchResult <> %CB_ERR)
Logged

Paul D. Elliott

  • Guest
? on combo box autocompletion
« Reply #9 on: July 12, 2004, 05:22:16 PM »

Roger,

Thanks. I'll see if I can plug this into my program.

---------------------------

Paul,

Will FF be setting the CB_SETEXTENDEDUI setting for Combo boxes?
I just checked with PB Forms and it was setting the style manually in
code. and it seemed to do the autocompletion without extra code on
my part. but then I found a glitch ( on my system at least ) with the
properties tabs in PB Forms and sent a request to their support. ( The
3rd tab is bleeding over into the 2nd tab. Well, that's their problem )

Will this change be in v1.06 and will it be out soon? No real rush as I'm
still learning this stuff and have a ways to go before I put anything into
production.
Logged

TechSupport

  • Guest
? on combo box autocompletion
« Reply #10 on: July 12, 2004, 05:29:45 PM »

Quote from: "Roger Garstang"
Hey Paul, I just posted the code you need...hehehe

This only needs done on CBS_DROPDOWN and CBS_SIMPLE style combos too.

Thanks Roger - you're certainly on top of things. :)

I am modifying the generated source code to automatically do the subclassing so the user won't have to.
Logged

David Martin

  • Guest
? on combo box autocompletion
« Reply #11 on: July 12, 2004, 10:16:31 PM »

Quote from: "TechSupport"
Thanks Roger - you're certainly on top of things. :)
Yeah, I was thinking Roger was having way to much fun with this. :wink:
Logged

Roger Garstang

  • Guest
? on combo box autocompletion
« Reply #12 on: July 12, 2004, 11:46:38 PM »

You mean you don't have fun with FireFly?  Man, I live on this forum just to see what new toys I can play with.  FF is awesome!

That, and the one app I used the AutoComplete in also had Radio Buttons I Subclassed and made into status lights...so I had the subclassing code to cut and paste too.  That same App also had a %BS_PUSHLIKE button too I used as a toggle...hopefully Paul saw my WishList request to have that and the other non-auto styles for checkboxes/radio buttons available as properties/styles.
Logged

Paul D. Elliott

  • Guest
? on combo box autocompletion
« Reply #13 on: July 29, 2004, 01:53:06 PM »

I've still got a small problem. If I start typing and it finds a match so far,
it won't let me backspace to clear the whole entry. As far as I'm concerned
( as a user ), I've typed 1 character and it automatically filled in the rest.
But then I change my mind and want to simply backspace over the 1
character I've typed to start over ( say I'm a lousy typist ).  It won't let
me and is frustrating. It takes a lot of keystrokes to get back to an empty
field to start typing again and my users won't like it.

I found a routine for VB that so far does what I want but it gets called from
the keypress event. I'm not sure but with the latest FF doing the sub-
classing, will I have access to that routine? In v1.05 I probably could have
done it when I created the sub-classing.

I'm just trying to get the best of all possible solutions. I'm currently
creating versions of roughly the same program in FF & EZGui & Delphi
and VB.
The easiest version for the users will probably be the one used.

Thanks for your help.
Logged

Roger Garstang

  • Guest
? on combo box autocompletion
« Reply #14 on: July 29, 2004, 08:12:15 PM »

That is what the line:

If lengthComboString > previousSize Then

is supposed to do, then it only does it if the character typed makes it larger, backspace makes it <= previousSize so it shouldn't process when backspace is pressed.
Logged
Pages: [1] 2