Jump to content

Using the {enter} key as a Tab


Go to solution Solved by Melba23,

Recommended Posts

Posted

I am writing a script where I would like the users to be able to hit enter as well as the tab key to navigate the inputs.

I have this working apart from one problem, when a message box appears and the user presses enter to close it, this will then close the message box but still send the Tab key, here is the part of my code I am using;

I thought the code would not run as it checks to see if the input is in focus, my problem is that after the message box my code returns the focus to the input, this then sends the Tab, I am not sure how to get around it? 

$cEnter = GUICtrlCreateDummy()
    Local $aAccelKeys[1][2] = [["{ENTER}", $cEnter]]
    GUISetAccelerators($aAccelKeys)

    While 1
        $nMsg = GUIGetMsg()
        Switch $nMsg
            Case $GUI_EVENT_CLOSE
                _SQL_Close()
                $btFormat.Close( 1 )
                $btApp.Quit( 1 )    
                Exit    
            case $cEnter
                enterPressed()
        EndSwitch       
    WEnd

Func enterPressed()

    $cFocus = _WinAPI_GetFocus()
    If $cFocus = GUICtrlGetHandle( $txtPackerID ) Then Send( "{TAB}" )
    If $cFocus = GUICtrlGetHandle( $txtParcType ) Then Send( "{TAB}" )
    If $cFocus = GUICtrlGetHandle( $txtWeight ) Then savePrint()

EndFunc

I hope I have explained well enough!

Thanks in advance.

 

  • Moderators
Posted

ale1981,

This example script does not move the focus when using {ENTER} to clear a MsgBox: ;)

#include <GUIConstantsEx.au3>
#include <MsgBoxConstants.au3>
#include <WinAPI.au3>

$hGUI = GUICreate("Test", 500, 500)

$cInput_1 = GUICtrlCreateInput("", 10, 10, 200, 20)
$cInput_2 = GUICtrlCreateInput("", 10, 50, 200, 20)
$cInput_3 = GUICtrlCreateInput("", 10, 90, 200, 20)

$cEnter = GUICtrlCreateDummy()

GUISetState()

Local $aAccelKeys[1][2] = [["{ENTER}", $cEnter]]
GUISetAccelerators($aAccelKeys)

AdlibRegister("_MsgBox", 5000)

While 1

    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
        Case $cEnter
            Switch  _WinAPI_GetFocus()
                Case GUICtrlGetHandle($cInput_1)
                    GUICtrlSetState($cInput_2, $GUI_FOCUS) ; Why Send {TAB} - this is more efficient
                Case GUICtrlGetHandle($cInput_2)
                    Send ("{TAB}")                         ; But this still does not move focus
                Case GUICtrlGetHandle($cInput_3)
                    ConsoleWrite("End" & @CRLF)
            EndSwitch
    EndSwitch

WEnd

Func _MsgBox()
    MsgBox($MB_SYSTEMMODAL, "Hi", "")
EndFunc
How does your code differ from that? :huh:

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

  Reveal hidden contents

 

Posted

Thanks guys will experiment and get back to you, not quite sure why I was using Send instead of the SetState, making it difficult for myself!

Posted

@Melba23 OK, think I have found a problem, try this, when pressing Enter on the message box the focus will go to the next input and ignores the GUICtrlSetState in the checkEntry function, is it possible to stop this?

#include <GUIConstantsEx.au3>
#include <MsgBoxConstants.au3>
#include <WinAPI.au3>

$hGUI = GUICreate("Test", 500, 500)

$cInput_1 = GUICtrlCreateInput("", 10, 10, 200, 20)
$cInput_2 = GUICtrlCreateInput("", 10, 50, 200, 20)
$cInput_3 = GUICtrlCreateInput("", 10, 90, 200, 20)

$cEnter = GUICtrlCreateDummy()

GUISetState()

Local $aAccelKeys[1][2] = [["{ENTER}", $cEnter]]
GUISetAccelerators($aAccelKeys)

Func checkEntry()

    MsgBox( 0, "Test", "Press Enter to close this message box" )
    GUICtrlSetState( $cInput_1, $GUI_FOCUS )

EndFunc

While 1

    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
        Case $cInput_1
            checkEntry()
        Case $cEnter
            Switch  _WinAPI_GetFocus()
                Case GUICtrlGetHandle($cInput_1)
                    GUICtrlSetState($cInput_2, $GUI_FOCUS) ; Why Send {TAB} - this is more efficient
                Case GUICtrlGetHandle($cInput_2)
                    Send ("{TAB}")                         ; But this still does not move focus
                Case GUICtrlGetHandle($cInput_3)
                    ConsoleWrite("End" & @CRLF)
            EndSwitch
    EndSwitch

WEnd
  • Moderators
Posted

ale1981,

Sorry, only just got in. I will look at both your posts later tonight / tomorrow. :)

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

  Reveal hidden contents

 

  • Moderators
Posted

ale1981,

The problem is caused by your code structure - you are looking for the event of {ENTER} being pressed in an input AND as an accelerator key. Each time you press {ENTER} inside the input you are firing both events and so getting the undesired behaviour. :(>

The way to get round this is to check the input content within the accelerator handler and then decide what to do:

#include <GUIConstantsEx.au3>
#include <MsgBoxConstants.au3>
#include <WinAPI.au3>

$hGUI = GUICreate("Test", 500, 500)

$cInput_1 = GUICtrlCreateInput("", 10, 10, 200, 20)
$cInput_2 = GUICtrlCreateInput("", 10, 50, 200, 20)
$cInput_3 = GUICtrlCreateInput("", 10, 90, 200, 20)

$cEnter = GUICtrlCreateDummy()

GUISetState()

Local $aAccelKeys[1][2] = [["{ENTER}", $cEnter]]
GUISetAccelerators($aAccelKeys)

While 1

    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
        Case $cEnter
            Switch  _WinAPI_GetFocus()
                Case GUICtrlGetHandle($cInput_1)
                    ; Check the input content
                    If checkEntry() = True Then
                        ; Correct so move to next input
                        GUICtrlSetState($cInput_2, $GUI_FOCUS)
                    EndIf
                    ; Not correct so stay in current input
                Case GUICtrlGetHandle($cInput_2)
                    If checkEntry() = True Then
                        GUICtrlSetState($cInput_3, $GUI_FOCUS)
                    EndIf
                Case GUICtrlGetHandle($cInput_3)
                    If checkEntry() = True Then
                        ConsoleWrite("End" & @CRLF)
                    EndIf

            EndSwitch
    EndSwitch

WEnd

Func checkEntry()

    ; Random chance of correct answer or fail
    If Mod(@SEC, 2) = 0 Then
        MsgBox($MB_SYSTEMMODAL, "Test Fail", "Press Enter to close this message box" )
        Return False
    EndIf
    Return True

EndFunc
All clear? :)

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

  Reveal hidden contents

 

Posted (edited)

Melba,

Thanks for the reply.  I see exactly what you are saying, now my problem is the Tab key does nothing, so if I amend the code to the below then press the Tab key, pressing Enter on the message box still seems to move the focus or I get two message boxes appear?

#include <GUIConstantsEx.au3>
#include <MsgBoxConstants.au3>
#include <WinAPI.au3>

$hGUI = GUICreate("Test", 500, 500)

$cInput_1 = GUICtrlCreateInput("", 10, 10, 200, 20)
$cInput_2 = GUICtrlCreateInput("", 10, 50, 200, 20)
$cInput_3 = GUICtrlCreateInput("", 10, 90, 200, 20)

$cEnter = GUICtrlCreateDummy()

GUISetState()

Local $aAccelKeys[1][2] = [["{ENTER}", $cEnter]]
GUISetAccelerators($aAccelKeys)

While 1

    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
        Case $cInput_1
           If checkEntry() = True Then
                ; Correct so move to next input
                GUICtrlSetState($cInput_2, $GUI_FOCUS)
            EndIf
        Case $cEnter
            Switch  _WinAPI_GetFocus()
                Case GUICtrlGetHandle($cInput_1)
                    ; Check the input content
                    If checkEntry() = True Then
                        ; Correct so move to next input
                        GUICtrlSetState($cInput_2, $GUI_FOCUS)
                    EndIf
                    ; Not correct so stay in current input
                Case GUICtrlGetHandle($cInput_2)
                    If checkEntry() = True Then
                        GUICtrlSetState($cInput_3, $GUI_FOCUS)
                    EndIf
                Case GUICtrlGetHandle($cInput_3)
                    If checkEntry() = True Then
                        ConsoleWrite("End" & @CRLF)
                    EndIf

            EndSwitch
    EndSwitch

WEnd

Func checkEntry()

    ; Random chance of correct answer or fail
    If Mod(@SEC, 2) = 0 Then
        MsgBox($MB_SYSTEMMODAL, "Test Fail", "Press Enter to close this message box" )
        Return False
    EndIf
    Return True

EndFunc
Edited by ale1981
  • Moderators
Posted

ale1981,

 

  Quote

now my problem is the Tab key does nothing

If you want the {TAB} key to run the check and move on if correct in the same manner as the {ENTER} key, just set it as another accelerator linked to the same dummy control:

Local $aAccelKeys[2][2] = [["{ENTER}", $cEnter], ["{TAB}", $cEnter]]
Now pressing either of the 2 keys will run the handler. :)

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

  Reveal hidden contents

 

  • Moderators
Posted

ale1981,

What else do you want it to do? :huh:

Perhaps if you post the code of the GUI you are actually using rather than this minimal reproducer then things might become clearer. ;)

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

  Reveal hidden contents

 

Posted

Melba,

On most controls I would like the Tab key to do as it usually does but only on 3 of my inputs I want it to work with the Enter key.

Can I PM you my code rather than post it here, it's 550 lines?

Thanks

  • Moderators
Posted

ale1981,

By all means send it via PM. :)

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

  Reveal hidden contents

 

  • Moderators
  • Solution
Posted

ale1981,

But what about this:

#include <GUIConstantsEx.au3>
#include <MsgBoxConstants.au3>
#include <WinAPI.au3>

$hGUI = GUICreate("Test", 500, 500)

$cInput_1 = GUICtrlCreateInput("", 10, 10, 200, 20)
$cInput_2 = GUICtrlCreateInput("", 10, 50, 200, 20)
$cInput_3 = GUICtrlCreateInput("", 10, 90, 200, 20)

$cButton_1 = GUICtrlCreateButton("Button 1", 250, 10, 80, 30)
$cButton_2 = GUICtrlCreateButton("Button 2", 250, 50, 80, 30)
$cButton_3 = GUICtrlCreateButton("Button 3", 250, 90, 80, 30)

$cEnter = GUICtrlCreateDummy()

GUISetState()

Local $aAccelKeys[2][2] = [["{ENTER}", $cEnter], ["{TAB}", $cEnter]] ; Make {TAB} an accelerator
GUISetAccelerators($aAccelKeys)

While 1

    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
        Case $cEnter
            Switch  _WinAPI_GetFocus()
                Case GUICtrlGetHandle($cInput_1)
                    ; Check the input content
                    If checkEntry() = True Then
                        ; Correct so move to next input
                        GUICtrlSetState($cInput_2, $GUI_FOCUS)
                    EndIf
                    ; Not correct so stay in current input
                Case GUICtrlGetHandle($cInput_2)
                    If checkEntry() = True Then
                        GUICtrlSetState($cInput_3, $GUI_FOCUS)
                    EndIf
                Case GUICtrlGetHandle($cInput_3)
                    If checkEntry() = True Then
                        ConsoleWrite("End" & @CRLF)
                    EndIf
                Case Else
                    GUISetAccelerators(0)                     ; Remove accelerator link
                    ControlSend($hGUI, "", "", "{TAB}")       ; Send {TAB} to the GUI
                    GUISetAccelerators($aAccelKeys)           ; Reset the accelerator

            EndSwitch
    EndSwitch

WEnd

Func checkEntry()

    ; Random chance of correct answer or fail
    If Mod(@SEC, 2) = 0 Then
        MsgBox($MB_SYSTEMMODAL, "Test Fail", "Press Enter to close this message box" )
        Return False
    EndIf
    Return True

EndFunc
That works for me - you can tab between the buttons without problem. :)

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

  Reveal hidden contents

 

Posted

Melba, 

Is it possible to detect which of the Accelerator keys was pressed or would it be best to split them in to separate keys?

  • Moderators
Posted

ale1981,

You could create another dummy control and link the {TAB} key to that - then you would have separate event handler code in the idle loop. :)

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

  Reveal hidden contents

 

  • Moderators
Posted

ale1981,

As always,, delighted I could help. :)

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

  Reveal hidden contents

 

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...