• Offizieller Beitrag

    Als StandardControl haben wir ja mit der ComboBox die Möglichkeit eine eingabesensitive Auswahl zu ermöglichen.
    Ich habe hier mal ein Beispiel erstellt, wie man diese Funktionalität auch für z.B. Input-Ctrl erreichen kann.
    Gründe dafür:
    - ich finde es optisch nicht sehr ansprechend, wenn die Schaltfläche der ComboBox die GUI 'verschandelt'
    - ich habe hiermit die Möglichkeit eigene Auswahllisten auch für Fremdanwendungen (so sie denn Standard Windows Controls verwenden) zu nutzen


    Funktionsweise:
    Wird in das Inputfeld ein Buchstabe eingegeben, der auch als Anfangsbuchstabe in der Liste hinterlegt ist, popt das Auswahlfenster auf.
    Der Focus bleibt aber beim Inputfeld.
    Ist in der Liste kein Eintrag mit diesem Buchstaben, wird sie auch nicht eingeblendet.
    Es wird mit jedem weiteren Buchstaben auf Übereinstimmung geprüft und entsprechend der erste Eintrag markiert, auf den die bisherige Eingabe zutrifft.
    Mit PFEIL AUF / PFEIL AB kann in der Liste die Auswahl verschoben werden.
    Mit ENTER wird der momentan markierte Eintrag aus der Liste in das Input übernommen.
    Mit ESC kann die Liste ohne Übernahme gechlossen werden.

    Edit 08.03.09:
    Habe das Skript nochmal etwas bearbeitet. Alle bisher im Thread besprochenen Änderungen/Ergänzungen sind enthalten.
    Es ist jetzt allgemein gehalten, sodass es für Input- und ComboBox-Ctrl gleichermaßen verwendet werden kann. Es brauchen auch keine Anpassungen in den Funktionen für die Control-ID's erfolgen.
    Es muß zur Anwendung nur noch folgendes getan werden:
    - Einmalig bei der Erstellung eine Zuweisung auf den allgemeinen Namen ($SenseGui u. $SenseCtrl)
    - Befüllen des DatenArray mit den Auswahldaten
    Edit zum Edit: $nNotifyCode für ComboBox fehlte noch :S - jetzt komplett

    Spoiler anzeigen
    [autoit]

    #include<GUIConstantsEx.au3>
    #include<ListBoxConstants.au3>
    #include <WindowsConstants.au3>
    #include <GUIListBox.au3>
    #Include <WinAPI.au3>
    #include <Misc.au3>
    Opt("GUICloseOnESC", 0)

    [/autoit] [autoit][/autoit] [autoit]

    #region - Deklarationen für Sense
    Global $show = False
    Global $indexB = -1
    Global $SenseGui, $SenseCtrl, $guiBox, $box
    Global $POSSenseGui[2]
    #Region Box
    ; Hier die Auswahldaten (braucht nicht sortiert sein):
    Global $aData[10] = ['Birne','Alligator','Auto','Dank','Automat','Bett','Garten','Bettler','Danke','Danksagung']
    $guiBox = GUICreate('', 150, 85, 0, 0, BitOR($WS_SIZEBOX,$WS_POPUP), $WS_EX_TOPMOST)
    $box = _GUICtrlListBox_Create($guiBox, '', 0, 0, 150, 86, BitOR($LBS_SORT, 0x00B00002))
    ; ListBox muß 1 Pixel höher als GUI sein - sonst fehlerhafte Darstellung
    For $i = 0 To UBound($aData) -1 ; falls Daten mit _FileReadToArray gelesen werden: StartIndex=1
    _GUICtrlListBox_AddString($box, $aData[$i])
    Next
    #EndRegion Box
    GUIRegisterMsg($WM_COMMAND, "MY_WM_COMMAND")
    GUIRegisterMsg($WM_MOVE, "_WM_MOVE")
    GUIRegisterMsg(0x231, "_WM_ENTERSIZEMOVE")
    #EndRegion - Deklarationen Sense

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    #Region Main
    $Form1 = GUICreate('Intelli Sense Box', 400, 300, 200, 50)
    $SenseGui = $Form1 ; <== Für Allgemeingültigkeit Zuweisung an $SenseGui
    $Input = GUICtrlCreateInput('', 10, 10, 380, 21)
    $SenseCtrl = $Input ; <== Für Allgemeingültigkeit Zuweisung an $SenseCtrl
    $hInput = GUICtrlGetHandle($Input)
    GUISetState()
    #EndRegion Main

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    While True
    _ChooseBox()
    If GUIGetMsg() = $GUI_EVENT_CLOSE Then Exit
    WEnd

    [/autoit] [autoit][/autoit] [autoit]

    #region - SenseFuncs
    Func _ChooseBox()
    If Not $show Then Return
    If _IsPressed('0D') Then ; ENTER
    ControlSetText($SenseGui, '', $SenseCtrl, _GUICtrlListBox_GetText($box, $indexB))
    GUISetState(@SW_HIDE, $guiBox)
    $show = False
    ElseIf _IsPressed('1B') Then ; ESC
    GUISetState(@SW_HIDE, $guiBox)
    $show = False
    ElseIf _IsPressed('26') Then ; UP
    If $indexB > 0 Then
    $indexB -= 1
    _GUICtrlListBox_SetCurSel($box, $indexB)
    Sleep(90)
    EndIf
    ElseIf _IsPressed('28') Then ; DOWN
    If $indexB < _GUICtrlListBox_GetCount($box)-1 Then
    $indexB += 1
    _GUICtrlListBox_SetCurSel($box, $indexB)
    Sleep(90)
    EndIf
    EndIf
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func MY_WM_COMMAND($hWnd, $Msg, $wParam, $lParam)
    Local $nNotifyCode = BitShift($wParam, 16)
    Local $hCtrl = $lParam
    Local $hSenseCtrl = $SenseCtrl
    If Not IsHWnd($hSenseCtrl) Then $hSenseCtrl = GUICtrlGetHandle($hSenseCtrl)
    If ($nNotifyCode = 1024 Or $nNotifyCode = 6) And $hCtrl = $hSenseCtrl Then
    Local $str = ControlGetText($SenseGui, '', $SenseCtrl)
    $indexB = _GUICtrlListBox_FindString($box, $str)
    _GUICtrlListBox_SetCurSel($box, $indexB)
    $caret = _CaretPos()
    If Not @error And Not $show Then
    If $caret[3] + $caret[4] - 95 < 0 Then ; Platz für Liste über dem Ctrl ausreichend?
    WinMove($guiBox, '', $caret[0], $caret[1] +25) ; Versatz 25 (Ctrlhöhe+5) unter y vom Ctrl
    Else
    WinMove($guiBox, '', $caret[0], $caret[1] -95) ; Versatz 95 (Boxhöhe+10) über y vom Ctrl
    EndIf
    GUISetState(@SW_SHOWNOACTIVATE, $guiBox)
    $show = True
    EndIf
    ElseIf $hCtrl = $box And $nNotifyCode = 1 Then
    $indexB = _GUICtrlListBox_GetCurSel($box)
    ControlSetText($SenseGui, '', $SenseCtrl, _GUICtrlListBox_GetText($box, $indexB))
    GUISetState(@SW_HIDE, $guiBox)
    $show = False
    ElseIf $show And $nNotifyCode = 512 And $hCtrl = $lParam And Not $hCtrl = $box Then
    GUISetState(@SW_HIDE,$guiBox)
    $show = False
    EndIf
    Return $GUI_RUNDEFMSG
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func _WM_ENTERSIZEMOVE($hWnd)
    If $hWnd = $SenseGui Then $POSSenseGui = WinGetPos($SenseGui)
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func _WM_MOVE($hWnd)
    If $hWnd = $SenseGui Then
    Local $pos = WinGetPos($guiBox)
    Local $postemp = WinGetPos($SenseGui)
    WinMove($guiBox,"",$pos[0]-($POSSenseGui[0]-$postemp[0]),$pos[1]-($POSSenseGui[1]-$postemp[1]))
    $POSSenseGui = WinGetPos($SenseGui)
    EndIf
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func _CaretPos()
    Local $old = Opt("CaretCoordMode", 0) ;relative mode
    Local $c = WinGetCaretPos() ;relative caret coords
    Local $w = WinGetPos("") ;window's coords
    Local $f = ControlGetFocus("","") ;text region "handle"
    Local $e = ControlGetPos("", "", $f) ;text region coords
    Local $h = ControlGetHandle("", "", $f) ;Ctrl-Handle
    Local $t[5]
    If IsArray($c) and IsArray($w) and IsArray($e) Then
    If _WinAPI_IsClassName($SenseCtrl, 'Edit') Then ; Input wird als Edit-Class erkannt
    $t[0] = $c[0] + $w[0] + $e[0]
    ElseIf _WinAPI_IsClassName($SenseCtrl, 'ComboBox') Then
    $t[0] = $w[0] + $e[0]
    EndIf
    $t[1] = $c[1] + $w[1] + $e[1]
    $t[2] = $h
    $t[3] = $w[1]
    $t[4] = $e[1]
    Opt("CaretCoordMode", $old)
    Return $t ;absolute screen coords of caret cursor
    Else
    Opt("CaretCoordMode", $old)
    SetError(1)
    EndIf
    EndFunc
    #endregion - SenseFuncs

    [/autoit]

    DL bisher: 70

  • Hab mal eingebaut, dass die Liste beim Focus-Verlust ausgeblendet wird und man das Fenster auch verschieben kann :)
    Auch Auswahl mit Klick auf den Eintrag möglich.
    Außerdem Beide Bugs Gefixt :)

    Spoiler anzeigen
    [autoit]

    #include <GUIConstants.au3>
    #include <GUIListBox.au3>
    #include <Misc.au3>
    #include <WinApi.au3>
    Opt("GUICloseOnESC", 0)

    [/autoit] [autoit][/autoit] [autoit]

    Global $show = False
    Global $index = -1

    [/autoit] [autoit][/autoit] [autoit]

    #Region Main
    $Form1 = GUICreate('Intelli Sense Box', 400, 300, 200, 50)
    $Input = GUICtrlCreateInput('', 10, 10, 380, 21)
    $hInput = GUICtrlGetHandle($Input)
    GUISetState()
    #EndRegion Main

    [/autoit] [autoit][/autoit] [autoit]

    GUIRegisterMsg($WM_COMMAND, 'MY_WM_COMMAND')
    GUIRegisterMsg($WM_MOVE,"_WM_MOVE")
    GUIRegisterMsg(0x231,"_WM_ENTERSIZEMOVE")

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    Global $POSForm1[2]
    Func _WM_ENTERSIZEMOVE($hWnd, $Msg, $wParam, $lParam)
    If $hWnd = $Form1 Then $POSForm1 = WinGetPos($Form1)
    EndFunc
    Func _WM_MOVE($hWnd, $Msg, $wParam, $lParam)
    If $hWnd = $Form1 Then

    [/autoit] [autoit][/autoit] [autoit]

    Local $pos = WinGetPos($guiBox)
    Local $postemp = WinGetPos($Form1)
    WinMove($guiBox,"",$pos[0]-($POSForm1[0]-$postemp[0]),$pos[1]-($POSForm1[1]-$postemp[1]))
    $POSForm1 = WinGetPos($Form1)
    EndIf
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    #Region Box
    ;~ Global $PathData = @ScriptDir & '\Data.txt', $aData
    ;~ _FileReadToArray($PathData, $aData)
    ;~ If Not IsArray($aData) Then Exit

    [/autoit] [autoit][/autoit] [autoit]

    $guiBox = GUICreate('', 150, 85, 0, 0, BitOR(0,$WS_POPUP), $WS_EX_TOPMOST+$WS_EX_TOOLWINDOW)
    $box = _GUICtrlListBox_Create($guiBox, '', 0, 0, 150, 86, BitOR($LBS_SORT, 0x00B00002))
    ; ListBox muß 1 Pixel höher als GUI sein - sonst fehlerhafte Darstellung

    [/autoit] [autoit][/autoit] [autoit]

    ;~ For $i = 1 To 10 ;UBound($aData) -1
    ;~ _GUICtrlListBox_AddString($box, $aData[$i])
    ;~ Next

    [/autoit] [autoit][/autoit] [autoit]

    ;### nur zum Test von Hand gefüllt ###
    _GUICtrlListBox_AddString($box, 'Cadmium')
    _GUICtrlListBox_AddString($box, 'Arznei')
    _GUICtrlListBox_AddString($box, 'Arzt')
    _GUICtrlListBox_AddString($box, 'Bagger')
    _GUICtrlListBox_AddString($box, 'Baggereimer')
    _GUICtrlListBox_AddString($box, 'Baggergreifer')
    _GUICtrlListBox_AddString($box, 'Baggergut')
    _GUICtrlListBox_AddString($box, 'Baggerlader')
    _GUICtrlListBox_AddString($box, 'Baggerlöffel')
    _GUICtrlListBox_AddString($box, 'Baggern')
    _GUICtrlListBox_AddString($box, 'Cadillac')
    #EndRegion Box

    [/autoit] [autoit][/autoit] [autoit]

    While True
    If $show Then
    If _IsPressed('0D') Then
    GUICtrlSetData($Input, _GUICtrlListBox_GetText($box, $index))
    GUISetState(@SW_HIDE, $guiBox)
    $show = False
    ElseIf _IsPressed('1B') Then
    GUISetState(@SW_HIDE, $guiBox)
    $show = False
    ElseIf _IsPressed('26') Then
    If $index > 0 Then
    $index -= 1
    _GUICtrlListBox_SetCurSel($box, $index)
    Sleep(90)
    EndIf
    ElseIf _IsPressed('28') Then
    If $index < _GUICtrlListBox_GetCount($box)-1 Then
    $index += 1
    _GUICtrlListBox_SetCurSel($box, $index)
    Sleep(90)
    EndIf
    EndIf
    EndIf
    If GUIGetMsg() = $GUI_EVENT_CLOSE Then Exit
    WEnd

    [/autoit] [autoit][/autoit] [autoit]

    Func MY_WM_COMMAND($hWnd, $Msg, $wParam, $lParam)
    $nNotifyCode = BitShift($wParam, 16)
    $nID = BitAnd($wParam, 0x0000FFFF)
    $hCtrl = $lParam
    If $nNotifyCode = 1024 And $hCtrl = $hInput Then
    Local $str = GUICtrlRead($Input)
    $index = _GUICtrlListBox_FindString($box, $str)
    If $index = -1 Then Return
    _GUICtrlListBox_SetCurSel($box, $index)
    $caret = _CaretPos()
    If Not @error And Not $show Then
    If $caret[3] + $caret[4] - 95 < 0 Then ; Platz für Liste über dem Ctrl ausreichend?
    WinMove($guiBox, '', $caret[0], $caret[1] +25) ; Versatz 25 (Ctrlhöhe+5) unter y vom Ctrl
    Else
    WinMove($guiBox, '', $caret[0], $caret[1] -95) ; Versatz 95 (Boxhöhe+10) über y vom Ctrl
    EndIf
    GUISetState(@SW_SHOWNOACTIVATE, $guiBox)
    $show = True
    ;~ ControlClick($Form1, '', $Input)
    EndIf
    ElseIf $hCtrl = $box And $nNotifyCode = 1 Then
    $index = _GUICtrlListBox_GetCurSel($box)
    ElseIf $show And $nNotifyCode = 512 And $hCtrl = $lParam And Not $hCtrl = $box Then
    GUISetState(@SW_HIDE,$guiBox)
    $show = False
    EndIf
    ;~ ConsoleWrite($nNotifyCode & @LF)
    Return $GUI_RUNDEFMSG
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func _CaretPos()
    Opt("CaretCoordMode", 0) ;relative mode
    Local $c = WinGetCaretPos() ;relative caret coords
    Local $w = WinGetPos("") ;window's coords
    Local $f = ControlGetFocus("","") ;text region "handle"
    Local $e = ControlGetPos("", "", $f) ;text region coords
    Local $h = ControlGetHandle("", "", $f) ;Ctrl-Handle
    Local $t[5]
    If IsArray($c) and IsArray($w) and IsArray($e) Then
    $t[0] = $c[0] + $w[0] + $e[0]
    $t[1] = $c[1] + $w[1] + $e[1]
    $t[2] = $h
    $t[3] = $w[1]
    $t[4] = $e[1]
    Return $t ;absolute screen coords of caret cursor
    Else
    SetError(1)
    EndIf
    EndFunc

    [/autoit]
    • Offizieller Beitrag

    Danke progandy :)

    Für die Übernahme per Mausklick fehlt nur noch ein kleines bischen :P

    [autoit]

    ElseIf $hCtrl = $box And $nNotifyCode = 1 Then
    $index = _GUICtrlListBox_GetCurSel($box)
    GUICtrlSetData($Input, _GUICtrlListBox_GetText($box, $index))
    GUISetState(@SW_HIDE, $guiBox)
    $show = False

    [/autoit]
    • Offizieller Beitrag

    Ja, das hab ich oben in meinem Edit geschrieben ;)
    Die Ctrl-Erkennung erfolgt automatisch.
    Hier mal ein Bsp. (Code ist identisch, bis auf die Region Main also deine GUI mit Control):

    Spoiler anzeigen
    [autoit]

    #Include <WinAPI.au3>
    #include <WindowsConstants.au3>
    #Include <GuiListBox.au3>
    #include <GUIComboBox.au3>
    #include <Misc.au3>

    [/autoit] [autoit][/autoit] [autoit]

    #region - Deklarationen für Sense
    Global $show = False
    Global $indexB = -1
    Global $SenseGui, $SenseCtrl, $guiBox, $box
    Global $POSSenseGui[2]
    #Region Box
    ; Hier die Auswahldaten (braucht nicht sortiert sein):
    Global $aData = StringSplit("Ananas|Apfel|Apfelmus|Birne|Cola|Datteln|Eis|Fleisch|Gemüse|Hefe|Ingwer|Joghurt|Kaffee|Lachs|Mais|Nuss|Nutella|Obst|Pizza|Quark|Reis|Salz|Tee|U|Vanillezucker|Wasser|X|Y|Zucker", '|')
    $guiBox = GUICreate('', 150, 85, 0, 0, BitOR($WS_SIZEBOX,$WS_POPUP), $WS_EX_TOPMOST)
    $box = _GUICtrlListBox_Create($guiBox, '', 0, 0, 150, 86, BitOR($LBS_SORT, 0x00B00002))
    ; ListBox muß 1 Pixel höher als GUI sein - sonst fehlerhafte Darstellung
    For $i = 1 To UBound($aData) -1 ; falls Daten mit _FileReadToArray gelesen werden: StartIndex=1
    _GUICtrlListBox_AddString($box, $aData[$i])
    Next
    #EndRegion Box
    GUIRegisterMsg($WM_COMMAND, "MY_WM_COMMAND")
    GUIRegisterMsg($WM_MOVE, "_WM_MOVE")
    GUIRegisterMsg(0x231, "_WM_ENTERSIZEMOVE")
    #EndRegion - Deklarationen Sense

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    #Region Main
    $gui = GuiCreate("Main Gui", 300,300)
    $Combo = GuiCtrlCreateCombo("Einkaufsliste...", 35, 150, -1, -1, BitOR($CBS_DROPDOWN,$WS_VSCROLL,$WS_TABSTOP))
    $BUtton = GuiCtrlCreateButton("OK", 240,148)
    $SenseGui = $gui ; <== Für Allgemeingültigkeit Zuweisung an $SenseGui
    $SenseCtrl = $Combo ; <== Für Allgemeingültigkeit Zuweisung an $SenseCtrl
    GUISetState()
    #EndRegion Main

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    While True
    _ChooseBox()
    If GUIGetMsg() = $GUI_EVENT_CLOSE Then Exit
    WEnd

    [/autoit] [autoit][/autoit] [autoit]

    #region - SenseFunc's
    Func _ChooseBox()
    If Not $show Then Return
    If _IsPressed('0D') Then ; ENTER
    ControlSetText($SenseGui, '', $SenseCtrl, _GUICtrlListBox_GetText($box, $indexB))
    GUISetState(@SW_HIDE, $guiBox)
    $show = False
    ElseIf _IsPressed('1B') Then ; ESC
    GUISetState(@SW_HIDE, $guiBox)
    $show = False
    ElseIf _IsPressed('26') Then ; UP
    If $indexB > 0 Then
    $indexB -= 1
    _GUICtrlListBox_SetCurSel($box, $indexB)
    Sleep(90)
    EndIf
    ElseIf _IsPressed('28') Then ; DOWN
    If $indexB < _GUICtrlListBox_GetCount($box)-1 Then
    $indexB += 1
    _GUICtrlListBox_SetCurSel($box, $indexB)
    Sleep(90)
    EndIf
    EndIf
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func MY_WM_COMMAND($hWnd, $Msg, $wParam, $lParam)
    Local $nNotifyCode = BitShift($wParam, 16)
    Local $hCtrl = $lParam
    Local $hSenseCtrl = $SenseCtrl
    If Not IsHWnd($hSenseCtrl) Then $hSenseCtrl = GUICtrlGetHandle($hSenseCtrl)
    If ($nNotifyCode = 1024 Or $nNotifyCode = 6) And $hCtrl = $hSenseCtrl Then
    Local $str = ControlGetText($SenseGui, '', $SenseCtrl)
    $indexB = _GUICtrlListBox_FindString($box, $str)
    _GUICtrlListBox_SetCurSel($box, $indexB)
    $caret = _CaretPos()
    If Not @error And Not $show Then
    If $caret[3] + $caret[4] - 95 < 0 Then ; Platz für Liste über dem Ctrl ausreichend?
    WinMove($guiBox, '', $caret[0], $caret[1] +25) ; Versatz 25 (Ctrlhöhe+5) unter y vom Ctrl
    Else
    WinMove($guiBox, '', $caret[0], $caret[1] -95) ; Versatz 95 (Boxhöhe+10) über y vom Ctrl
    EndIf
    GUISetState(@SW_SHOWNOACTIVATE, $guiBox)
    $show = True
    EndIf
    ElseIf $hCtrl = $box And $nNotifyCode = 1 Then
    $indexB = _GUICtrlListBox_GetCurSel($box)
    ControlSetText($SenseGui, '', $SenseCtrl, _GUICtrlListBox_GetText($box, $indexB))
    GUISetState(@SW_HIDE, $guiBox)
    $show = False
    ElseIf $show And $nNotifyCode = 512 And $hCtrl = $lParam And Not $hCtrl = $box Then
    GUISetState(@SW_HIDE,$guiBox)
    $show = False
    EndIf
    Return $GUI_RUNDEFMSG
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func _WM_ENTERSIZEMOVE($hWnd)
    If $hWnd = $SenseGui Then $POSSenseGui = WinGetPos($SenseGui)
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func _WM_MOVE($hWnd)
    If $hWnd = $SenseGui Then
    Local $pos = WinGetPos($guiBox)
    Local $postemp = WinGetPos($SenseGui)
    WinMove($guiBox,"",$pos[0]-($POSSenseGui[0]-$postemp[0]),$pos[1]-($POSSenseGui[1]-$postemp[1]))
    $POSSenseGui = WinGetPos($SenseGui)
    EndIf
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func _CaretPos()
    Local $old = Opt("CaretCoordMode", 0) ;relative mode
    Local $c = WinGetCaretPos() ;relative caret coords
    Local $w = WinGetPos("") ;window's coords
    Local $f = ControlGetFocus("","") ;text region "handle"
    Local $e = ControlGetPos("", "", $f) ;text region coords
    Local $h = ControlGetHandle("", "", $f) ;Ctrl-Handle
    Local $t[5]
    If IsArray($c) and IsArray($w) and IsArray($e) Then
    If _WinAPI_IsClassName($SenseCtrl, 'Edit') Then ; Input wird als Edit-Class erkannt
    $t[0] = $c[0] + $w[0] + $e[0]
    ElseIf _WinAPI_IsClassName($SenseCtrl, 'ComboBox') Then
    $t[0] = $w[0] + $e[0]
    EndIf
    $t[1] = $c[1] + $w[1] + $e[1]
    $t[2] = $h
    $t[3] = $w[1]
    $t[4] = $e[1]
    Opt("CaretCoordMode", $old)
    Return $t ;absolute screen coords of caret cursor
    Else
    Opt("CaretCoordMode", $old)
    SetError(1)
    EndIf
    EndFunc
    #endregion - SenseFunc's

    [/autoit]
  • Vielen Dank an BugFix & CoCoder, genau das habe ich lange gesucht!!

    Ich wuerde gerne das Script anpassen und in mein Projekt uebernehmen. Allerdings mit folgenen 2 Modifikationen:

    1. Die dargestellten Treffer in der ListBox sollten waehrend der Eingabe eingeschraenkt werden, d.h. nur die Treffer anzeigen, die aufgrund der bisherigen Eingabe noch relevant sind.
    2. Die ListBox sollte bei Bedarf auch entsprechend der Anzahl der Treffer in der Hoehe dynamisch angepasst werden.

    Kann mir bitte jemand einen Tipp geben, wo ich im Code drehen muss, um diesen Effekt zu erreichen?

    Vielen Dank im voraus.
    - George

    • Offizieller Beitrag

    Hallo

    Wo wir schon dabei sind. Ich mag die Umsetzung mit IsPressed überhaupt nicht. Hier mal eine Version mit OnEvent + AcceleratorKeys:

    Spoiler anzeigen
    [autoit]

    #include<GUIConstantsEx.au3>
    #include<ListBoxConstants.au3>
    #include <WindowsConstants.au3>
    #include <GUIListBox.au3>
    #include <WinAPI.au3>
    #include <Misc.au3>
    Opt("GUICloseOnESC", 0)
    Opt("GuiOnEventMode", 1)

    [/autoit] [autoit][/autoit] [autoit]

    #Region - Deklarationen für Sense
    Global $show = False
    Global $indexB = -1
    Global $SenseGui, $SenseCtrl, $guiBox, $box
    Global $POSSenseGui[2]
    #Region Box
    ; Hier die Auswahldaten (braucht nicht sortiert sein):
    Global $aData[10] = ['Birne', 'Alligator', 'Auto', 'Dank', 'Automat', 'Bett', 'Garten', 'Bettler', 'Danke', 'Danksagung']
    $guiBox = GUICreate('', 150, 85, 0, 0, $WS_POPUP, $WS_EX_TOPMOST + $WS_EX_TOOLWINDOW)
    $box = _GUICtrlListBox_Create($guiBox, '', 0, 0, 150, 86, BitOR($LBS_SORT, 0x00B00002), 0)
    ; ListBox muß 1 Pixel höher als GUI sein - sonst fehlerhafte Darstellung
    For $i = 0 To UBound($aData) - 1 ; falls Daten mit _FileReadToArray gelesen werden: StartIndex=1
    _GUICtrlListBox_AddString($box, $aData[$i])
    Next
    WinSetTrans($guiBox, "", 200)

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    #EndRegion Box
    GUIRegisterMsg($WM_COMMAND, "MY_WM_COMMAND")
    GUIRegisterMsg($WM_MOVE, "_WM_MOVE")
    GUIRegisterMsg(0x231, "_WM_ENTERSIZEMOVE")
    #EndRegion - Deklarationen für Sense

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    #Region Main
    $Form1 = GUICreate('Intelli Sense Box', 400, 300, 200, 50)
    GUISetOnEvent(-3, "_Exit")
    $SenseGui = $Form1 ; <== Für Allgemeingültigkeit Zuweisung an $SenseGui
    $Input = GUICtrlCreateInput('', 10, 10, 380, 21)
    $SenseCtrl = $Input ; <== Für Allgemeingültigkeit Zuweisung an $SenseCtrl
    $hInput = GUICtrlGetHandle($Input)
    GUICtrlCreateButton("Bla", 10, 35, 80, 20)
    GUISetState()
    #EndRegion Main
    Local $Dumm[5]
    $Dumm[0] = GUICtrlCreateDummy()
    For $i = 1 To 4
    $Dumm[$i] = GUICtrlCreateDummy()
    GUICtrlSetOnEvent(-1, "_Dummy")
    Next

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    Dim $AccelKeys[4][2] = [["{ENTER}", $Dumm[1]],["{ESC}", $Dumm[2]],["{UP}", $Dumm[3]],["{DOWN}", $Dumm[4]]]
    GUISetAccelerators($AccelKeys)

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    While True
    Sleep(500)
    WEnd

    [/autoit] [autoit][/autoit] [autoit]

    Func _Dummy()
    If Not $show Then Return
    Switch @GUI_CtrlId - $Dumm[0]
    Case 1;ENTER
    ControlSetText($SenseGui, '', $SenseCtrl, _GUICtrlListBox_GetText($box, $indexB))
    GUISetState(@SW_HIDE, $guiBox)
    $show = False
    Case 2 ;ESC
    GUISetState(@SW_HIDE, $guiBox)
    $show = False
    Case 3 ;UP
    If $indexB > 0 Then
    $indexB -= 1
    _GUICtrlListBox_SetCurSel($box, $indexB)
    Sleep(90)
    EndIf
    Case 4;DOWN
    If $indexB < _GUICtrlListBox_GetCount($box) - 1 Then
    $indexB += 1
    _GUICtrlListBox_SetCurSel($box, $indexB)
    Sleep(90)
    EndIf
    EndSwitch

    [/autoit] [autoit][/autoit] [autoit]

    EndFunc ;==>_Dummy

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    Func _Exit()
    Exit
    EndFunc ;==>_Exit

    [/autoit] [autoit][/autoit] [autoit]

    Func MY_WM_COMMAND($hWnd, $Msg, $wParam, $lParam)
    Local $nNotifyCode = BitShift($wParam, 16)
    Local $hCtrl = $lParam
    Local $hSenseCtrl = $SenseCtrl
    If Not IsHWnd($hSenseCtrl) Then $hSenseCtrl = GUICtrlGetHandle($hSenseCtrl)
    If ($nNotifyCode = 1024 Or $nNotifyCode = 6) And $hCtrl = $hSenseCtrl Then
    Local $str = ControlGetText($SenseGui, '', $SenseCtrl)
    $indexB = _GUICtrlListBox_FindString($box, $str)
    _GUICtrlListBox_SetCurSel($box, $indexB)
    $caret = _CaretPos()
    If Not @error And Not $show Then
    If $caret[3] + $caret[4] - 95 < 0 Then ; Platz für Liste über dem Ctrl ausreichend?
    WinMove($guiBox, '', $caret[0], $caret[1] + 25) ; Versatz 25 (Ctrlhöhe+5) unter y vom Ctrl
    Else
    WinMove($guiBox, '', $caret[0], $caret[1] - 95) ; Versatz 95 (Boxhöhe+10) über y vom Ctrl
    EndIf
    GUISetState(@SW_SHOWNOACTIVATE, $guiBox)
    $show = True
    EndIf
    ElseIf $hCtrl = $box And $nNotifyCode = 1 Then
    $indexB = _GUICtrlListBox_GetCurSel($box)
    ControlSetText($SenseGui, '', $SenseCtrl, _GUICtrlListBox_GetText($box, $indexB))
    GUISetState(@SW_HIDE, $guiBox)
    $show = False
    ElseIf $show And $nNotifyCode = 512 And $hCtrl = $lParam And Not $hCtrl = $box Then
    GUISetState(@SW_HIDE, $guiBox)
    $show = False
    EndIf
    Return $GUI_RUNDEFMSG
    EndFunc ;==>MY_WM_COMMAND

    [/autoit] [autoit][/autoit] [autoit]

    Func _WM_ENTERSIZEMOVE($hWnd)
    If $hWnd = $SenseGui Then $POSSenseGui = WinGetPos($SenseGui)
    EndFunc ;==>_WM_ENTERSIZEMOVE

    [/autoit] [autoit][/autoit] [autoit]

    Func _WM_MOVE($hWnd)
    If $hWnd = $SenseGui Then
    Local $pos = WinGetPos($guiBox)
    Local $postemp = WinGetPos($SenseGui)
    WinMove($guiBox, "", $pos[0] - ($POSSenseGui[0] - $postemp[0]), $pos[1] - ($POSSenseGui[1] - $postemp[1]))
    $POSSenseGui = WinGetPos($SenseGui)
    EndIf
    EndFunc ;==>_WM_MOVE

    [/autoit] [autoit][/autoit] [autoit]

    Func _CaretPos()
    Local $old = Opt("CaretCoordMode", 0) ;relative mode
    Local $c = WinGetCaretPos() ;relative caret coords
    Local $w = WinGetPos("") ;window's coords
    Local $f = ControlGetFocus("", "") ;text region "handle"
    Local $e = ControlGetPos("", "", $f) ;text region coords
    Local $h = ControlGetHandle("", "", $f) ;Ctrl-Handle
    Local $t[5]
    If IsArray($c) And IsArray($w) And IsArray($e) Then
    If _WinAPI_IsClassName($SenseCtrl, 'Edit') Then ; Input wird als Edit-Class erkannt
    $t[0] = $c[0] + $w[0] + $e[0]
    ElseIf _WinAPI_IsClassName($SenseCtrl, 'ComboBox') Then
    $t[0] = $w[0] + $e[0]
    EndIf
    $t[1] = $c[1] + $w[1] + $e[1]
    $t[2] = $h
    $t[3] = $w[1]
    $t[4] = $e[1]
    Opt("CaretCoordMode", $old)
    Return $t ;absolute screen coords of caret cursor
    Else
    Opt("CaretCoordMode", $old)
    SetError(1)
    EndIf
    EndFunc ;==>_CaretPos
    #EndRegion - SenseFunc's

    [/autoit]

    Gruß
    Spider

  • Wirklich gut gemacht.

    Drei kleine Fehler hab ich trotzdem entdeckt:

    1. Wenn man nichts markiert hat, und trotzdem Enter drückt, wird 0 in das Input geschrieben.
    2. Das Fenster, welches du erstellst, wird in der Taskleiste angezeigt.
    3. Wenn man etwas in die Box reinschreibt, dies dann aber wieder löscht, ist die Box trotzdem noch da.

    Sind zwar nicht wirklich Fehler, hab sie trotzdem behoben. Ich hoffe, du bist mir nicht böse. ;)

    Spoiler anzeigen
    [autoit]

    #include<GUIConstantsEx.au3>
    #include<ListBoxConstants.au3>
    #include <WindowsConstants.au3>
    #include <GUIListBox.au3>
    #Include <WinAPI.au3>
    #include <Misc.au3>
    Opt("GUICloseOnESC", 0)

    [/autoit] [autoit][/autoit] [autoit]

    #region - Deklarationen für Sense
    Global $show = False
    Global $indexB = -1
    Global $SenseGui, $SenseCtrl, $guiBox, $box
    Global $POSSenseGui[2]
    #Region Box
    ; Hier die Auswahldaten (braucht nicht sortiert sein):
    Global $aData[10] = ['Birne','Alligator','Auto','Dank','Automat','Bett','Garten','Bettler','Danke','Danksagung']
    $guiBox = GUICreate('', 150, 85, 0, 0, BitOR($WS_SIZEBOX, $WS_POPUP), BitOR($WS_EX_TOPMOST, $WS_EX_TOOLWINDOW))
    $box = _GUICtrlListBox_Create($guiBox, '', 0, 0, 150, 86, BitOR($LBS_SORT, 0x00B00002))
    ; ListBox muß 1 Pixel höher als GUI sein - sonst fehlerhafte Darstellung
    For $i = 0 To UBound($aData) -1 ; falls Daten mit _FileReadToArray gelesen werden: StartIndex=1
    _GUICtrlListBox_AddString($box, $aData[$i])
    Next
    #EndRegion Box
    GUIRegisterMsg($WM_COMMAND, "MY_WM_COMMAND")
    GUIRegisterMsg($WM_MOVE, "_WM_MOVE")
    GUIRegisterMsg(0x231, "_WM_ENTERSIZEMOVE")
    #EndRegion - Deklarationen Sense

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    #Region Main
    $Form1 = GUICreate('Intelli Sense Box', 400, 300, 200, 50)
    $SenseGui = $Form1 ; <== Für Allgemeingültigkeit Zuweisung an $SenseGui
    $Input = GUICtrlCreateInput('', 10, 10, 380, 21)
    $SenseCtrl = $Input ; <== Für Allgemeingültigkeit Zuweisung an $SenseCtrl
    $hInput = GUICtrlGetHandle($Input)
    GUISetState()
    #EndRegion Main

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    While True
    _ChooseBox()
    If GUIGetMsg() = $GUI_EVENT_CLOSE Then Exit
    WEnd

    [/autoit] [autoit][/autoit] [autoit]

    #region - SenseFuncs
    Func _ChooseBox()
    If Not $show Or ControlGetText($SenseGui, '', $SenseCtrl) = "" Then
    GUISetState(@SW_HIDE, $guiBox)
    $show = False
    Return
    EndIf
    If _IsPressed('0D') Then ; ENTER
    If _GUICtrlListBox_GetText($box, $indexB) <> 0 Then
    ControlSetText($SenseGui, '', $SenseCtrl, _GUICtrlListBox_GetText($box, $indexB))
    EndIf
    GUISetState(@SW_HIDE, $guiBox)
    $show = False
    ElseIf _IsPressed('1B') Then ; ESC
    GUISetState(@SW_HIDE, $guiBox)
    $show = False
    ElseIf _IsPressed('26') Then ; UP
    If $indexB > 0 Then
    $indexB -= 1
    _GUICtrlListBox_SetCurSel($box, $indexB)
    Sleep(90)
    EndIf
    ElseIf _IsPressed('28') Then ; DOWN
    If $indexB < _GUICtrlListBox_GetCount($box)-1 Then
    $indexB += 1
    _GUICtrlListBox_SetCurSel($box, $indexB)
    Sleep(90)
    EndIf
    EndIf
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func MY_WM_COMMAND($hWnd, $Msg, $wParam, $lParam)
    Local $nNotifyCode = BitShift($wParam, 16)
    Local $hCtrl = $lParam
    Local $hSenseCtrl = $SenseCtrl
    If Not IsHWnd($hSenseCtrl) Then $hSenseCtrl = GUICtrlGetHandle($hSenseCtrl)
    If ($nNotifyCode = 1024 Or $nNotifyCode = 6) And $hCtrl = $hSenseCtrl Then
    Local $str = ControlGetText($SenseGui, '', $SenseCtrl)
    $indexB = _GUICtrlListBox_FindString($box, $str)
    _GUICtrlListBox_SetCurSel($box, $indexB)
    $caret = _CaretPos()
    If Not @error And Not $show Then
    If $caret[3] + $caret[4] - 95 < 0 Then ; Platz für Liste über dem Ctrl ausreichend?
    WinMove($guiBox, '', $caret[0], $caret[1] +25) ; Versatz 25 (Ctrlhöhe+5) unter y vom Ctrl
    Else
    WinMove($guiBox, '', $caret[0], $caret[1] -95) ; Versatz 95 (Boxhöhe+10) über y vom Ctrl
    EndIf
    GUISetState(@SW_SHOWNOACTIVATE, $guiBox)
    $show = True
    EndIf
    ElseIf $hCtrl = $box And $nNotifyCode = 1 Then
    $indexB = _GUICtrlListBox_GetCurSel($box)
    ControlSetText($SenseGui, '', $SenseCtrl, _GUICtrlListBox_GetText($box, $indexB))
    GUISetState(@SW_HIDE, $guiBox)
    $show = False
    ElseIf $show And $nNotifyCode = 512 And $hCtrl = $lParam And Not $hCtrl = $box Then
    GUISetState(@SW_HIDE,$guiBox)
    $show = False
    EndIf
    Return $GUI_RUNDEFMSG
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func _WM_ENTERSIZEMOVE($hWnd)
    If $hWnd = $SenseGui Then $POSSenseGui = WinGetPos($SenseGui)
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func _WM_MOVE($hWnd)
    If $hWnd = $SenseGui Then
    Local $pos = WinGetPos($guiBox)
    Local $postemp = WinGetPos($SenseGui)
    WinMove($guiBox,"",$pos[0]-($POSSenseGui[0]-$postemp[0]),$pos[1]-($POSSenseGui[1]-$postemp[1]))
    $POSSenseGui = WinGetPos($SenseGui)
    EndIf
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func _CaretPos()
    Local $old = Opt("CaretCoordMode", 0) ;relative mode
    Local $c = WinGetCaretPos() ;relative caret coords
    Local $w = WinGetPos("") ;window's coords
    Local $f = ControlGetFocus("","") ;text region "handle"
    Local $e = ControlGetPos("", "", $f) ;text region coords
    Local $h = ControlGetHandle("", "", $f) ;Ctrl-Handle
    Local $t[5]
    If IsArray($c) and IsArray($w) and IsArray($e) Then
    If _WinAPI_IsClassName($SenseCtrl, 'Edit') Then ; Input wird als Edit-Class erkannt
    $t[0] = $c[0] + $w[0] + $e[0]
    ElseIf _WinAPI_IsClassName($SenseCtrl, 'ComboBox') Then
    $t[0] = $w[0] + $e[0]
    EndIf
    $t[1] = $c[1] + $w[1] + $e[1]
    $t[2] = $h
    $t[3] = $w[1]
    $t[4] = $e[1]
    Opt("CaretCoordMode", $old)
    Return $t ;absolute screen coords of caret cursor
    Else
    Opt("CaretCoordMode", $old)
    SetError(1)
    EndIf
    EndFunc
    #endregion - SenseFuncs

    [/autoit]
    Zitat

    [Heute, 11:39] Raupi: Soll ich es dir machen?
    [Heute, 11:47] BugFix: "Soll ich es dir machen? " - also Raupi !! bitte nicht so öffentlich :rofl:

    Zitat

    [Heute, 11:51] BugFix: und ich werde es mir jetzt machen - das Mittagessen :P

    AMsg UDF v1.00.00 IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII 100%
    OwnStyle UDF Version 1.10.00 IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII 100%

  • funktioniert genial!

    Eine SQL Tabelle mit 1500 Einträgen als Quelle für die Listbox und läuft Super.

    Wo ich lange gestolpert bin, einige Werte meines eingelesenes array´s hatten zusätzlich ein @lf hinter dem wert. Dann funktioniert die intellisensebox nicht! Falls jemand mal so ein Problem haben sollte...

    vielen Dank Bugfix für dieses Script!

    ---
    In "Independence Day" konnten die Windows-Erdcomputer problemlos mit denen der Außerirdischen kommunizieren. Was sagt uns das über unseren lieben Bill Gates? :D
    ---

  • Hallo @BugFix und natürlich alle anderen :)

    ich suchte die Möglichkeit Auswahlfenster für eine GUI zu erstellen. Auch wenn der Thread schon alt ist, scheint mir das Skript das beste (passendste) für mich zu sein unter den Alternativen, die ich gefunden habe. In einer GUI habe ich mehrere Inputboxen wunderbar mit Auswahllisten ausstatten können. Das klappt ganz toll! Vielen Dank dafür.

    Nun wollte ich versuchen, Auswahllisten in einer anderen GUI zu platzieren. Allerdings stoße ich hier an Verständnis-Probleme und wäre für Hilfe sehr dankbar.

    - ich habe hiermit die Möglichkeit eigene Auswahllisten auch für Fremdanwendungen (so sie denn Standard Windows Controls verwenden) zu nutzen


    Wenn ich im vorliegenden Skript die Region Main herausnehme, die GUI in einem zweiten Skript laufen lasse und hier die Handles von Fenster und Controls als $SenseGui und $SenseCtrl nutze, erscheint das Auswahlfenster nicht.

    Spoiler anzeigen


    Bei genauerer Betrachtung scheint das auch klar zu sein, weil das Fenster in der MY_WM_COMMAND-Funktion angezeigt wird. Wie kann ich da überhaupt die Events von fremden GUIs empfangen? Wie ist das vielleicht sonst gedacht?

    Grüße autoiter