Jump to content

Reference a ComboBox individually


Recommended Posts

So I've hit a wall in working out the logic behind a problem I'm having. The scenario is this:

I have a loop iterating up to a certain amount of 'slots', creating rows of GUI elements in a program. Currently I'm modding it to include ComboBoxes within that loop. The elements all can be referenced by row in functions etc elsewhere simply being called via "$Elem1[$i]" "$Elem2[$i]" "$Elem3[$i]" etc. But when creating a variable for the combobox if I add [$i] to the variable the combobox suddenly doesn't get populated properly, I'm assuming because you can't place comboboxes into arrays? It sounds a little confusing, but the screenshot and code snippet should explain what I'm talking about :P

So this is the GUI, with the rows being produced (the comboboxes I added into the loop - showing the bug I'm facing when adding [$i] to the variable they're declared into):

https://imgur.com/a/RISPO

And this is the code producing those elements (I'll cut some out since it's mainly the comboboxes we're concerned with):

For $i = 0 To $g_iUpgradeSlots - 1
        $g_hPicUpgradeStatus[$i]= GUICtrlCreateIcon($g_sLibIconPath, $eIcnTroops, $x - 10, $y+1, 14, 14)
            _GUICtrlSetTip(-1, $sTxtStatus)
        $g_hChkUpgrade[$i] = GUICtrlCreateCheckbox($i+1 &":", $x + 5, $y+1, 34, 15)
            _GUICtrlSetTip(-1,  $sTxtCheckBox & " #" & $i+1 & " " & $sTxtAfterUsing)
;           GUICtrlSetFont(-1, 8)
            GUICtrlSetOnEvent(-1, "btnchkbxUpgrade")
        $g_hTxtUpgradeName[$i] = GUICtrlCreateInput("", $x+40, $y, 87, 17,BitOR($ES_CENTER, $GUI_SS_DEFAULT_INPUT, $ES_READONLY, $ES_NUMBER)) ;ORIGINAL $g_hTxtUpgradeName[$i] = GUICtrlCreateInput("", $x+40, $y, 107, 17,BitOR($ES_CENTER, $GUI_SS_DEFAULT_INPUT, $ES_READONLY, $ES_NUMBER))
;           GUICtrlSetFont(-1, 8)
            _GUICtrlSetTip(-1, $sTxtShowName)
        $g_hTxtUpgradeLevel[$i] = GUICtrlCreateInput("", $x+130, $y, 23, 17, BitOR($ES_CENTER, $GUI_SS_DEFAULT_INPUT, $ES_READONLY, $ES_NUMBER))
;           GUICtrlSetFont(-1, 8)
            _GUICtrlSetTip(-1, $sTxtShowLevel)

....

        $g_hIntUpgradeMaxLevel = GUICtrlCreateCombo("", $x + 395, $y+1, 35, 25, BitOR($CBS_DROPDOWNLIST, $CBS_AUTOHSCROLL)) ;Create dropdown menu (combo box)
            GUICtrlSetTip(-1, $sTxtMaxLevel)
            GUICtrlSetData($g_hIntUpgradeMaxLevel, "1|2|3|4|5|6|7|8|9|10|11|12|13|14", "14") ;Populate it with potential levels

        $y += 22
    Next

So it's that combo box at the end I'm trying to reference by individual row. If I add "$g_hIntUpgradeMaxLevel[$i]" the comboboxes don't get populated (as in the screenshot) so it has to be a single variable. This means the variable will just be populated with the last combobox created so the program won't realise which row I'm trying to pull the combobox index from, if you see what I mean? :blink:

Each combobox is subject to change indvividually, I added this:

$g_hTxtUpgradeLevelRef[$i] = (_GUICtrlComboBox_GetCurSel($g_hIntUpgradeMaxLevel)) + 1

to the end of the loop which is fine for when the elements are created, but I can't think of a way to update them individually on an event.

I've messed around with functions elsewhere through SetOnEvent, but again, the variable is still just a static value of the last combobox created - also since you can't parse parameters via OnEvent things are even more difficult :P

I'm probably missing something totally obvious, but after spending hours reading the code I'm slightly burnt out and could use a fresh pair of eyes - the more I think about it the further I get from a solution :>

Thanks in advance!

mBernin

Link to comment
Share on other sites

Maybe something like:

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

Example()

Func Example()
    Local $idComboBox[4], $iY = 10, $sComboRead = ""
    Local $hGUI = GUICreate("Example", 300, 200)

    ; Create a combobox control.
    For $i = 0 To 3
        $idComboBox[$i] = GUICtrlCreateCombo("Item " & $i, 10, $iY, 185, 20)
        $iY += 25
    Next
    Local $idClose = GUICtrlCreateButton("Close", 210, 170, 85, 25)

    ; Add additional items to the combobox.
    For $i = 0 To 3
        GUICtrlSetData($idComboBox[$i], "Item 1|Item 2|Item 3", "Item " & $i)
    Next
    GUISetState()
    While 1
        $iMsg = GUIGetMsg()
        For $i = 0 To 3
            If $iMsg = $idComboBox[$i] Then
               $sComboRead = GUICtrlRead($idComboBox[$i])
               MsgBox($MB_SYSTEMMODAL, "", "The combobox is currently displaying: " & $sComboRead, 0, $hGUI)
            EndIf
        Next
       Switch $iMsg
            Case $GUI_EVENT_CLOSE, $idClose
                ExitLoop
        EndSwitch
    WEnd

    GUIDelete($hGUI)
EndFunc   ;==>Example

 

Link to comment
Share on other sites

@Subz A nice solution, thank you! Though the close button isn't working and CPU usage caps out, I think maybe it's stuck in that while loop (the comboboxes are created successfully)

Sorry this is my first crack at AutoIt :>

Link to comment
Share on other sites

9 minutes ago, mBernin said:

Though the close button isn't working and CPU usage caps out

Are you sure you copied it correctly? I tested Subz's code by itself and it closes fine with both the X button and the close button, and it barely uses any CPU.

UHJvZmVzc2lvbmFsIENvbXB1dGVyZXI=

Link to comment
Share on other sites

@anthonyjr2 hmm, I made a couple of adjustments just to suit my needs (14 ComboBoxes) plus added "Local" to $iMsg since it was flagging as undeclared:

Func cmbBuild()
    Local $idComboBox[14], $iY = 10, $sComboRead = ""
    Local $hGUI = GUICreate("Max Level Selection", 300, 420)



    ; Create a combobox control.
    For $i = 0 To 13
        $idComboBox[$i] = GUICtrlCreateCombo("Item " & $i, 10, $iY, 185, 20)
        $iY += 25
    Next
    Local $idClose = GUICtrlCreateButton("Close", 210, 170, 85, 25)

    ; Add additional items to the combobox.
    For $i = 0 To 13
        GUICtrlSetData($idComboBox[$i], "1|2|3|4|5|6|7|8|9|10|11|12|13|14", "14" & $i)
    Next
    GUISetState()
    While 1
    Local $iMsg = GUIGetMsg()
        For $i = 0 To 13
            If $iMsg = $idComboBox[$i] Then
               $sComboRead = GUICtrlRead($idComboBox[$i])
               MsgBox($MB_SYSTEMMODAL, "", "The combobox is currently displaying: " & $sComboRead, 0, $hGUI)
            EndIf
        Next
       Switch $iMsg
            Case $GUI_EVENT_CLOSE, $idClose
                ExitLoop
        EndSwitch
    WEnd
    GUIDelete($hGUI)
EndFunc   ;==>cmbBuild()

 

Link to comment
Share on other sites

You're right, running it independently solves the problem. It seems to be linking itself in some way with the status of the main program's GUI - when I close the main program it closes this extra combobox handler cleanly. Strange effect, not sure where to start in solving it :shocked:

Thank you both for the replies though, given me a very nice baseline to work from! :)

Wish me luck, I'll most likely need it :lol:

Link to comment
Share on other sites

Do you have:

Opt("GUIOnEventMode", 1)

at the top of your program? This changes the GUI so that instead of constantly checking the GUI, it will pause the main GUI and execute whatever is in the called function. For example, if I have a main GUI with a button that opens a secondary one, it will pause the main GUI and open the secondary one, only resuming the main when the called function is finished.

UHJvZmVzc2lvbmFsIENvbXB1dGVyZXI=

Link to comment
Share on other sites

Yeah that's called on the program's 'main' script. Though by the time it reaches the function in question any number of things may have changed (it's a large program that I'm not the original author of - just adding a feature I thought of). The program's GUI is structured in tabs and subtabs - in theory the program's main script (could be called it's executable) should encapsulate all these tabs, but could it be possible that this GUIOnEventMode isn't applying to subtabs and their functions?

Also all of these GUI rows are produced within a function as well, so when running this extra combobox window we're essentially running functions within functions (not sure how far it goes :lol:)

Link to comment
Share on other sites

From the help file:

Quote

OnEvent functions are only called when Opt("GUIOnEventMode", 1) - when in this mode GUIGetMsg() is NOT used at all.

So you either should switch to GUIOnEventMode or GUIGetMsg in your script, here is code using GUIOnEventMode.

#include <GUIConstantsEx.au3>
#include <MsgBoxConstants.au3>
Global $hGUI, $hGUI_Close = False
Opt("GuiOnEventMode", 1)

_ComboBuild()

Func _ComboBuild()
    Local $idComboBox[14], $iY = 10
    $hGUI = GUICreate("Max Level Selection", 300, 420)
        GUISetOnEvent($GUI_EVENT_CLOSE, "_CloseGui", $hGUI)

    ; Create a combobox control.
    For $i = 0 To 13
        $idComboBox[$i] = GUICtrlCreateCombo("Item " & $i, 10, $iY, 185, 20)
        GUICtrlSetData($idComboBox[$i], "1|2|3|4|5|6|7|8|9|10|11|12|13|14", "14" & $i)
        GUICtrlSetOnEvent($idComboBox[$i], "_ComboRead")
        $iY += 25
    Next
    Local $idClose = GUICtrlCreateButton("Close", 210, 170, 85, 25)
    GUICtrlSetOnEvent($idClose, "_CloseGui")

    GUISetState()

    While $hGUI_Close = False
        Sleep(10)
    WEnd
    GUIDelete($hGUI)
EndFunc   ;==>_ComboBuild()

Func _ComboRead()
    $sComboRead = GUICtrlRead(@GUI_CtrlId)
    MsgBox(4096, "", "The combobox is currently displaying: " & $sComboRead, 0, $hGUI)
EndFunc

Func _CloseGui()
    $hGUI_Close = True
EndFunc   ;==>_CloseGui

 

Link to comment
Share on other sites

Still producing the same effect, though it's definitely on the program's end;

I ran the code independently as before and again it worked as intended. When I removed the GUIOnEventMode it reflected the behaviour of when it was being ran within the program, meaning somewhere along the line of the main program being initialized the scope of EventMode is being lost. As far as I can tell the structure of the program is this:

Main Script (EventMode set here) -> CreateMainGUI() -> CreateTabsWithinGUI() -> CreateSubtabs() -> CreateSubTabsUnderThoseSubTabs() -> CreateGUIElementsShownInScreenshot() -- GUICtrlSetOnEvent(-1, "_ComboBuild") --> FunctionWe'reCreating()

Or in simpler terms:

Main script, defining various global options etc (including EventMode) + initializing the GUI creation -> MainGUI() -> Tab1 -> Tab1a -> Tab1aa (Our function here)

 

I've tried placing

Opt("GuiOnEventMode", 1)

Further and further down the program structure but can't find the sweet spot. It's definitely the culprit of the issue, since the problem can be reproduced simply by removing this option from your latest code.

Link to comment
Share on other sites

Searching for it from the program's root folder in Windows explorer I've found there's a function (called "_ExtMsgBox") that temporarily switches EventMode off to use GuiGetMsg, switching it back on when the operation is finished. Though it isn't in the same .au3 file as where we're working, and the function isn't called anywhere in the .au3 file that I'm adding these changes either.

Might be important to note that these .au3 files containing functions (of which there's over a hundred) are all in a 'global includes' type script to allow their use anywhere in the program's code, meaning anywhere in the program I could call a function that uses GuiGetMsg, but right now it's not called in an area that should conflict with what I'm doing, plus it only temporarily uses its functionality. As far as the program is concerned before and after calling this function GuiOnEventMode should still be enabled globally

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