Jump to content
Sign in to follow this  
notta

Auto tab inputbox?

Recommended Posts

notta

Is there a built in function(that I missed again) that will allow the focus of the input box to automatically move to the next inputbox after x amount of characters have been entered? Example would be a phone number. Input 555 and then it jumps to a second inputbox without having to hit the tab key. Thanks.

Share this post


Link to post
Share on other sites
-Ultima-

Nope. You're going to have to do this via the GetMsg() while loop, or if you're using OnEvent functions, use an event. Whatever the case, any time the event is fired, or GetMsg() returns the control you want to check, you need to to check the number of characters yourself, and if it reaches the desired threshold, you can change the focus using GUICtrlSetState($Control_ID, $GUI_FOCUS). This needs to be done for each and every control you want to behave like this.

Edited by -Ultima-

[ WinINet.au3 | Array.au3 (Optimized) | _UnixTimeParse() ]

Share this post


Link to post
Share on other sites
Siao

Specifically...

#include <GUIConstantsEx.au3>

Global $input_limit = 4

$gui = GUICreate("InputBox autofocus demo", 250, 100)
$in1 = GUICtrlCreateInput("", 40, 20, 50, 20)
GUICtrlSetLimit(-1, $input_limit)
$in2 = GUICtrlCreateInput("", 100, 20, 50, 20)
GUICtrlSetLimit(-1, $input_limit)
$in3 = GUICtrlCreateInput("", 160, 20, 50, 20)
GUICtrlSetLimit(-1, $input_limit)
$btn = GUICtrlCreateButton("OK", 100, 60, 50, 25)

GUIRegisterMsg(0x0111, "On_WM_COMMAND")
GUISetState()
While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
        Case $btn
            $str = GUICtrlRead($in1) & " " & GUICtrlRead($in2) & " " & GUICtrlRead($in3)
            MsgBox(0, "You have entered", $str)
    EndSwitch
WEnd

Func On_WM_COMMAND($hWnd, $Msg, $wParam, $lParam)
    $nNotifyCode = BitShift($wParam, 16)
    $nID = BitAnd($wParam, 0x0000FFFF)
    Switch $nNotifyCode
        Case 0x400 ;$EN_UPDATE
            If StringLen(GUICtrlRead($nID)) = $input_limit Then GUICtrlSetState($nID+1, $GUI_FOCUS)
    EndSwitch
EndFunc
Edited by Siao

"be smart, drink your wine"

Share this post


Link to post
Share on other sites
notta

Specifically...

#include <GUIConstantsEx.au3>

Global $input_limit = 4

$gui = GUICreate("InputBox autofocus demo", 250, 100)
$in1 = GUICtrlCreateInput("", 40, 20, 50, 20)
GUICtrlSetLimit(-1, $input_limit)
$in2 = GUICtrlCreateInput("", 100, 20, 50, 20)
GUICtrlSetLimit(-1, $input_limit)
$in3 = GUICtrlCreateInput("", 160, 20, 50, 20)
GUICtrlSetLimit(-1, $input_limit)
$btn = GUICtrlCreateButton("OK", 100, 60, 50, 25)

GUIRegisterMsg(0x0111, "On_WM_COMMAND")
GUISetState()
While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
        Case $btn
            $str = GUICtrlRead($in1) & " " & GUICtrlRead($in2) & " " & GUICtrlRead($in3)
            MsgBox(0, "You have entered", $str)
    EndSwitch
WEnd

Func On_WM_COMMAND($hWnd, $Msg, $wParam, $lParam)
    $nNotifyCode = BitShift($wParam, 16)
    $nID = BitAnd($wParam, 0x0000FFFF)
    Switch $nNotifyCode
        Case 0x400 ;$EN_UPDATE
            If StringLen(GUICtrlRead($nID)) = $input_limit Then GUICtrlSetState($nID+1, $GUI_FOCUS)
    EndSwitch
EndFunc
Thanks for the replies. I have never used GUIRegisterMsg. I could just paste this into my script and be done with it, but I'd really like to learn what's going on here. If Siao or anyone has the time could they help me understand what this is actually doing? I understand the basic graphical code :) but the function itself has me lost as lost can be. I have read many times how powerful GUIRegisterMsg is, but I have never really been able to grasp what's in the help file about it. Help understanding this would be appreciated if anyone has the time. Thanks.

Share this post


Link to post
Share on other sites
-Ultima-

@notta: http://msdn2.microsoft.com/en-us/library/ms647591.aspx

The inputbox sends a notification to the containing window whenever the user types into it. When that happens, the function registered for the WM_COMMAND notification gets fired. The $wParam contains the handle to the control that caused the function to be called (or some form of it anyway -- hence the call to BitAND()). After the ID is extracted from wParam, the function reads the current string from the control and gets its length, then compares it with $input_limit. From there, you can do whatever you want (like give focus to another control).

The reason why $nID+1 works to focus the next control is because it's based on the assumption that each input control is created exactly one after another. That means that creating any control in between the creation of those controls would cause the function to not jump to the next input properly. One example of when this might happen is if you happen to create a label in between each field. Just make sure you create labels separately from the inputboxes if you need to label them, I guess.

Edited by -Ultima-

[ WinINet.au3 | Array.au3 (Optimized) | _UnixTimeParse() ]

Share this post


Link to post
Share on other sites
Siao

To expand on what -Ultima- said...

Controls send various notifications to their parent window when something noteworthy happens or is about to happen. It is done either though WM_NOTIFY or WM_COMMAND (or sometimes with some standalone messages like WM_CTLCOLOREDIT). wParam and lParam of the message contains the info. Which contains what and how to extract it differs in each case, so that's why you should have MSDN library link close to hand when attempting to do something "tricky" with your GUI :) Luckily the part of MSDN dealing with common controls is clasified pretty good. http://msdn2.microsoft.com/en-us/library/bb773169.aspx

Now back to InputBox, which really is Edit control. It sends EN_UPDATE notification to its parent right before redrawing itself (which is caused by the text change), through WM_COMMAND message.

MSDN says: "wParam

The low-order word specifies the edit control identifier.

The high-order word specifies the notification message."

So you have to extract that high word from wParam, to know which notification it is (because many notifications go though WM_COMMAND) - here you need EN_UPDATE only. And you also need to extract low word from wParam to know the control ID of the InputBox which sent the notification (when you have several InputBoxes). That is done with

BitShift($wParam, 16)

BitAnd($wParam, 0x0000FFFF)

Why exactly these instructions? Consider that on 32-bit systems wParam is d(ouble)word, and has, well, 32 bits (and each bit can be either 1 or 0).

So if we say that hexadecimal representation of wParam looks like this:

0xHHHHLLLL

Then if we bitwise Shift it 16 bits to the right, it becomes:

0x0000HHHH

If we bitwise And it with 0x0000FFFF (why? because FF is max possible byte value, and all bits in in are set to 1, while 00 is the lowest possible byte value and all bits are set to 0), it becomes:

0x0000LLLL

Which is what we need.

From then on it's pretty selfexplanatory, after making sure notification = EN_UPDATE, we count chars in InputBox, and if it equals our limit, we pass the keyboard focus to the next control. In AutoIt, controls have IDs assigned in order you create them. Which is what I used for the sake of simplicity. Like -Ultima- noted, if you mix the order of creation of these controls, or create some other control inbetween your InputBoxes, it wouldn't exactly work as expected. In such case you'd have to use variables $in1, $in2, $in3 with some conditional statement.

Edited by Siao

"be smart, drink your wine"

Share this post


Link to post
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
Sign in to follow this  

×

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.