Jump to content

Recommended Posts

Posted (edited)

Using Melba23  post here as a guide  (Thanks for the enlightenment)

I managed to get this far
A Autocomplete selector for existing tags
 

#include <GUIConstantsEx.au3>
#include <EditConstants.au3>
#include <WindowsConstants.au3>
#include <Array.au3>
#include <WinAPI.au3>
#include <GuiListBox.au3>

; Global Variables
Global $g_hMainGUI
Global $g_idEditInputTags
Global $g_idListboxSuggestions
Global $g_hListboxSuggestionsHWND
Global $g_aAvailableTags
Global $g_iCurrentSuggestionIndex = -1

; Dummy control IDs for accelerators (Listbox Navigation Key)
Global $g_idAccelUp, $g_idAccelDown, $g_idAccelEnter, $g_idAccelEscape

; Load all unique tags from database
$g_aAvailableTags = _GetAllUniqueTags()
If @error Then MsgBox(16, "Error", "Failed to load unique tags from database.")

_CreateGUI() ; Create Main GUI

Exit

;---------------------------------------------------------------------------------------
Func _GetAllUniqueTags()
    ; This function should retrieve your actual unique tags from a database or file.
    ; For demonstration, it reads words from a text file.
    Local $sString = StringLower(FileRead("C:\Program Files (x86)\AutoIt3\SciTE\SciTE Jump\License.txt"))

    ; matches sequences of letters that are at least 4 characters long
    Local $aWords = StringRegExp($sString, '[a-zA-Z]{4,}', 3)

    $aWords = _ArrayUnique($aWords)
    ; This removes the count element from the array returned by StringRegExp with flag 3.
    If UBound($aWords) > 0 Then _ArrayDelete($aWords, 0)
    _ArraySort($aWords)

    Return $aWords
EndFunc   ;==>_GetAllUniqueTags
;---------------------------------------------------------------------------------------
Func _CreateGUI()
    $g_hMainGUI = GUICreate("Main GUI", 700, 300)

    GUICtrlCreateLabel("Title:", 10, 20, 50, 20)
    Local $idTitle = GUICtrlCreateInput("", 70, 20, 600, 25)

    GUICtrlCreateLabel("Tags:", 10, 60, 50, 20)
    $g_idEditInputTags = GUICtrlCreateInput("", 70, 60, 600, 25, $ES_AUTOVSCROLL)
    GUICtrlSetLimit($g_idEditInputTags, 250)

    Local $aPos = ControlGetPos($g_hMainGUI, "", $g_idEditInputTags)
    If @error Then Exit MsgBox(16, "Error", "Failed to get position of Tags input control. Exiting.")

    ; Suggestions Listbox
    $g_idListboxSuggestions = GUICtrlCreateList("", $aPos[0], $aPos[1] + $aPos[3], $aPos[2], 150, BitOR($LBS_NOTIFY, $WS_VSCROLL, $WS_BORDER, $WS_TABSTOP))
    GUICtrlSetState($g_idListboxSuggestions, $GUI_HIDE)
    $g_hListboxSuggestionsHWND = GUICtrlGetHandle($g_idListboxSuggestions)

    GUIRegisterMsg($WM_COMMAND, "_WM_COMMAND_Handler")
    GUIRegisterMsg($WM_MOUSEWHEEL, "_WM_MOUSEWHEEL_Handler")

    $g_idAccelUp = GUICtrlCreateDummy()
    $g_idAccelDown = GUICtrlCreateDummy()
    $g_idAccelEnter = GUICtrlCreateDummy()
    $g_idAccelEscape = GUICtrlCreateDummy()

    Local $AccelKeys[4][2] = [ _
            ["{UP}", $g_idAccelUp], _
            ["{DOWN}", $g_idAccelDown], _
            ["{ENTER}", $g_idAccelEnter], _
            ["{ESCAPE}", $g_idAccelEscape] _
            ]

    GUISetAccelerators($AccelKeys)
    Local $idExit = GUICtrlCreateButton("Exit", 300, 250, 100, 30)
    GUISetState(@SW_SHOW)

    Local $iMsg

    While 1
        $iMsg = GUIGetMsg()
        Switch $iMsg
            Case $GUI_EVENT_CLOSE, $idExit
                ExitLoop
            Case $g_idAccelUp
                _ListboxNavigationKey($g_idAccelUp)
            Case $g_idAccelDown
                _ListboxNavigationKey($g_idAccelDown)
            Case $g_idAccelEnter
                _ListboxNavigationKey($g_idAccelEnter)
            Case $g_idAccelEscape
                _ListboxNavigationKey($g_idAccelEscape)
        EndSwitch
    WEnd

    GUIDelete($g_hMainGUI)

EndFunc   ;==>_CreateGUI
;---------------------------------------------------------------------------------------
Func _ApplySelectedTag($sSelectedTag)
    If $sSelectedTag = "" Then Return

    Local $sCurrentTags = GUICtrlRead($g_idEditInputTags)
    If @error Then Return

    Local $iLastCommaPos = StringInStr($sCurrentTags, ",", 0, -1) ; Find the last comma

    Local $sPrefixToKeep = ""
    If $iLastCommaPos > 0 Then
        $sPrefixToKeep = StringLeft($sCurrentTags, $iLastCommaPos)
        $sPrefixToKeep = StringStripWS($sPrefixToKeep, $STR_STRIPTRAILING) & " "
    EndIf

    Local $sNewTags = $sPrefixToKeep & $sSelectedTag & ", "

    GUICtrlSetData($g_idEditInputTags, $sNewTags)
    If @error Then Return

    _HideSuggestions()

    GUICtrlSetState($g_idEditInputTags, $GUI_FOCUS)
    If @error Then Return

    _WinAPI_PostMessage(GUICtrlGetHandle($g_idEditInputTags), $EM_SETSEL, StringLen($sNewTags), StringLen($sNewTags))

    $g_iCurrentSuggestionIndex = -1
EndFunc   ;==>_ApplySelectedTag
;---------------------------------------------------------------------------------------
Func _ShowSuggestions($sCurrentInput)
    Local $sTrimmedInput = StringStripWS($sCurrentInput, $STR_STRIPLEADING + $STR_STRIPTRAILING)
    If $sTrimmedInput = "" Then Return _HideSuggestions()

    Local $aInputParts = StringSplit($sTrimmedInput, ",", $STR_NOCOUNT)
    Local $sLastPart = ""
    If UBound($aInputParts) > 0 Then
        $sLastPart = StringStripWS($aInputParts[UBound($aInputParts) - 1], $STR_STRIPLEADING + $STR_STRIPTRAILING)
    Else
        $sLastPart = $sTrimmedInput
    EndIf

    If $sLastPart = "" Then Return _HideSuggestions()

    Local $aFilteredSuggestions[0]
    Local $iCount = 0
    Local $iLenLastPart = StringLen($sLastPart)

    For $sTag In $g_aAvailableTags
        If $sTag <> "" And StringLen($sTag) >= $iLenLastPart And StringLeft($sTag, $iLenLastPart) = $sLastPart Then
            _ArrayAdd($aFilteredSuggestions, $sTag)
            $iCount += 1
        EndIf
    Next

    If $iCount > 0 Then
        GUICtrlSendMsg($g_idListboxSuggestions, $LB_RESETCONTENT, 0, 0)
        For $sSuggestion In $aFilteredSuggestions
            If $sSuggestion <> "" Then
                GUICtrlSendMsg($g_idListboxSuggestions, $LB_ADDSTRING, 0, $sSuggestion)
            EndIf
        Next

        GUICtrlSetState($g_idListboxSuggestions, $GUI_SHOW)
        GUICtrlSendMsg($g_idListboxSuggestions, $LB_SETCURSEL, 0, 0)
        GUICtrlSendMsg($g_idListboxSuggestions, $LB_SETTOPINDEX, 0, 0)
        $g_iCurrentSuggestionIndex = 0
    Else
        _HideSuggestions()
    EndIf
EndFunc   ;==>_ShowSuggestions
;---------------------------------------------------------------------------------------
Func _HideSuggestions()
    GUICtrlSetState($g_idListboxSuggestions, $GUI_HIDE)
    GUICtrlSendMsg($g_idListboxSuggestions, $LB_RESETCONTENT, 0, 0)
    $g_iCurrentSuggestionIndex = -1
EndFunc   ;==>_HideSuggestions
;---------------------------------------------------------------------------------------
Func _ListboxNavigationKey($idKey)

    If Not BitAND(GUICtrlGetState($g_idListboxSuggestions), $GUI_SHOW) Then Return

    Local $iCount = GUICtrlSendMsg($g_idListboxSuggestions, $LB_GETCOUNT, 0, 0)
    If $iCount = 0 Then Return

    Switch $idKey
        Case $g_idAccelUp
            If $g_iCurrentSuggestionIndex <= 0 Then
                $g_iCurrentSuggestionIndex = $iCount - 1
            Else
                $g_iCurrentSuggestionIndex -= 1
            EndIf
            GUICtrlSendMsg($g_idListboxSuggestions, $LB_SETCURSEL, $g_iCurrentSuggestionIndex, 0)
            GUICtrlSendMsg($g_idListboxSuggestions, $LB_SETTOPINDEX, $g_iCurrentSuggestionIndex, 0)

        Case $g_idAccelDown
            If $g_iCurrentSuggestionIndex >= $iCount - 1 Then
                $g_iCurrentSuggestionIndex = 0
            Else
                $g_iCurrentSuggestionIndex += 1
            EndIf
            GUICtrlSendMsg($g_idListboxSuggestions, $LB_SETCURSEL, $g_iCurrentSuggestionIndex, 0)
            GUICtrlSendMsg($g_idListboxSuggestions, $LB_SETTOPINDEX, $g_iCurrentSuggestionIndex, 0)

        Case $g_idAccelEnter
            Local $iIndex = GUICtrlSendMsg($g_idListboxSuggestions, $LB_GETCURSEL, 0, 0)
            If $iIndex <> $LB_ERR Then
                Local $sSelectedTag = _GUICtrlListBox_GetText($g_idListboxSuggestions, $iIndex)
                If $sSelectedTag <> "" Then
                    _ApplySelectedTag($sSelectedTag)
                EndIf
            Else
                _HideSuggestions()
            EndIf
            $g_iCurrentSuggestionIndex = -1

        Case $g_idAccelEscape
            _HideSuggestions()
            $g_iCurrentSuggestionIndex = -1
    EndSwitch
EndFunc   ;==>_ListboxNavigationKey
;---------------------------------------------------------------------------------------
Func _WM_COMMAND_Handler($hWnd, $iMsg, $wParam, $lParam)
    Local $iControlID = _WinAPI_LoWord($wParam)
    Local $iNotificationCode = _WinAPI_HiWord($wParam)

    Switch $iMsg
        Case $WM_COMMAND
            Switch $iControlID
                Case $g_idEditInputTags
                    Switch $iNotificationCode
                        Case $EN_CHANGE
                            Local $sCurrentInput = GUICtrlRead($g_idEditInputTags)
                            _ShowSuggestions($sCurrentInput)
                        Case $EN_KILLFOCUS
                            Sleep(50)
                            Local $hFocusedWindow = _WinAPI_GetFocus()
                            Local $hListboxSuggestionsHandle = GUICtrlGetHandle($g_idListboxSuggestions)
                            Local $hEditInputTagsHandle = GUICtrlGetHandle($g_idEditInputTags)

                            If $hFocusedWindow <> $hListboxSuggestionsHandle And $hFocusedWindow <> $hEditInputTagsHandle Then
                                _HideSuggestions()
                                Local $sCurrentTags = GUICtrlRead($g_idEditInputTags)
                                If StringRight($sCurrentTags, 2) = ", " Then
                                    GUICtrlSetData($g_idEditInputTags, StringTrimRight($sCurrentTags, 2))
                                ElseIf StringRight($sCurrentTags, 1) = "," Then
                                    GUICtrlSetData($g_idEditInputTags, StringTrimRight($sCurrentTags, 1))
                                EndIf
                            EndIf
                    EndSwitch
                Case $g_idListboxSuggestions
                    Switch $iNotificationCode
                        Case $LBN_SELCHANGE
                            Local $iIndex = GUICtrlSendMsg($g_idListboxSuggestions, $LB_GETCURSEL, 0, 0)
                            If $iIndex <> $LB_ERR Then
                                Local $sSelectedTag = _GUICtrlListBox_GetText($g_idListboxSuggestions, $iIndex)
                                If $sSelectedTag <> "" Then
                                    _ApplySelectedTag($sSelectedTag)
                                EndIf
                            EndIf
                        Case $LBN_DBLCLK
                            Local $iIndex = GUICtrlSendMsg($g_idListboxSuggestions, $LB_GETCURSEL, 0, 0)
                            If $iIndex <> $LB_ERR Then
                                Local $sSelectedTag = _GUICtrlListBox_GetText($g_idListboxSuggestions, $iIndex)
                                If $sSelectedTag <> "" Then
                                    _ApplySelectedTag($sSelectedTag)
                                EndIf
                            EndIf
                    EndSwitch
            EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc   ;==>_WM_COMMAND_Handler
;---------------------------------------------------------------------------------------
Func _WM_MOUSEWHEEL_Handler($hWnd, $iMsg, $wParam, $lParam)
    ; Using GUIGetCursorInfo to find the control under the mouse
    Local $aCursorInfo = GUIGetCursorInfo($g_hMainGUI)

    ; Check if the mouse is over the suggestions ListBox and if the ListBox is visible
    If Not @error And IsArray($aCursorInfo) And UBound($aCursorInfo) >= 5 And $aCursorInfo[4] = $g_idListboxSuggestions And BitAND(GUICtrlGetState($g_idListboxSuggestions), $GUI_SHOW) Then
        Local $iDelta = _WinAPI_HiWord($wParam) ; How much the wheel turned (120 for a "click" up, -120 for a "click" down)
        Local $iNumLinesToScroll = 1 ; We scroll one line at a time with the wheel

        Local $iCurrentSelection = GUICtrlSendMsg($g_idListboxSuggestions, $LB_GETCURSEL, 0, 0)
        Local $iTotalItems = GUICtrlSendMsg($g_idListboxSuggestions, $LB_GETCOUNT, 0, 0)

        If $iTotalItems <= 0 Then Return 1 ; No items, nothing to scroll or select

        If $iDelta > 0 Then ; Scroll Up (wheel up)
            If $iCurrentSelection > 0 Then
                $g_iCurrentSuggestionIndex = $iCurrentSelection - $iNumLinesToScroll
                If $g_iCurrentSuggestionIndex < 0 Then $g_iCurrentSuggestionIndex = 0
            Else
                $g_iCurrentSuggestionIndex = 0 ; Already at the top
            EndIf
        Else ; Scroll Down (wheel down)
            If $iCurrentSelection < $iTotalItems - 1 Then
                $g_iCurrentSuggestionIndex = $iCurrentSelection + $iNumLinesToScroll
                If $g_iCurrentSuggestionIndex >= $iTotalItems Then $g_iCurrentSuggestionIndex = $iTotalItems - 1
            Else
                $g_iCurrentSuggestionIndex = $iTotalItems - 1 ; Already at the bottom
            EndIf
        EndIf

        ; We define the new option
        GUICtrlSendMsg($g_idListboxSuggestions, $LB_SETCURSEL, $g_iCurrentSuggestionIndex, 0)
        ; Also, make the selected element visible (if it isn't already)
        GUICtrlSendMsg($g_idListboxSuggestions, $LB_SETTOPINDEX, $g_iCurrentSuggestionIndex, 0)

        Return 1 ; Message has been handled
    EndIf

    Return $GUI_RUNDEFMSG ; Let AutoIt handle the message for other controls
EndFunc   ;==>_WM_MOUSEWHEEL_Handler

 

Please, every comment is appreciated!
leave your comments and experiences here!
Thank you very much  :)

Edited by ioa747

I know that I know nothing

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
  • Recently Browsing   0 members

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