Jump to content

Making a search box that gives query suggestions?


Herb191
 Share

Recommended Posts

How would a person go about making a search box that gives query suggestions? The idea is to make a search assist built into an input box. Something like you see on most search engines like Yahoo or Google. I would like to pull the search suggestions from an already existing .ini file.

I was thinking about trying to use GUICtrlCreateCombo in a loop that is continually refreshing its list of items depending on what is typed in the box. But I am not sure if there is a way to make the GUICtrlCreateCombo menu stay open when refreshing or typing.

Anyone have any ideas?

Link to comment
Share on other sites

make an Input box with button beside it and a child GUI popup that looks like the combox?

Link to comment
Share on other sites

with GUIgetcursorinfo and label controls containing the suggestions?

Link to comment
Share on other sites

with GUIgetcursorinfo and label controls containing the suggestions?

Ok I’m not sure I know how to do that. I would like to be able to type in part of a word and then use the arrow keys or mouse to select the option I want.

So typing “som” would bring up a list of something like this:

Something

Some

Somebody

I am not sure how I can do that with GUIgetcursorinfo and label controls. :)

Link to comment
Share on other sites

guictrlcreateCOMBO () does that... but it will not bring the suggestions up automatically but it does give you a list to choose from

oops my bad... typo

Edited by CodyBarrett
Link to comment
Share on other sites

guictrlcreateCOMBO () does that... but it will not bring the suggestions up automatically but it does give you a list to choose from

oops my bad... typo

Right, I think I can write the script to bring up the suggestions automatically with a loop but then I come back to my original problem. I am not sure if there is a way to make the GUICtrlCreateCombo menu stay open when refreshing or typing.

Link to comment
Share on other sites

Here is an autocomplete example using an ini file. You can use the exact same system for your purposes. I wasn't permitted to upload an ini file. So create "files.ini" in keeping with the below format and put in the same directory.

[files]
Schedules=c:\Schedule.xls
About=c:\about.exe
Timesheet=D:\Timesheet2009.xls
Other=D:\other.xls
Annual=D:\annual.xls

slickrun.au3

Edited by picea892
Link to comment
Share on other sites

I think your best bet would be to make your own child gui that looks like a combobox like Cody said. I don't think there is a way to make the combobox itself stay open.

Yeah I have been playing around with it a bit and I think it will work. I only one more question how do you keep the border from displaying the column information at the top of the child window?

Here is an example of what I mean:

#AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6
#include <GuiConstantsEx.au3>
#include <GuiListView.au3>
#include <WindowsConstants.au3>
Global $Input, $Inputread

HotKeySet('{ESC}', '_EXIT')

GUICreate("Main", 500, 425, 50, 50)
$Input = GUICtrlCreateInput("", 47, 57, 400, 20)
GUISetState()


While 1
    $Inputread = (GUICtrlRead($Input))
    If $Inputread = ("0") Then $Input = ("")
    GUISetState()
    Select
        Case $Inputread <> ("")
            _Dropdown()
    EndSelect
WEnd


_Dropdown()

Func _Dropdown()
    Local $hListView

    GUICreate("Dropdown", 400, 325, 100, 150, $WS_POPUP, $WS_EX_MDICHILD)
    $hListView = GUICtrlCreateListView("", 47, 77, 400, 350)

    GUISetState()

    _GUICtrlListView_InsertColumn($hListView, 0, "Column 1", 100)
    _GUICtrlListView_AddItem($hListView, "Item 1")
    _GUICtrlListView_AddItem($hListView, "Item 2")
    _GUICtrlListView_AddItem($hListView, "Item 3")

    Do
    Until GUIGetMsg() = $GUI_EVENT_CLOSE
    GUIDelete()

EndFunc   ;==>_Dropdown



Func _EXIT()
    Local $iMsgBoxAnswer

    $iMsgBoxAnswer = MsgBox(262193, "", "Are you sure you want to exit?")

    Select
        Case $iMsgBoxAnswer = 1 ;OK
            GUIDelete()
            Exit
        Case $iMsgBoxAnswer = 2 ;Cancel
    EndSelect
EndFunc   ;==>_EXIT
Link to comment
Share on other sites

Here is an autocomplete example using an ini file. You can use the exact same system for your purposes. I wasn't permitted to upload an ini file. So create "files.ini" in keeping with the below format and put in the same directory.

[files]
Schedules=c:\Schedule.xls
About=c:\about.exe
Timesheet=D:\Timesheet2009.xls
Other=D:\other.xls
Annual=D:\annual.xls

Thanks, Picea I tried to run it but I got an error:

(12) : ==> Subscript used with non-Array variable.:

I will take a better look at it in the morning I am sure its just a typo or something. Thanks again.

Link to comment
Share on other sites

Here is a concept for you to play with. I'm using an edit control and no buttons to do it but you can use what you want. The trick is in the _GUICtrlListview*() functions. It could also be done with the Listview created on a popup window. It takes a few seconds to load because of the file I'm using for testing (in the attached zip). Just start typing sentences into the edit control. It's set to ignore words less than 4 characters in lengh.

#include<GuiListView.au3>
#include<GuiConstantsEx.au3>
#include<EditConstants.au3>
#include<WindowsConstants.au3>
$sWords = StringLower(FileRead(@ScriptDir & "\wordlist2.txt"))
GUICreate("Test", 320, 500)
$Edit_1 = GUICtrlCreateEdit("", 10, 10, 300, 200, BitOR($ES_WANTRETURN, $ES_AUTOVSCROLL, $WS_VSCROLL))
$LV_1 = GUICtrlCreateListView("Suggestions", 10, 250, 300, 200)
_GUICtrlListView_SetColumnWidth($LV_1, 0, 280)
$lvStart = GUICtrlCreateDummy()
$lvEnd = GUICtrlCreateDummy()
$sStr = GUICtrlRead($Edit_1)
GUISetState()
While 1
   $Msg = GUIGetMsg()
   If GUICtrlRead($Edit_1) <> $sStr Then
      $sStr = GUICtrlRead($Edit_1)
      If StringRegExp($sStr,"(?s)^.+\b[\s?!.]$") Then _ClearList()
      If StringRegExp($sStr, "(?i)(?s)^.*\b([a-z]{4,})$") Then
         $slast = StringRegExpReplace($sStr, "(?i)(?s)^.*\b([a-z]{4,})$", "$1")
         If NOT @Error Then _GetWords($slast)
      EndIf
   EndIf
   If _GUICtrlListView_GetItemCount($LV_1) Then
      $sReplace = _GUICtrlListView_GetItemTextString($LV_1)
      If $sReplace Then
         If StringRegExp($sStr, "^" & $slast & "$|[.?!]\s*" & $slast & "$") Then
            $sReplace = StringUpper(StringLeft($sReplace, 1)) & StringMid($sReplace, 2)
         EndIf
         $sStr = StringRegExpReplace($sStr,"(?i)(?s)^(.*)" & $slast & "$", "$1") & $sReplace
         GUICtrlSetData($Edit_1, $sStr)
         GUICtrlSetState($Edit_1, $GUI_FOCUS)
         Send("^{end}")
         _ClearList()
      EndIf
   EndIf
   Switch $Msg
      Case -3
         Exit
      Case Else
   EndSwitch
WEnd
Func _GetWords($s_Word)
   _GUICtrlListView_BeginUpdate($LV_1)
   For $i = $lvStart To $lvEnd
      GUICtrlDelete($i)
   Next
   $lvStart = GUICtrlCreateDummy()
   $aWords = StringRegExp($sWords, "(?i)(?m:^)(" & $s_Word & ".*)(?:\v|$)", 3)
   If @Error Then
      _GUICtrlListView_EndUpdate($LV_1)
      $lvEnd = GUICtrlCreateDummy()
      Return
   EndIf
   For $i = 0 To Ubound($aWords) -1
      GUICtrlCreateListViewItem($aWords[$i], $LV_1)
   Next
   _GUICtrlListView_EndUpdate($LV_1)
   $lvEnd = GUICtrlCreateDummy()
EndFunc   ;<==> _GetWords()
Func _ClearList()
   If NOT _GUICtrlListView_GetItemCount($LV_1) Then Return
   _GUICtrlListView_BeginUpdate($LV_1)
   For $i = $lvStart To $lvEnd
      GUICtrlDelete($i)
   Next
   _GUICtrlListView_EndUpdate($LV_1)
   $lvStart = GUICtrlCreateDummy()
   $lvEnd = GUICtrlCreateDummy()
EndFunc   ;<==> _ClearList()

EDIT: Added a couple of lines to capitalize the first word of a sentence.

EDIT2: Wordlist attachment removed. You can find it here

Edited by GEOSoft

George

Question about decompiling code? Read the decompiling FAQ and don't bother posting the question in the forums.

Be sure to read and follow the forum rules. -AKA the AutoIt Reading and Comprehension Skills test.***

The PCRE (Regular Expression) ToolKit for AutoIT - (Updated Oct 20, 2011 ver:3.0.1.13) - Please update your current version before filing any bug reports. The installer now includes both 32 and 64 bit versions. No change in version number.

Visit my Blog .. currently not active but it will soon be resplendent with news and views. Also please remove any links you may have to my website. it is soon to be closed and replaced with something else.

"Old age and treachery will always overcome youth and skill!"

Link to comment
Share on other sites

Hi,

You may want to try this too...

#AutoIt3Wrapper_au3check_parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6
#include <GUIComboBox.au3>
#include <GuiConstantsEx.au3>
#include <WindowsConstants.au3>
#include <ComboConstants.au3>
#include <Array.au3>


Opt('MustDeclareVars', 1)

$Debug_CB = False ; Check ClassName being passed to ComboBox/ComboBoxEx functions, set to True and use a handle to another control to see it work

Global $hCombo, $Search , $dbase, $word, $msg

; suggestions database
$dbase = "AutoIt v3 is a freeware BASIC-like scripting language designed for automating the Windows GUI and general scripting. It uses a combination of simulated keystrokes, mouse movement and window/control manipulation in order to automate tasks in a way not possible or reliable with other languages (e.g. VBScript and SendKeys). AutoIt is also very small, self-contained and will run on all versions of Windows out-of-the-box with no annoying ""runtimes"" required!"

_Main()

Func _Main()

    ; Create GUI
    GUICreate("ComboBox Auto Complete", 400, 296)
    $hCombo = GUICtrlCreateCombo("", 2, 2, 270, 200)
    $Search = GUICtrlCreateButton ( "  Search  ", 275, 2)
    GUISetState()

    ; Add files
    _GUICtrlComboBox_BeginUpdate($hCombo)
    _GUICtrlComboBox_InsertString($hCombo, "Initial text", 0)
    _GUICtrlComboBox_EndUpdate($hCombo)
    _GUICtrlComboBox_ShowDropDown($hCombo, False)

    GUIRegisterMsg($WM_COMMAND, "WM_COMMAND")

    ; Loop until user exits
    Do
        $msg = GUIGetMsg()
        If $msg = $Search Then MsgBox(0,"","Dummy search...")
    Until $msg = $GUI_EVENT_CLOSE
    GUIDelete()
EndFunc   ;==>_Main

Func _Edit_Changed()
    $word = _GUICtrlComboBox_GetEditText($hCombo)
    _GUICtrlComboBox_ResetContent($hCombo)
    If $word <> "" Then
        _GUICtrlComboBox_ShowDropDown($hCombo, True)
        Local $array = StringRegExp($dbase, "(?i)\b"&$word&"\S*", 3)
        For $i = 0 To UBound($array)-1
            _GUICtrlComboBox_InsertString($hCombo, $array[$i], 0)
        Next
    Else
        _GUICtrlComboBox_ShowDropDown($hCombo, False)
    EndIf
    _GUICtrlComboBox_SetEditText($hCombo,$word)
    _GUICtrlComboBox_AutoComplete($hCombo)
EndFunc   ;==>_Edit_Changed

Func WM_COMMAND($hWnd, $iMsg, $iwParam, $ilParam)
    #forceref $hWnd, $iMsg
    Local $hWndFrom, $iIDFrom, $iCode, $hWndCombo
    If Not IsHWnd($hCombo) Then $hWndCombo = GUICtrlGetHandle($hCombo)
    $hWndFrom = $ilParam
    $iIDFrom = BitAND($iwParam, 0xFFFF) ; Low Word
    $iCode = BitShift($iwParam, 16) ; Hi Word
    Switch $hWndFrom
        Case $hCombo, $hWndCombo
            Switch $iCode
                Case $CBN_CLOSEUP ; Sent when the list box of a combo box has been closed
                    ; no return value
                Case $CBN_DBLCLK ; Sent when the user double-clicks a string in the list box of a combo box
                    ; no return value
                Case $CBN_DROPDOWN ; Sent when the list box of a combo box is about to be made visible
                    ; no return value
                Case $CBN_EDITCHANGE ; Sent after the user has taken an action that may have altered the text in the edit control portion of a combo box
                    _Edit_Changed()
                    ; no return value
                Case $CBN_EDITUPDATE ; Sent when the edit control portion of a combo box is about to display altered text
                    ; no return value
                Case $CBN_ERRSPACE ; Sent when a combo box cannot allocate enough memory to meet a specific request
                    ; no return value
                Case $CBN_KILLFOCUS ; Sent when a combo box loses the keyboard focus
                    ; no return value
                Case $CBN_SELCHANGE ; Sent when the user changes the current selection in the list box of a combo box
                    ; no return value
                Case $CBN_SELENDCANCEL ; Sent when the user selects an item, but then selects another control or closes the dialog box
                    ; no return value
                Case $CBN_SELENDOK ; Sent when the user selects a list item, or selects an item and then closes the list
                    ; no return value
                Case $CBN_SETFOCUS ; Sent when a combo box receives the keyboard focus
                    ; no return value
            EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_COMMAND

I wrote this script based on _GUICtrlComboBox_AutoComplete sample.

Hi ;)

Link to comment
Share on other sites

guys there is any any way to eliminate the user32.dll ? i try to use 'picea892' sample its works fine under xp/vista but under win PE its fail ... i can't select word, file exist ini is ok hmm maybe its some issue with mapped network drive, i have lot of backup.cmd's with i implement in files.ini.

Link to comment
Share on other sites

Yes, you just have to find another way to detect if the Enter button is pressed. That can be done using HotKeySet. Here is the resulting code:

#include <GuiConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GuiComboBox.au3>
#include <Misc.au3>
;Dim $sString = "Hello|world|AutoIt|rules|and|more|some|data"

HotKeySet("{ENTER}", "EnterPressed")

$hGUI = GUICreate("AutoComplete Combo Demo", 300, 200)
$filelist = IniReadSection("files.ini", "files")
Global $sString = ""
For $i = 1 To $filelist[0][0]
    $sString = $sString & "|" & $filelist[$i][0]
Next
$hCombo = GUICtrlCreateCombo("", 70, 75, 170, 20)
GUICtrlSetData(-1, $sString, "")

GUIRegisterMsg($WM_COMMAND, "WM_COMMAND")

GUISetState()

Do
    Sleep(50)
Until GUIGetMsg() = $GUI_EVENT_CLOSE

Func WM_COMMAND($hWnd, $Msg, $wParam, $lParam)
    Local $iIDFrom = BitAND($wParam, 0x0000FFFF)
    Local $iCode = BitShift($wParam, 16)

    Switch $iIDFrom
        Case $hCombo
            Switch $iCode
                Case $CBN_EDITCHANGE
                    _GUICtrlComboBox_AutoComplete($hCombo)
            EndSwitch
    EndSwitch

    Return $GUI_RUNDEFMSG
EndFunc ;==>WM_COMMAND

Func EnterPressed()
    $var = IniRead("files.ini", "files", GUICtrlRead($hCombo), "-1")
    ShellExecute($var)
EndFunc ;==>EnterPressed
Link to comment
Share on other sites

Yes, you just have to find another way to detect if the Enter button is pressed. That can be done using HotKeySet. Here is the resulting code:

#include <GuiConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GuiComboBox.au3>
#include <Misc.au3>
;Dim $sString = "Hello|world|AutoIt|rules|and|more|some|data"

HotKeySet("{ENTER}", "EnterPressed")

$hGUI = GUICreate("AutoComplete Combo Demo", 300, 200)
$filelist = IniReadSection("files.ini", "files")
Global $sString = ""
For $i = 1 To $filelist[0][0]
    $sString = $sString & "|" & $filelist[$i][0]
Next
$hCombo = GUICtrlCreateCombo("", 70, 75, 170, 20)
GUICtrlSetData(-1, $sString, "")

GUIRegisterMsg($WM_COMMAND, "WM_COMMAND")

GUISetState()

Do
    Sleep(50)
Until GUIGetMsg() = $GUI_EVENT_CLOSE

Func WM_COMMAND($hWnd, $Msg, $wParam, $lParam)
    Local $iIDFrom = BitAND($wParam, 0x0000FFFF)
    Local $iCode = BitShift($wParam, 16)

    Switch $iIDFrom
        Case $hCombo
            Switch $iCode
                Case $CBN_EDITCHANGE
                    _GUICtrlComboBox_AutoComplete($hCombo)
            EndSwitch
    EndSwitch

    Return $GUI_RUNDEFMSG
EndFunc ;==>WM_COMMAND

Func EnterPressed()
    $var = IniRead("files.ini", "files", GUICtrlRead($hCombo), "-1")
    ShellExecute($var)
EndFunc ;==>EnterPressed

thx for reply, yep now its works fine without .dll but looks me issue is UNC path ... when i copy all to RAM on x: its will works ...

edit:

ha its works, i just add copy backup script to x: and exec from x: :)

thx

Edited by lxxl
Link to comment
Share on other sites

I've made something (an example like this) in the past but using a combo. I think it was under auto complete or something. Have a quick search and see if you can find it :)

Link to comment
Share on other sites

  • 4 months later...

Here is a concept for you to play with. I'm using an edit control and no buttons to do it but you can use what you want. The trick is in the _GUICtrlListview*() functions. It could also be done with the Listview created on a popup window. It takes a few seconds to load because of the file I'm using for testing (in the attached zip). Just start typing sentences into the edit control. It's set to ignore words less than 4 characters in lengh.

#include<GuiListView.au3>
#include<GuiConstantsEx.au3>
#include<EditConstants.au3>
#include<WindowsConstants.au3>
$sWords = StringLower(FileRead(@ScriptDir & "\wordlist2.txt"))
GUICreate("Test", 320, 500)
$Edit_1 = GUICtrlCreateEdit("", 10, 10, 300, 200, BitOR($ES_WANTRETURN, $ES_AUTOVSCROLL, $WS_VSCROLL))
$LV_1 = GUICtrlCreateListView("Suggestions", 10, 250, 300, 200)
_GUICtrlListView_SetColumnWidth($LV_1, 0, 280)
$lvStart = GUICtrlCreateDummy()
$lvEnd = GUICtrlCreateDummy()
$sStr = GUICtrlRead($Edit_1)
GUISetState()
While 1
   $Msg = GUIGetMsg()
   If GUICtrlRead($Edit_1) <> $sStr Then
      $sStr = GUICtrlRead($Edit_1)
      If StringRegExp($sStr,"(?s)^.+\b[\s?!.]$") Then _ClearList()
      If StringRegExp($sStr, "(?i)(?s)^.*\b([a-z]{4,})$") Then
         $slast = StringRegExpReplace($sStr, "(?i)(?s)^.*\b([a-z]{4,})$", "$1")
         If NOT @Error Then _GetWords($slast)
      EndIf
   EndIf
   If _GUICtrlListView_GetItemCount($LV_1) Then
      $sReplace = _GUICtrlListView_GetItemTextString($LV_1)
      If $sReplace Then
         If StringRegExp($sStr, "^" & $slast & "$|[.?!]\s*" & $slast & "$") Then
            $sReplace = StringUpper(StringLeft($sReplace, 1)) & StringMid($sReplace, 2)
         EndIf
         $sStr = StringRegExpReplace($sStr,"(?i)(?s)^(.*)" & $slast & "$", "$1") & $sReplace
         GUICtrlSetData($Edit_1, $sStr)
         GUICtrlSetState($Edit_1, $GUI_FOCUS)
         Send("^{end}")
         _ClearList()
      EndIf
   EndIf
   Switch $Msg
      Case -3
         Exit
      Case Else
   EndSwitch
WEnd
Func _GetWords($s_Word)
   _GUICtrlListView_BeginUpdate($LV_1)
   For $i = $lvStart To $lvEnd
      GUICtrlDelete($i)
   Next
   $lvStart = GUICtrlCreateDummy()
   $aWords = StringRegExp($sWords, "(?i)(?m:^)(" & $s_Word & ".*)(?:\v|$)", 3)
   If @Error Then
      _GUICtrlListView_EndUpdate($LV_1)
      $lvEnd = GUICtrlCreateDummy()
      Return
   EndIf
   For $i = 0 To Ubound($aWords) -1
      GUICtrlCreateListViewItem($aWords[$i], $LV_1)
   Next
   _GUICtrlListView_EndUpdate($LV_1)
   $lvEnd = GUICtrlCreateDummy()
EndFunc   ;<==> _GetWords()
Func _ClearList()
   If NOT _GUICtrlListView_GetItemCount($LV_1) Then Return
   _GUICtrlListView_BeginUpdate($LV_1)
   For $i = $lvStart To $lvEnd
      GUICtrlDelete($i)
   Next
   _GUICtrlListView_EndUpdate($LV_1)
   $lvStart = GUICtrlCreateDummy()
   $lvEnd = GUICtrlCreateDummy()
EndFunc   ;<==> _ClearList()

EDIT: Added a couple of lines to capitalize the first word of a sentence.

Loved this! I was trying to incorporate a keyboard shortcut but there's some weird behavior that I dont get.

After typing something in the edit control, I transfer focus to the first line of the list in the suggestions box by pressing the down arrow key on the keyboard. Focus works ok, but I need to send yet another "down" keystroke, so that next time I press it, then it will go the next item. Otherwise down needs to be physically pressed twice. Why??

Here is what I tried - putting this code inside the main While loop

; this is a global flag for the very first "down", dont put inside while
$listIndex == -1 

;the below is inside While
  If _IsPressed("28", $dll) AND $listIndex == -1 Then
    _GUICtrlListView_SetItemSelected($LV_1, 0)
    GUICtrlSetState($LV_1, $GUI_FOCUS)
    Send ("{DOWN}")   ;why???
    $listIndex = $listIndex +1  
  EndIf

Would appreciate any help.

Thanks!

Edited by aria
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...