Nochmal WM_Command - Enter Taste beim Input-Control

  • Hey,

    folgendes Problem:
    Bei einer Erfassungsmaske (hauptsächlich für Zahlen) soll man immer mit der Enter-Taste (bzw. Num-Enter) zum nächsten Feld springen können.
    Das funktioniert auch grudnsätzlich:

    Spoiler anzeigen
    [autoit]


    #include <WindowsConstants.au3>
    #include <GUIConstantsEx.au3>
    #include <StaticConstants.au3>
    #include <EditConstants.au3>
    #include <StructureConstants.au3>
    #include <WinAPI.au3>

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

    Global $eventCount = 0
    $sHeader = "Input1|Input2|Input3"
    Global $hGui = GUICreate("", 400, 400, -1, -1)
    Global $aHeader = StringSplit($sHeader, '|') ; Überschriften-Array
    Global $aNew[$aHeader[0]] ; Array für die Input-IDs
    Global $aInputWidth[$aHeader[0]] = [100, 100, 100] ; hier die Länge (in Pixel) der Inputfelder eintragen
    Global $xPos = 20
    For $i = 1 To $aHeader[0]
    GUICtrlCreateLabel($aHeader[$i], $xPos + 2,200, 110, 20) ; Überschriften-Label erstellen
    GUICtrlSetFont(-1, 8, 400, 0, 'Verdana') ; Schriftgröße und -art der Überschriften festlegen
    $aNew[$i - 1] = GUICtrlCreateInput("", $xPos, 220, $aInputWidth[$i - 1], 20,Default, $WS_EX_STATICEDGE) ; Eingabefelder erstellen
    GUICtrlSetFont(-1, 10, 600, 0, 'Verdana') ; Schriftgröße und -art der Eingabefelder festlegen
    $xPos += $aInputWidth[$i - 1] + 5
    Next

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

    GUISetState(@SW_SHOW, $hGui)
    GUIRegisterMsg($WM_Command ,"WM_COMMAND")

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

    While 1
    $nMsg = GUIGetMsg(1) ; Message-Event holen (1) = erweiterter Modus

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

    Switch $nMsg[0] ; anhand der Control-ID das entsprechende Case aufrufen
    case $anew[0]
    GUICtrlSetState($aNew[1], $GUI_FOCUS)
    #Region Schließen
    Case $GUI_EVENT_CLOSE ; User hat auf das Schließen-Symbol geklickt (bzw. die ESC-Taste gedrückt)
    Switch $nMsg[1] ; erweiterte Abfrage für welches Fenster
    Case $hGui ; User will das Hauptfenster schließen
    exit

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

    EndSwitch

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

    #EndRegion Schließen
    EndSwitch

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

    WEnd

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

    Func WM_COMMAND($hWnd, $iMsg, $iwParam, $ilParam)
    Local $hwndFrom, $iIDFrom, $iCode
    $iIDFrom = BitAND($iwParam, 0xFFFF) ; Low Word
    $iCode = BitShift($iwParam, 16) ; Hi Word
    Switch $iIDFrom
    case $anew[0]
    switch $iCode
    case 0
    GUICtrlSetState($aNew[1], $GUI_FOCUS)
    EndSwitch
    case $anew[1]
    switch $icode
    case 0
    GUICtrlSetState($aNew[2], $GUI_FOCUS)
    EndSwitch
    case $anew[2]
    switch $iCode
    case 0
    GUICtrlSetState($aNew[0], $GUI_FOCUS)
    EndSwitch

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

    EndSwitch
    Return $GUI_RUNDEFMSG
    EndFunc ;==>WM_COMMAND

    [/autoit]


    Allerdings gibt es in meinem Fall auch einige Felder, die nicht jedes mal befüllt/geändert werden müssen.
    WM_Command reagiert aber leider nur nachdem im Input etwas erfasst wurde :(
    Gibts einen Trick das zu umgehen?

    Gruß nuts

    Einmal editiert, zuletzt von nuts (2. Oktober 2009 um 12:31)

  • so ggf....

    Spoiler anzeigen
    [autoit]

    #include <ButtonConstants.au3>
    #include <WindowsConstants.au3>
    #include <GUIConstantsEx.au3>

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

    Global $eventCount = 0
    $sHeader = "Input1|Input2|Input3"
    Global $hGui = GUICreate("", 400, 400, -1, -1)
    Global $aHeader = StringSplit($sHeader, '|') ; Überschriften-Array
    Global $aNew[$aHeader[0]] ; Array für die Input-IDs
    Global $aInputWidth[$aHeader[0]] = [100, 100, 100] ; hier die Länge (in Pixel) der Inputfelder eintragen
    Global $xPos = 20
    For $i = 1 To $aHeader[0]
    GUICtrlCreateLabel($aHeader[$i], $xPos + 2,200, 110, 20) ; Überschriften-Label erstellen
    GUICtrlSetFont(-1, 8, 400, 0, 'Verdana') ; Schriftgröße und -art der Überschriften festlegen
    $aNew[$i - 1] = GUICtrlCreateInput("", $xPos, 220, $aInputWidth[$i - 1], 20,Default, $WS_EX_STATICEDGE) ; Eingabefelder erstellen
    GUICtrlSetFont(-1, 10, 600, 0, 'Verdana') ; Schriftgröße und -art der Eingabefelder festlegen
    $xPos += $aInputWidth[$i - 1] + 5
    Next

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

    $btn_virtuell=GUICtrlCreateButton("test",10,10,10,10,$BS_DEFPUSHBUTTON) ;button erstellen

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

    GUISetState(@SW_SHOW, $hGui)
    GUIRegisterMsg($WM_Command ,"WM_COMMAND")
    GUIctrlSetState($btn_virtuell,$GUI_hide ) ;button unsichtbar machen

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

    While 1
    $nMsg = GUIGetMsg(1) ; Message-Event holen (1) = erweiterter Modus
    Switch $nMsg[0] ; anhand der Control-ID das entsprechende Case aufrufen
    case $btn_virtuell
    Tooltip("Enter gedrückt")
    sleep(1000)
    Tooltip("")

    case $anew[0]
    GUICtrlSetState($aNew[1], $GUI_FOCUS)
    #Region Schließen
    Case $GUI_EVENT_CLOSE ; User hat auf das Schließen-Symbol geklickt (bzw. die ESC-Taste gedrückt)
    Switch $nMsg[1] ; erweiterte Abfrage für welches Fenster
    Case $hGui ; User will das Hauptfenster schließen
    exit

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

    EndSwitch

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

    #EndRegion Schließen
    EndSwitch

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

    WEnd

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

    Func WM_COMMAND($hWnd, $iMsg, $iwParam, $ilParam)
    Local $hwndFrom, $iIDFrom, $iCode
    $iIDFrom = BitAND($iwParam, 0xFFFF) ; Low Word
    $iCode = BitShift($iwParam, 16) ; Hi Word
    Switch $iIDFrom
    case $anew[0]
    switch $iCode
    case 0
    GUICtrlSetState($aNew[1], $GUI_FOCUS)
    EndSwitch
    case $anew[1]
    switch $icode
    case 0
    GUICtrlSetState($aNew[2], $GUI_FOCUS)
    EndSwitch
    case $anew[2]
    switch $iCode
    case 0
    GUICtrlSetState($aNew[0], $GUI_FOCUS)
    EndSwitch

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

    EndSwitch
    Return $GUI_RUNDEFMSG
    EndFunc ;==>WM_COMMAN

    [/autoit]
  • Ah das hätte ich dazuschreiben müssen, sorry.
    Hotkeyset, _Ispressed und $BS_DEFPUSHBUTTON kenne ich schon :)

    Bei $BS_DEFPUSHBUTTON gibt teilweise Problem, wenn ein anderer Button den Fokus hat.
    Schaus mir aber nochmal an, bei einer Erfassungsmaske kann man damit vielleicht leben.

    • Offizieller Beitrag

    Hmm...vielleicht so:

    Spoiler anzeigen
    [autoit]


    #include <WindowsConstants.au3>
    #include <GUIConstantsEx.au3>
    #include <StaticConstants.au3>
    #include <EditConstants.au3>
    #include <StructureConstants.au3>
    #include <WinAPI.au3>

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

    Global $eventCount = 0
    $sHeader = "Input1|Input2|Input3"
    Global $hGui = GUICreate("", 400, 400, -1, -1)
    Global $hButton = GUICtrlCreateButton('Test', 10, 10, 100, 20)
    Global $aHeader = StringSplit($sHeader, '|') ; Überschriften-Array
    Global $aNew[$aHeader[0]] ; Array für die Input-IDs
    Global $aInputWidth[$aHeader[0]] = [100, 100, 100] ; hier die Länge (in Pixel) der Inputfelder eintragen
    Global $xPos = 20
    For $i = 1 To $aHeader[0]
    GUICtrlCreateLabel($aHeader[$i], $xPos + 2, 200, 110, 20) ; Überschriften-Label erstellen
    GUICtrlSetFont(-1, 8, 400, 0, 'Verdana') ; Schriftgröße und -art der Überschriften festlegen
    $aNew[$i - 1] = GUICtrlCreateInput("", $xPos, 220, $aInputWidth[$i - 1], 20, Default, $WS_EX_STATICEDGE) ; Eingabefelder erstellen
    GUICtrlSetFont(-1, 10, 600, 0, 'Verdana') ; Schriftgröße und -art der Eingabefelder festlegen
    $xPos += $aInputWidth[$i - 1] + 5
    Next

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

    GUISetState(@SW_SHOW, $hGui)
    GUIRegisterMsg($WM_Command, "WM_COMMAND")

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

    While 1
    $nMsg = GUIGetMsg(1) ; Message-Event holen (1) = erweiterter Modus

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

    Switch $nMsg[0] ; anhand der Control-ID das entsprechende Case aufrufen
    Case $aNew[0]
    GUICtrlSetState($aNew[1], $GUI_FOCUS)
    #Region Schließen
    Case $GUI_EVENT_CLOSE ; User hat auf das Schließen-Symbol geklickt (bzw. die ESC-Taste gedrückt)
    Switch $nMsg[1] ; erweiterte Abfrage für welches Fenster
    Case $hGui ; User will das Hauptfenster schließen
    Exit

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

    EndSwitch

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

    #EndRegion Schließen
    EndSwitch

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

    WEnd

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

    Func WM_COMMAND($hWnd, $iMsg, $iwParam, $ilParam)
    Local $hwndFrom, $iIDFrom, $iCode
    $iIDFrom = BitAND($iwParam, 0xFFFF) ; Low Word
    $iCode = BitShift($iwParam, 16) ; Hi Word
    If $iCode = 0 Then
    Send('{TAB}')
    If ControlGetFocus($hGui) = 'Edit3' Then Send('{TAB}')
    Return 1
    EndIf
    ;~ Switch $iIDFrom
    ;~ case $anew[0]
    ;~ switch $iCode
    ;~ case 0
    ;~ GUICtrlSetState($aNew[1], $GUI_FOCUS)
    ;~ EndSwitch
    ;~ case $anew[1]
    ;~ switch $icode
    ;~ case 0
    ;~ GUICtrlSetState($aNew[2], $GUI_FOCUS)
    ;~ EndSwitch
    ;~ case $anew[2]
    ;~ switch $iCode
    ;~ case 0
    ;~ GUICtrlSetState($aNew[0], $GUI_FOCUS)
    ;~ EndSwitch

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

    ;~ EndSwitch
    Return $GUI_RUNDEFMSG
    EndFunc ;==>WM_COMMAND

    [/autoit]


    Hab jetzt noch einen Button hinzugefügt, um Dir zu zeigen, wie man den Focus auch dann noch wieder auf das erste Input bekommt.

  • Spoiler anzeigen
    [autoit]


    #include <WindowsConstants.au3>
    #include <GUIConstantsEx.au3>
    #include <StaticConstants.au3>
    #include <EditConstants.au3>
    #include <StructureConstants.au3>
    #include <WinAPI.au3>

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

    Global $eventCount = 0
    $sHeader = "Input1|Input2|Input3"
    Global $hGui = GUICreate("", 400, 400, -1, -1)
    Global $hButton = GUICtrlCreateButton('Test', 10, 10, 100, 20)
    Global $aHeader = StringSplit($sHeader, '|') ; Überschriften-Array
    Global $aNew[$aHeader[0]] ; Array für die Input-IDs
    Global $aInputWidth[$aHeader[0]] = [100, 100, 100] ; hier die Länge (in Pixel) der Inputfelder eintragen
    Global $xPos = 20
    For $i = 1 To $aHeader[0]
    GUICtrlCreateLabel($aHeader[$i], $xPos + 2, 200, 110, 20) ; Überschriften-Label erstellen
    GUICtrlSetFont(-1, 8, 400, 0, 'Verdana') ; Schriftgröße und -art der Überschriften festlegen
    $aNew[$i - 1] = GUICtrlCreateInput("", $xPos, 220, $aInputWidth[$i - 1], 20, Default, $WS_EX_STATICEDGE) ; Eingabefelder erstellen
    GUICtrlSetFont(-1, 10, 600, 0, 'Verdana') ; Schriftgröße und -art der Eingabefelder festlegen
    $xPos += $aInputWidth[$i - 1] + 5
    Next

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

    GUISetState(@SW_SHOW, $hGui)
    GUIRegisterMsg($WM_Command, "WM_COMMAND")

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

    While 1
    $nMsg = GUIGetMsg(1) ; Message-Event holen (1) = erweiterter Modus

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

    Switch $nMsg[0] ; anhand der Control-ID das entsprechende Case aufrufen
    Case $aNew[0]
    GUICtrlSetState($aNew[1], $GUI_FOCUS)
    #Region Schließen
    Case $GUI_EVENT_CLOSE ; User hat auf das Schließen-Symbol geklickt (bzw. die ESC-Taste gedrückt)
    Switch $nMsg[1] ; erweiterte Abfrage für welches Fenster
    Case $hGui ; User will das Hauptfenster schließen
    Exit

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

    EndSwitch

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

    #EndRegion Schließen
    EndSwitch

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

    WEnd

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

    Func WM_COMMAND($hWnd, $iMsg, $iwParam, $ilParam)
    Local $hwndFrom, $iIDFrom, $iCode
    $iIDFrom = BitAND($iwParam, 0xFFFF) ; Low Word
    $iCode = BitShift($iwParam, 16) ; Hi Word
    If $iCode = 0 Then
    Send('{TAB}')
    If ControlGetFocus($hGui) = 'Edit3' Then Send('{TAB}')
    MsgBox(1, "", "Enter")
    Return 1
    EndIf
    ;~ Switch $iIDFrom
    ;~ case $anew[0]
    ;~ switch $iCode
    ;~ case 0
    ;~ GUICtrlSetState($aNew[1], $GUI_FOCUS)
    ;~ EndSwitch
    ;~ case $anew[1]
    ;~ switch $icode
    ;~ case 0
    ;~ GUICtrlSetState($aNew[2], $GUI_FOCUS)
    ;~ EndSwitch
    ;~ case $anew[2]
    ;~ switch $iCode
    ;~ case 0
    ;~ GUICtrlSetState($aNew[0], $GUI_FOCUS)
    ;~ EndSwitch

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

    ;~ EndSwitch
    Return $GUI_RUNDEFMSG
    EndFunc ;==>WM_COMMAND

    [/autoit]


    Hab mal eine msgbox eingefügt um das Problem damit zu verdeutlichen.

    Über den Fokus müsste sich aber wirklich was machen lassen.
    In WM_Command den Fokus bestimmten und in Abjängigkeit vom Fokus reagieren.

    Die zweite Möglichkeit: Man findet heraus was die Inputfelder für eine Nachricht erhalten nachdem etwas eingegeben wurde und schickt dieses Nachricht via GUICtrlSendMsg hinterher.
    Irgendwie krieg ichs aber nicht raus. :(

    edit \

    Spoiler anzeigen
    [autoit]


    #include <WindowsConstants.au3>
    #include <GUIConstantsEx.au3>
    #include <StaticConstants.au3>
    #include <EditConstants.au3>
    #include <StructureConstants.au3>
    #include <WinAPI.au3>

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

    Global $eventCount = 0
    $sHeader = "Input1|Input2|Input3"
    Global $hGui = GUICreate("", 400, 400, -1, -1)
    Global $aHeader = StringSplit($sHeader, '|') ; Überschriften-Array
    Global $aNew[$aHeader[0]]
    Global $haNew[$aHeader[0]]
    Global $aInputWidth[$aHeader[0]] = [100, 100, 100] ; hier die Länge (in Pixel) der Inputfelder eintragen
    Global $xPos = 20
    For $i = 1 To $aHeader[0]
    GUICtrlCreateLabel($aHeader[$i], $xPos + 2,200, 110, 20) ; Überschriften-Label erstellen
    GUICtrlSetFont(-1, 8, 400, 0, 'Verdana') ; Schriftgröße und -art der Überschriften festlegen
    $aNew[$i - 1] = GUICtrlCreateInput("", $xPos, 220, $aInputWidth[$i - 1], 20,Default, $WS_EX_STATICEDGE) ; Eingabefelder erstellen
    GUICtrlSetFont(-1, 10, 600, 0, 'Verdana') ; Schriftgröße und -art der Eingabefelder festlegen
    $hanew[$i-1] = GUICtrlGetHandle($aNew[$i - 1])
    $xPos += $aInputWidth[$i - 1] + 5
    Next

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

    GUISetState(@SW_SHOW, $hGui)
    GUIRegisterMsg($WM_Command ,"WM_COMMAND")

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

    While 1
    $nMsg = GUIGetMsg(1) ; Message-Event holen (1) = erweiterter Modus

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

    Switch $nMsg[0] ; anhand der Control-ID das entsprechende Case aufrufen
    case $anew[0]
    GUICtrlSetState($aNew[1], $GUI_FOCUS)
    #Region Schließen
    Case $GUI_EVENT_CLOSE ; User hat auf das Schließen-Symbol geklickt (bzw. die ESC-Taste gedrückt)
    Switch $nMsg[1] ; erweiterte Abfrage für welches Fenster
    Case $hGui ; User will das Hauptfenster schließen
    exit

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

    EndSwitch

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

    #EndRegion Schließen
    EndSwitch

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

    WEnd

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

    Func WM_COMMAND($hWnd, $iMsg, $iwParam, $ilParam)
    ;ConsoleWrite($hWnd & @tab & $iMsg & @tab & $iwParam & @tab & $ilParam& @CRLF)
    Local $hwndFrom, $iIDFrom, $iCode, $fokus
    ;$iIDFrom = BitAND($iwParam, 0xFFFF) ; Low Word
    $iCode = BitShift($iwParam, 16) ; Hi Word
    $fokus = _WinAPI_GetFocus()
    Switch $fokus
    case $hanew[0]
    switch $iCode
    case 0
    ;GUICtrlRecvMsg($anew[1],$NM_KEYDOWN)
    GUICtrlSetState($aNew[1], $GUI_FOCUS)
    ;GUICtrlSendMsg($anew[1],$NM_KEYDOWN, -1,0)
    EndSwitch
    case $hanew[1]
    switch $icode
    case 0
    GUICtrlSetState($aNew[2], $GUI_FOCUS)
    EndSwitch
    case $hanew[2]
    switch $iCode
    case 0
    GUICtrlSetState($aNew[0], $GUI_FOCUS)
    EndSwitch

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

    EndSwitch
    Return $GUI_RUNDEFMSG
    EndFunc ;==>WM_COMMAND

    [/autoit]


    Eine Möglichkeit über den Fokus.

    Einmal editiert, zuletzt von nuts (2. Oktober 2009 um 13:42)

  • Zitat

    Bei $BS_DEFPUSHBUTTON gibt teilweise Problem, wenn ein anderer Button den Fokus hat.

    Das verstehe ich nicht, entweder soll mit einem "Enter" der Fokus auf das nächste Inputfeld geschaltet werden, oder es soll ein Button gedrückt werden. Beides zusammen geht nicht, bzw ist ein Problem der Programmlogik.
    Die ausgefüllten Inputfelder sollen doch irgendwann weiterverarbeitet werden (Button am Ende der Maske). Da könnte man doch Oskars Idee weiterverarbeiten und nach dem Enter im letzten Inputfeld direkt auf den Button springen. Das ergäbe m.E, auch Sinn in der Usability. Wenn man vom letzten Inputfeld per TAB(s) zum Button springen muss, dann kann man gleich (wie gehabt) durch die Felder Tabben...

    */EDIT/* wg Langsamkeit

    Zitat

    In WM_Command den Fokus bestimmten und in Abjängigkeit vom Fokus reagieren.

    so hatte ich das gemeint^^

  • Ja habs auch grad bemerkt.
    Endweder man ist auf dem Input oder auf dem Button.

    Also "irgendwie" die Entertaste abfangen und entsprechend auf den Fokus reagieren.

    Danke an alle Beteiligten.

    P.S. Welche Message das Inputcontrol empfangsbreit macht wäre trotzdem ganz interessant.

    Einmal editiert, zuletzt von nuts (2. Oktober 2009 um 13:54)