poila Posted May 13, 2014 Share Posted May 13, 2014 I was recently trying to fix a bug in a program I was handed over for about 3 weeks, but has left me stuck for a long while, and asking others in my office is not a viable option. I did a code review on my own and had doubts. So I came here to ask. What is the default scope of variables when declared within a function, if "Global" and "Local" are not used? Sample code: Func showSidebar($guiEvent, $refresh = False) If ($refresh) Then $previousFormName = Null; EndIf ; Do stuff... If $guiEvent <> Null Then If $guiEvent[0] == $sideButton_Y Then $previousFormName = Null $helpStatus = True ElseIf $guiEvent[0] == $sideButton_N Then $previousFormName = Null $helpStatus = False EndIf EndIf ; Do stuff again... ; Declaration of variables - does scope change? Global $currentForm, $previousFormName, $currentFormName $currentFormName = "" $currentForm = WinGetHandle("") ; Do more stuff... If $currentFormName <> $previousFormName Then ; Clear buttons EndIf ; Do even more stuff... $previousFormName = $currentFormName EndFunc This function would be called within a "While 1" loop when loading a GUI: While 1 $guiEvent = GUIGetMsg(1) showSidebar($guiEvent) Switch $guiEvent[0] Case $guiEvent[0] = $blahButton ; Do stuff... EndSwitch WEnd Thing is, when the application runs initially, the variables $currentForm, $previousFormName, and $currentFormName are marked as initially undeclared. But once the function runs, all of them are within Global scope of the application. If I changed the code such that $currentForm, $previousFormName, and $currentFormName are declared as Global at the beginning of the code, the function would not behave as intended. As for resetting variables declared Global within the function, is the following code considered okay for resetting variables? $currentForm = "" $previousFormName = "" $currentFormName = "" Link to comment Share on other sites More sharing options...
Moderators Melba23 Posted May 13, 2014 Moderators Share Posted May 13, 2014 (edited) poila, What is the default scope of variables when declared within a function, if "Global" and "Local" are not used?By default, AutoIt treats all variables declared outside functions as Global - even if they are declared as Local. All variables declared inside functions are Local, unless specifically declared as Global (which is regarded as poor practice).You need not respecify the scope when resetting simple variables as they retain their initial scope. But you do need to specify the scope when resetting arrays or you will get a syntax error as array declarations require a scope at all times.The Variables - using Global, Local and ByRef tutorial in the Wiki should be your next port of call. M23 Edited May 13, 2014 by Melba23 Typo 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 columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area Link to comment Share on other sites More sharing options...
poila Posted May 13, 2014 Author Share Posted May 13, 2014 poila, By default, AutoIt treats all variables declared outside functions as Global - even if they are declared as Local. All variables declared inside functions are Local, unless specifically declared as Global (which is regarded as poor practice). You need not respecify the scope when resetting simple variables as they retain their initial scope. But you do need to specify the scope when resetting arrays or you will get a syntax error as array declarations require a scope at all times. The Variables - using Global, Local and ByRef tutorial in the Wiki should be your next port of call. M23 That was mildly helpful. I did remember reading that tutorial awhile ago, had abit of trouble with applying scope concepts onto legacy code. I went to play around with my variables' scope just now. Now I tried rewriting the function like this: Func showSidebar($guiEvent, $refresh = False) Local Static $currentForm, $previousFormName, $currentFormName If ($refresh) Then If IsDeclared($previousFormName) Then $previousFormName = Null; EndIf EndIf ; Do stuff... If $guiEvent <> Null Then If $guiEvent[0] == $sideButton_Y Then If IsDeclared($previousFormName) Then $previousFormName = Null; EndIf $helpStatus = True ElseIf $guiEvent[0] == $sideButton_N Then If IsDeclared($previousFormName) Then $previousFormName = Null; EndIf $helpStatus = False EndIf EndIf ; Do stuff again... $currentFormName = Null $previousFormName = Null $currentForm = WinGetHandle("") ; Do more stuff... If $currentFormName <> $previousFormName Then ; Clear buttons EndIf ; Do even more stuff... $previousFormName = $currentFormName EndFunc Unfortunately, the thing is that another function needs to make use of the variable $currentFormName, which previously was in Global scope but because I tried and experimented with Local Static, obviously it seemed to be effective within function showSidebar(). IsDeclared() would cause the script to prevent compiling because it detected $previousFormName as undeclared, though after checking with previous programmer, he mentioned that the way the earlier code shown was written was intentional (hack-ish, I feel). Also, as I have shown in my earlier post, because showSidebar() is within a While 1 loop, this is called continually until the While loop is exited, meaning that the variable $previousFormName would be continually reset only if I were to use the newer way I wrote. (The older code I showed meant that though showSidebar() is called continually, $previousFormName is only modified once, so that the sidebar GUI won't reset infinitely.) $currentForm is used for grabbing GUI handles. Need to show additional code for possible troubleshooting - this occurred before resetting variables and after $previousFormName = $currentFormName: expandcollapse popup$pos = WinGetPos($currentForm) If $currentFormName <> "" Then If $currentFormName <> $previousFormName Then If $sideButton_Y <> Null Then GUICtrlSetState($sideButton_Y, $GUI_HIDE) EndIf If $sideButton_N <> Null Then GUICtrlSetState($sideButton_N, $GUI_HIDE) EndIf GUISwitch($currentForm) ; Show help button on main forms If $currentFormName == "myCurrentForm" Then If $helpStatus Then $sideButton_N = GUICtrlCreateLabel("?", $pos[2] - 44, 2, 20, 20) GUICtrlSetBkColor(-1, $GUI_BKCOLOR_TRANSPARENT) GUICtrlSetFont(-1, 14, 1000, 0, "Tahoma") GUICtrlSetColor(-1, 0xeeeeee) Else $sideButton_Y = GUICtrlCreateLabel("?", $pos[2] - 44, 2, 20, 20) GUICtrlSetBkColor(-1, $GUI_BKCOLOR_TRANSPARENT) GUICtrlSetFont(-1, 14, 1000, 0, "Tahoma") GUICtrlSetColor(-1, 0xeeeeee) EndIf EndIf EndIf EndIf If $helpStatus Then If $currentFormName <> "" Then WinMove($sidebarForm, "", $pos[0] + $pos[2], $pos[1], $const_HelpWidth, $pos[3]) If $currentFormName <> $previousFormName Then calledAnotherFunction() ; $currentArrayIndex is some Global array variable, don't think too much about it If $currentArrayIndex >= 0 Then ; Do something Else showInput("Done!") EndIf If $currentFormName == "myCurrentForm" Then ; Do something else EndIf GUISetState(@SW_SHOWNOACTIVATE, $sidebarForm) EndIf Else calledAnotherFunction() EndIf Else calledAnotherFunction() EndIf calledAnotherFunction is as follows: Func calledAnotherFunction() ; Hide stuff GUISetState(@SW_HIDE, $sidebarForm) EndFunc Link to comment Share on other sites More sharing options...
Moderators Melba23 Posted May 13, 2014 Moderators Share Posted May 13, 2014 poila, That was mildly helpfulAnd I find your reply mildly insulting. Unfortunately, the thing is that another function needs to make use of the variable $currentFormNameThen it needs to be Global in scope or passed to the other function as a parameter. M23 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 columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area Link to comment Share on other sites More sharing options...
jdelaney Posted May 13, 2014 Share Posted May 13, 2014 (edited) If you don't define the variable in a function as local, and there is already a global match (not case sensitive), the global will be overwritten. Gotta be careful of that... $i = 10 Function() ConsoleWrite($i & @CRLF) Func Function() $i = 30 EndFunc ^output is 30, not 10. $i = 10 Function() ConsoleWrite($i & @CRLF) Func Function() Local $i = 30 EndFunc ^output is 10 Edited May 13, 2014 by jdelaney IEbyXPATH-Grab IE DOM objects by XPATH IEscriptRecord-Makings of an IE script recorder ExcelFromXML-Create Excel docs without excel installed GetAllWindowControls-Output all control data on a given window. Link to comment Share on other sites More sharing options...
poila Posted May 13, 2014 Author Share Posted May 13, 2014 (edited) I pushed the variables $currentForm, $previousFormName, $currentFormName to the top of source code, declared as Global, outside the function. Additionally, I did not re-declare the variables in the function to Local. Earlier code of function "showSidebar", I refactored first part to this: If $previousFormName <> Null Then $previousFormName = Null EndIf $currentForm = Null $currentFormName = Null ; Get currently focused form $currentForm = WinGetHandle("") Sidebar GUI keeps flashing instead. Reason for this refactor was to overcome another issue I need to raise, which is randomly-missing/hiding GUI controls. Welp? Edited May 13, 2014 by poila Link to comment Share on other sites More sharing options...
guinness Posted May 13, 2014 Share Posted May 13, 2014 Too late to the party I see. Word of advice to poila, with global variables use a prefix of $g_ e.g. $g_sMyName, as it's easy to distinguish what is local and global.(not case sensitive)I really love case-sensitive languages e.g. C#. (100% serious comment) jchd 1 UDF List: _AdapterConnections() • _AlwaysRun() • _AppMon() • _AppMonEx() • _ArrayFilter/_ArrayReduce • _BinaryBin() • _CheckMsgBox() • _CmdLineRaw() • _ContextMenu() • _ConvertLHWebColor()/_ConvertSHWebColor() • _DesktopDimensions() • _DisplayPassword() • _DotNet_Load()/_DotNet_Unload() • _Fibonacci() • _FileCompare() • _FileCompareContents() • _FileNameByHandle() • _FilePrefix/SRE() • _FindInFile() • _GetBackgroundColor()/_SetBackgroundColor() • _GetConrolID() • _GetCtrlClass() • _GetDirectoryFormat() • _GetDriveMediaType() • _GetFilename()/_GetFilenameExt() • _GetHardwareID() • _GetIP() • _GetIP_Country() • _GetOSLanguage() • _GetSavedSource() • _GetStringSize() • _GetSystemPaths() • _GetURLImage() • _GIFImage() • _GoogleWeather() • _GUICtrlCreateGroup() • _GUICtrlListBox_CreateArray() • _GUICtrlListView_CreateArray() • _GUICtrlListView_SaveCSV() • _GUICtrlListView_SaveHTML() • _GUICtrlListView_SaveTxt() • _GUICtrlListView_SaveXML() • _GUICtrlMenu_Recent() • _GUICtrlMenu_SetItemImage() • _GUICtrlTreeView_CreateArray() • _GUIDisable() • _GUIImageList_SetIconFromHandle() • _GUIRegisterMsg() • _GUISetIcon() • _Icon_Clear()/_Icon_Set() • _IdleTime() • _InetGet() • _InetGetGUI() • _InetGetProgress() • _IPDetails() • _IsFileOlder() • _IsGUID() • _IsHex() • _IsPalindrome() • _IsRegKey() • _IsStringRegExp() • _IsSystemDrive() • _IsUPX() • _IsValidType() • _IsWebColor() • _Language() • _Log() • _MicrosoftInternetConnectivity() • _MSDNDataType() • _PathFull/GetRelative/Split() • _PathSplitEx() • _PrintFromArray() • _ProgressSetMarquee() • _ReDim() • _RockPaperScissors()/_RockPaperScissorsLizardSpock() • _ScrollingCredits • _SelfDelete() • _SelfRename() • _SelfUpdate() • _SendTo() • _ShellAll() • _ShellFile() • _ShellFolder() • _SingletonHWID() • _SingletonPID() • _Startup() • _StringCompact() • _StringIsValid() • _StringRegExpMetaCharacters() • _StringReplaceWholeWord() • _StringStripChars() • _Temperature() • _TrialPeriod() • _UKToUSDate()/_USToUKDate() • _WinAPI_Create_CTL_CODE() • _WinAPI_CreateGUID() • _WMIDateStringToDate()/_DateToWMIDateString() • Au3 script parsing • AutoIt Search • AutoIt3 Portable • AutoIt3WrapperToPragma • AutoItWinGetTitle()/AutoItWinSetTitle() • Coding • DirToHTML5 • FileInstallr • FileReadLastChars() • GeoIP database • GUI - Only Close Button • GUI Examples • GUICtrlDeleteImage() • GUICtrlGetBkColor() • GUICtrlGetStyle() • GUIEvents • GUIGetBkColor() • Int_Parse() & Int_TryParse() • IsISBN() • LockFile() • Mapping CtrlIDs • OOP in AutoIt • ParseHeadersToSciTE() • PasswordValid • PasteBin • Posts Per Day • PreExpand • Protect Globals • Queue() • Resource Update • ResourcesEx • SciTE Jump • Settings INI • SHELLHOOK • Shunting-Yard • Signature Creator • Stack() • Stopwatch() • StringAddLF()/StringStripLF() • StringEOLToCRLF() • VSCROLL • WM_COPYDATA • More Examples... Updated: 22/04/2018 Link to comment Share on other sites More sharing options...
Solution poila Posted May 14, 2014 Author Solution Share Posted May 14, 2014 (edited) Hi guinness, I have already renamed my variables according to the standards used in the Best Practices tutorial in the AutoIt Wiki. eg.) The handle $currentForm is now $g_hCurrentForm (global, handle). I dug deeper into the problem, and it turned out that the functions/variables that I mentioned in this thread so far aren't the cause of the problem. It turned out that 2 other global variables - declared uninitialized at the top of source code - were being used and modified within the function "showSidebar()" If $currentFormName <> "" Then ; If focused form on current iteration is different from previous iteration then initiate help sequence If $currentFormName <> $previousFormName Then ; Remove previous buttons If $sideButton_Y <> Null Then GUICtrlSetState($sideButton_Y, $GUI_HIDE) EndIf If $sideButton_N <> Null Then GUICtrlSetState($sideButton_N, $GUI_HIDE) EndIf EndIf EndIf I am thinking of extracting out the contents of whatever GUI controls and handles (like showing the contents of an array) somewhat similar in fashion to the WinListChildren() UDF shown in this link: '?do=embed' frameborder='0' data-embedContent>> Is there a similar function (native or UDF) used for displaying GUI handles into an array/list? Thanks in advance. EDIT: It turned out that the 2 global variables I mentioned in this particular reply are the culprit to my predicament. It was more of a fundamental code design flaw rather than the way the functions I shared here were used/written. Thanks again everyone. At the meantime, I might leave the question on how to display member GUI handles into an arraylist as an open question, but probably in another thread. Edited May 14, 2014 by poila Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now