Jump to content

StringRight for numbers?


Recommended Posts

Hello, I am trying to make a GUI with buttons, which uses a big Switch Case.

While 1
   $selection = GUIGetMsg()
   Select
      Case $selection = $GUI_EVENT_CLOSE
         ExitLoop
      Case $selection = $but1
         Myfunc($command1)
      Case $selection = $but2
         Myfunc($command2)
      Case $selection = $but3
         Myfunc($command3)
      Case $selection = $but4
         Myfunc($command4)
      Case $selection = $but5
         Myfunc($command5)
      Case $selection = $but6
         Myfunc($command6)
      Case $selection = $but7
         Myfunc($command7)
      Case $selection = $but8
         Myfunc($command8)
      EndSelect

      Sleep(50)
Wend

Is there a way to get this down to just 2 cases?
1- $selection = $GUI_EVENT_CLOSE
2- $selection = $but#

Then, the second case is written in a way that it reads the number of the button that was pressed (but1, but3, but8, etc), and passes the correct $command# into Myfunc(). Is this possible?

I'm assuming the right one might be possible by reading the right-most character and then Executing $command+char. What if the buttons and commands go to 2 digits?

E.g. of rest of code:

GUICreate("GUI", 150, 330, @DesktopWidth - 150, 30)

Local $command1 = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"]
;...commandX
Local $command8 = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"]

$b1 = GUICtrlCreateButton ("Command1", 10, 10, 130, 30)
;...bX
$b8 = GUICtrlCreateButton ("Command8", 10, 290, 130, 30)

It's basically a gui with buttons which call functions.

Link to comment
Share on other sites

  • Moderators

Pured,

You could put all the button CIDs into an array and then loop through it - pseudo-code  looks like this:

; Declare array
Global $aButtons[][2]

; Then add CIDs to the array
; You need to advance the index each time and make sure the array is big enough, but that is not too difficult

$aButtons[$i][0] = GUICtrlCreateButton(...)
$aButtons[$i][1] = Function to call ; Either as string or as object

; Then loop through the array in the While...WEnd loop

While 1
    $iSel = GUIGetMsg()
    Switch
        Case $GUI_EVENT_CLOSE
            Exit
        Case Else
            For $i = 0 To UBound($aButtons) - 1
                If $iSel = $aButtons[$i][0] Then
                    Call function - depending on how it was stored
                    ExitLoop ; because we found a match
                EndIf
            Next
    EndSwitch
WEnd

Please ask if you have any questions.

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:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

Assuming that buttons are created all together :

Local $selection, $but
While 1
   $selection = GUIGetMsg()
   Switch $selection
      Case $GUI_EVENT_CLOSE
         ExitLoop
     Case $but1 To $but8
        $but = $selection-$but1+1
         Myfunc(eval("command" & $but))
      EndSwitch
Wend

 

Edited by Nine
Link to comment
Share on other sites

@Melba23 Thanks, that is good enough for me.

I've now got:

Local $commands = [ _
   ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], _ ;command1
   ;...RepeatUntilCommandX
] ;End of the array.

GUICreate("GUI", 150, 330, @DesktopWidth - 150, 30)

Local $buttons = [ _
   GUICtrlCreateButton("COMMAND1", 10, 10, 130, 30), _
   ;...RepeatUntilButtonX
] ;End of the array.

Func Myfunc($index)
   For $floop = 0 To UBound($commands[$index]) - 1
      MouseClick("Primary", 100, 100, 1, 0) ;Temporary ControlSend().
      Send($commands[$index][$floop])
      Sleep(100)
   Next
EndFunc

While 1
   $selection = GUIGetMsg()
   Select
      Case $selection = $GUI_EVENT_CLOSE
         Exit
      Case Else
         For $floop = 0 To UBound($buttons) - 1
            If $selection = $buttons[$floop] Then
               Myfunc($floop)

               ExitLoop
            EndIf

            Sleep(10)
         Next
      EndSelect

      Sleep(50)
Wend

Error comes with how I'm trying to use the 2D array.
When I tried debugging, ConsoleWrite(UBound($commands)) shows me the correct number, but trying to do ConsoleWrite(UBound($commands[0])) gives me this error instead of my expected "10":
Array variable has incorrect number of subscripts or subscript dimension range exceeded.

What is wrong with the way I try to do UBound on an element (it's an array) inside $commands?
I have also tried writing the arrays in different ways, but it didn't help.

Link to comment
Share on other sites

  • Moderators

Pured & Nine,

Quote

ids are created sequentially.  They are simply integer.

Not strictly true. A ControlId is actually the index of the control in an internal AutoIt array and it is true that they are normally consecutive. However, if you delete a control then the next created control takes that same index - filling the hole in the array if you like.

#include <GUIConstantsEx.au3>

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

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

GUISetState()

ConsoleWrite("Consecutive ControlIDs" & @CRLF)
ConsoleWrite("Button 1: " & $cButton_1 & @CRLF)
ConsoleWrite("Button 2: " & $cButton_2 & @CRLF)
ConsoleWrite("Button 3: " & $cButton_3 & @CRLF)

GUICtrlDelete($cButton_2)

$cButton_4 = GUICtrlCreateButton("Button 4", 10, 130, 80, 30)

ConsoleWrite("Filling the hole:" & @CRLF)
ConsoleWrite("Button 4: " & $cButton_4 & @CRLF)

While 1

    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
    EndSwitch

WEnd

So be a little careful using Nine's trick of using the ControlIds as loop parameters - it only works when you have created all the controls consecutively AND not deleted any control previously. The correct way (and I promise I am not saying this because my script did it that way) is to use an array to hold the ControlIDs so that you can guarantee checking the correct values.

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:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

Agree with @Melba23.  Make a note (;comment) in your script that if you use my trick to not delete any controls otherwise your script may not work anymore.

Edit : I use this trick all the times because I very rarely delete controls.  I may hide some, but delete is not usual to me.

Edited by Nine
Link to comment
Share on other sites

@Pured Here is an example of what Melba23 was suggesting (I was bored and noticed you had issues in the code you posted), although I was also a little confused with what your commands array was supposed to do, hopefully you'll get the gist.

#include <Array.au3>
#include <GUIConstantsEx.au3>
Global $g_aButtons[10][11], $y = 10

GUICreate("GUI", 150, 320)

;~ Creates a 2d Array
;~ $g_aButtons[0][x] = [ButtonId1, 1, 2, 3, 4, 5, 6, 7, 8, 9 10]
;~ etc...
;~ $g_aButtons[9][x] = [ButtonId10, 1, 2, 3, 4, 5, 6, 7, 8, 9 10]
For $i = 0 To UBound($g_aButtons) - 1
    $g_aButtons[$i][0] = GUICtrlCreateButton("Command" & $i + 1, 10, $y, 130, 30)
    For $j = 1 To 10
        $g_aButtons[$i][$j] = $j
    Next
    $y += 30
Next

GUISetState()

While 1
    $iSel = GUIGetMsg()
    Switch $iSel
        Case $GUI_EVENT_CLOSE
            Exit
        Case Else
            For $i = 0 To UBound($g_aButtons) - 1
                If $iSel = $g_aButtons[$i][0] Then
                    ;~ We send the array row number to MyFunc
                    MyFunc($i)
                    ExitLoop
                EndIf
            Next
    EndSwitch
WEnd

Func MyFunc($_iIndex)
    ;~ Read the commands from 1 to the end of the 2d Array row
    For $x = 1 To UBound($g_aButtons, 2) - 1
        ConsoleWrite("Command" & $_iIndex + 1 & " - Index: " & $g_aButtons[$_iIndex][$x] & @CRLF)
    Next
EndFunc

 

Link to comment
Share on other sites

Or as an option (in case the text of the button is enough to indicate in the function):

 

While 1
    $iMsg = GUIGetMsg()
    
    Switch $iMsg
        Case $GUI_EVENT_CLOSE
            ExitLoop
        Case $but1, $but2, $but3, $but4, $but5, $but6, $but7, $but8
            Myfunc(GUICtrlRead($iMsg, 1))
    EndSwitch
WEnd

But the array method is much better.

 

Spoiler

Using OS: Win 7 Professional, Using AutoIt Ver(s): 3.3.6.1 / 3.3.8.1

AutoIt_Rus_Community.png AutoIt Russian Community

My Work...

Spoiler

AutoIt_Icon_small.pngProjects: ATT - Application Translate Tool {new}| BlockIt - Block files & folders {new}| SIP - Selected Image Preview {new}| SISCABMAN - SciTE Abbreviations Manager {new}| AutoIt Path Switcher | AutoIt Menu for Opera! | YouTube Download Center! | Desktop Icons Restorator | Math Tasks | KeyBoard & Mouse Cleaner | CaptureIt - Capture Images Utility | CheckFileSize Program

AutoIt_Icon_small.pngUDFs: OnAutoItErrorRegister - Handle AutoIt critical errors {new}| AutoIt Syntax Highlight {new}| Opera Library! | Winamp Library | GetFolderToMenu | Custom_InputBox()! | _FileRun UDF | _CheckInput() UDF | _GUIInputSetOnlyNumbers() UDF | _FileGetValidName() UDF | _GUICtrlCreateRadioCBox UDF | _GuiCreateGrid() | _PathSplitByRegExp() | _GUICtrlListView_MoveItems - UDF | GUICtrlSetOnHover_UDF! | _ControlTab UDF! | _MouseSetOnEvent() UDF! | _ProcessListEx - UDF | GUICtrl_SetResizing - UDF! | Mod. for _IniString UDFs | _StringStripChars UDF | _ColorIsDarkShade UDF | _ColorConvertValue UDF | _GUICtrlTab_CoverBackground | CUI_App_UDF | _IncludeScripts UDF | _AutoIt3ExecuteCode | _DragList UDF | Mod. for _ListView_Progress | _ListView_SysLink | _GenerateRandomNumbers | _BlockInputEx | _IsPressedEx | OnAutoItExit Handler | _GUICtrlCreateTFLabel UDF | WinControlSetEvent UDF | Mod. for _DirGetSizeEx UDF
 
AutoIt_Icon_small.pngExamples: 
ScreenSaver Demo - Matrix included | Gui Drag Without pause the script | _WinAttach()! | Turn Off/On Monitor | ComboBox Handler Example | Mod. for "Thinking Box" | Cool "About" Box | TasksBar Imitation Demo

Like the Projects/UDFs/Examples? Please rate the topic (up-right corner of the post header: Rating AutoIt_Rating.gif)

* === My topics === *

==================================================
My_Userbar.gif
==================================================

 

 

 

AutoIt is simple, subtle, elegant. © AutoIt Team

Link to comment
Share on other sites

It might be worth putting a >0 check before the For loop, as GUIGetMsg pretty steadily returns values less than 1 for different GUI events ($GUI_EVENT_NONE, and $GUI_EVENT_MOUSEMOVE in particular come through pretty frequently). Unless you're already handling those events somewhere else in your switch statement, then it's going to be running through that For loop, looking for the control ID pretty often.

Just something like this (modifying @Subz example):

While 1
    $iSel = GUIGetMsg()
    Switch $iSel
        Case $GUI_EVENT_CLOSE
            Exit
        Case Else
            If $iSel > 0 Then
                For $i = 0 To UBound($g_aButtons) - 1
                    If $iSel = $g_aButtons[$i][0] Then
                        ;~ We send the array row number to MyFunc
                        MyFunc($i)
                        ExitLoop
                    EndIf
                Next
            EndIf
    EndSwitch
WEnd

 

Edited by therks
Link to comment
Share on other sites

Thanks for all the help and approaches. I've combined them all and am really happy with what I've got now (one place of modification and <50 lines of code):

#include <GUIConstants.au3>
#include <Array.au3>

Local $buttons[0] ;Array to be added to.

;Modification Start
GUICreate("GUI", 150, 330, @DesktopWidth - 150, 30)

Local $var1 = ["comman1", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
;...
Local $varX = ["commandX", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
;Modification End

For $i = 0 To X - 1 ;X = based on above $var#
    _ArrayAdd($buttons, Execute("$var" + $i)
Next

For $i = 0 To UBound($buttons) - 1
   $buttons[$i][0] = GUICtrlCreateButton($buttons[$i][0], 10, ($i * 40) + 10, 130, 30)
Next

However... There is still one small improvement I'd like to make.

Instead of having to deal with the array twice, I want to deal with it just once. Therefore, instead of:

Local $var1 = ["command1", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
;...
Local $varX = ["commandX", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

For $i = 0 To X - 1 ;X = based on above $var#
    _ArrayAdd($buttons, Execute("$var" + $i)
Next

I want to do:

_ArrayAdd($buttons, ["command1", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
;...
_ArrayAdd($buttons, ["commandX", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])


How can I achieve this?

 

@Subz Basically we have a set of hotkeys (numbers) which need to be pressed in sequence to do different things, e.g. Backup, Rename, Remove, Begin, Pause, End, ...
Creating a GUI allows us to give human visuals to these hotkeys, which they can simply click from a GUI.

Link to comment
Share on other sites

 Thanks, I've got that working now with (1):

_ArrayAdd($buttons, "command1,1,2,3,4,5,6,7,8,9,10", 1, ",")

 

Final question (2):

Local $buttons[0][15]

;_ArrayAdd()s here...

For $i = 0 To UBound($buttons) - 1
   $buttons[$i][0] = GUICtrlCreateButton($buttons[$i][1], 10, ($i * 40) + 10, 130, 30)
Next

The above code works. However, I don't want to explicitly make $buttons an [X][15] array. I want it to be [X][Y], meaning each [X] can have a different number of elements in [Y] instead of always 15.

Simply removing the [15] from the code sounds like it would work to me, because we are adding an array to [X], but it won't let me do that due to how _ArrayAdd() works. It seems it only populates the pre-existing elements of an array in [Y] rather than creating an array in [X] (3):

==> Array variable has incorrect number of subscripts or subscript dimension range exceeded.:
$buttons[$i][0] = GUICtrlCreateButton($buttons[$i][1], 10, ($i * 40) + 10, 130, 30)
^ ERROR

I think if I wanted to achieve this, I would have to go back to my old approach of (4):

Local $var1 = ["command1", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
;...
Local $varX = ["commandX", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

For $i = 0 To X - 1 ;X = based on above $var#
    _ArrayAdd($buttons, Execute("$var" + $i)
Next

Please let me know if there is a way I can achieve this with the kind of code I have in (2) rather than have to resort to (4).

Link to comment
Share on other sites

[X] = Row number
[Y] = Column number

Use the maximum number of columns required when creating the array, if you look at $var1, you need 11 columns, so for example:

Local $var1[1][11]       ;~ Create an array with 1 row, 11 columns
$var1[0][0] = "command1" ;~ Row 1, Column 1
$var1[0][1] = 1          ;~ Row 1, Column 2
$var1[0][2] = 2          ;~ Row 1, Column 3
$var1[0][3] = 3          ;~ Row 1, Column 4
$var1[0][4] = 4          ;~ Row 1, Column 5
$var1[0][5] = 5          ;~ Row 1, Column 6
$var1[0][6] = 6          ;~ Row 1, Column 7
$var1[0][7] = 7          ;~ Row 1, Column 8
$var1[0][8] = 8          ;~ Row 1, Column 9
$var1[0][9] = 9          ;~ Row 1, Column 10
$var1[0][10] = 10        ;~ Row 1, Column 11

You can add a place holder for a column if you require, by leaving it blank or adding text (see example below), you could also use _ArrayColInsert, to add another column to an existing array, however recommend specifying your column dimensions first otherwise you need to track where your columns.

Also recommend adding in error (debug) handling using the @error and other functions like _ArrayDisplay, below is a basic example:

#include <Array.au3>
Global $g_bDebug = True ;~ Use false to disable debugging

Global $g_aCommands[0][12] ;~ Create an array with 0 rows, 12 columns, $g = Global Variable, a = Array, Commands = description of the variable
_ArrayAdd($g_aCommands, "Row 1, Column 0 - Button1 place holder|Command1|1|2|3|4|5|6|7|8|9|10") ;~ Adds new row, with 12 columns - row 0
    If $g_bDebug Then _Error_ArrayAdd(@error)
_ArrayAdd($g_aCommands, "Row 2, Column 0 - Button2 place holder|Command2|1|2|3|4|5|6|7|8|9|10") ;~ Adds new row, with 12 columns - row 1
    If $g_bDebug Then _Error_ArrayAdd(@error)
_ArrayAdd($g_aCommands, "Row 3, Column 0 - Button3 place holder|Command3|1|2|3|4|5|6|7|8|9|10") ;~ Adds new row, with 12 columns - row 2
    If $g_bDebug Then _Error_ArrayAdd(@error)
_ArrayAdd($g_aCommands, "Row 4, Column 0 - Button4 place holder|Command4|1|2|3|4|5|6|7|8|9|10") ;~ Adds new row, with 12 columns - row 3
    If $g_bDebug Then _Error_ArrayAdd(@error)
_ArrayAdd($g_aCommands, "|Command5|1|2|3|4|5|6|7|8|9|10")                                       ;~ This also adds new row, with 12 columns - row 4, you do not need to specify the placeholder
    If $g_bDebug Then _Error_ArrayAdd(@error)

If $g_bDebug Then _ArrayDisplay($g_aCommands, "Before adding buttons")
For $i = 0 To UBound($g_aCommands) - 1 ;~ Loop from row 1 (0) to the last row (4)
    ;~ Replace row ($i), column 1 (0) with control id
    $g_aCommands[$i][0] = GUICtrlCreateButton($g_aCommands[$i][1], 10, ($i * 40) + 10, 130, 30)
Next
If $g_bDebug Then _ArrayDisplay($g_aCommands, "After adding buttons")

Func _Error_ArrayAdd($_iError)
    If Not $_iError Then Return ;~ Check if error occurred
    MsgBox(4096, "_ArrayAdd Error", "Error occurred" & @CRLF & "See help file for error: " & $_iError)
    Exit ;~ Exit the script and fix the issue
EndFunc

 

Link to comment
Share on other sites

Sorry, I don't think I explained that well.

Not all commands have 10 actions. Some might have 3, some 10, some 7, etc...
I want to know if the size of Y can be dynamic and not pre-defined. The reason I chose 15 is because I know no commands will be that long, but I don't like this hard-coded approach.

Like you said, empty elements are not an issue because I can simply use an If Then Else statement.

Link to comment
Share on other sites

A 2D array is essentially a table, you can't have one row having more columns than the max otherwise it will error, you could use subarrays example:

#include <Array.au3>
#include <GUIConstantsEx.au3>

Global $g_aButtons[5][2] ;~ Create an array with 0 rows, 2 columns, $g = Global Variable, a = Array, Commands = description of the variable
Global $g_aCommand[] = ["Command1",1,2,3,4] ;~ Create 1D Array, 5 rows
    $g_aButtons[0][1] = $g_aCommand
Global $g_aCommand[] = ["Command2",1,2,3,4,5,6,7] ;~ Create 1D Array, 8 rows
    $g_aButtons[1][1] = $g_aCommand
Global $g_aCommand[] = ["Command3",1,2,3] ;~ Create 1D Array, 4 rows
    $g_aButtons[2][1] = $g_aCommand
Global $g_aCommand[] = ["Command4",1,2,3,4,5,6,7,8] ;~ Create 1D Array, 9 rows
    $g_aButtons[3][1] = $g_aCommand
Global $g_aCommand[] = ["Command5",1,2,3,4,5,6,7,8,9,10] ;~ Create 1D Array, 11 rows
    $g_aButtons[4][1] = $g_aCommand

GUICreate("", 500, (UBound($g_aButtons) * 40) + 10)
For $i = 0 To UBound($g_aButtons) - 1 ;~ Loop from row 1 (0) to the last row (4)
    ;~ Replace row ($i), column 1 (0) with control id
    $g_aButtons[$i][0] = GUICtrlCreateButton(($g_aButtons[$i][1])[0], 10, ($i * 40) + 10, 130, 30)
Next

GUISetState()
While 1
    $iSel = GUIGetMsg()
    Switch $iSel
        Case $GUI_EVENT_CLOSE
            Exit
        Case Else
            For $i = 0 To UBound($g_aButtons) - 1
                If $iSel = $g_aButtons[$i][0] Then
                    ;~ We send the array row number to MyFunc
                    MyFunc($i)
                    ExitLoop
                EndIf
            Next
    EndSwitch
WEnd

Func MyFunc($_iIndex)
    ;~ Read the commands from 1 to the end of the 2d Array row
    _ArrayDisplay($g_aButtons[$_iIndex][1])
    Local $aCommand = $g_aButtons[$_iIndex][1]
    MsgBox(4096, $aCommand[0], _ArrayToString($aCommand, @CRLF, 1, -1, @CRLF))
EndFunc

 

Link to comment
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
 Share

  • Recently Browsing   0 members

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