tonedeaf Posted November 3, 2005 Posted November 3, 2005 Creating/Managing multiple forms in AutoIt3 Part 1When creating multiple forms in AutoIt, there is no provision for creating a custom FORM data type (like in Visual Basic) and there is no way to access the controls on the form using dot (.) notation. For eg. If you have a text box: txtYourName on a form: frmMain, Visual Basic allows you to access the text in the text box using the dot notation: sName = frmMain.txtYourNameAn obvious advantage of having a FORM data type is that its possible to have different forms with same control names. For eg. An OK button called cmdOK could be both on the main window and on any sub window (or child window) in the application.Moreover, this way ensures that only one variable remains global (the form variable is global even in Visual Basic) and the rest remain local (to be referenced using the form variable).With AutoIt, we have to think unique names for all the forms, and the controls on the forms. And all controls and form variables are declared Global.Managing multiple forms, may not be difficult for one or two forms. But with an application having many windows (like GUIBuilder by Cyberslug/LiveWire), the code can become complex to manage.So for AutoIt programmers facing this issue, Id like this topic to be a discussion for ways to manage multiple forms in AutoIt by implementing a FORM data type.Solution (Part - I)Ive seen code posts implementing complex data structures (like binary trees) using arrays in AutoIt.Since AutoIt doesnt support user defined data types, arrays are the closest (besides DllStructs) when it comes to defining custom data types.Implementing a FORM Datatype using Arrays:1) Design form using KODA FormDesigner (by Lookfar/Lazycat) or GUIBuilder (by Cyberslug/LiveWire) 2) Determine Form and Control variable names3) Convert the code generated by FormDesigner/GUIBuilder into an array mimicking a FORM data type.FormDesigner generated code:#include <GUIConstants.au3> $frmResetPassword = GUICreate("Reset Password", 318, 111, 390, 279) GUICtrlCreateLabel("New passsword:", 11, 13, 131, 13) $txtNewPwd = GUICtrlCreateInput("", 143, 11, 165, 23) GUICtrlCreateLabel("Confirm new passsword:", 11, 13, 131, 13) $txtConfirmPwd = GUICtrlCreateInput("", 143, 41, 165, 23) $cmdOK = GUICtrlCreateButton("OK", 152, 75, 75, 23) $cmdCancel = GUICtrlCreateButton("Cancel", 233, 75, 75, 23) GUISetState(@SW_SHOW) While 1 $msg = GuiGetMsg() Select Case $msg = $GUI_EVENT_CLOSE ExitLoop Case Else ;;;;;;; EndSelect Wend ExitConverted code representing a FORM data type using an array:expandcollapse popup#include <GUIConstants.au3> Global $afrmResetPassword CreateForm_frmResetPassword($afrmResetPassword) GUISetState(@SW_SHOW, $afrmResetPassword[0][1]) While 1 $msg = GuiGetMsg() Select Case $msg = $GUI_EVENT_CLOSE ExitLoop Case Else ;;;;;;; EndSelect Wend Exit Func CreateForm_frmResetPassword(ByRef $afrmNew) Dim $afrmNew[5][2] $afrmNew[0][0] = "$frmResetPassword" $afrmNew[0][1] = GUICreate("Reset Password", 318, 111, 390, 279) GUICtrlCreateLabel("New passsword:", 11, 13, 131, 13) $afrmNew[1][0] = "$txtNewPwd" $afrmNew[1][1] = GUICtrlCreateInput("", 143, 11, 165, 23) GUICtrlCreateLabel("Confirm new passsword:", 11, 44, 131, 13) $afrmNew[2][0] = "$txtConfirmPwd" $afrmNew[2][1] = GUICtrlCreateInput("", 143, 41, 165, 23) $afrmNew[3][0] = "$cmdOK" $afrmNew[3][1] = GUICtrlCreateButton("OK", 152, 75, 75, 23) $afrmNew[4][0] = "$cmdCancel" $afrmNew[4][1] = GUICtrlCreateButton("Cancel", 233, 75, 75, 23) EndFuncThe FORM array[][0] stores the text representation of the controls internal name and array[][1] stores the handle returned by the _GuiCtrlCreate function for the control. This FORM array[][] also stores the form handle which is always stored as the first array elementArray[0][0] , stores the form internal nameArray[0][1], stores the form handle.Notice that for controls we do not want to manipulate in code, we skip storing them in the FORM array.Whenever we want to refer to the form handle we, refer to $afrmResetPassword[0][1] as the form variable is always stored as the first element in the array. This would get a form up and running, but this approach is not useful for referring controls on the form as fixing array positions for controls would make the code very difficult to read.Eg. GUICtrlSetData($afrmResetPassword[1][1], "!1234ABCD#$") would not be intitutive enough to imply that were assigning a value to $txtNewPwd.So we write another function to take advantage of control variable names stored in array[][0] elements.The function _GetCtrl() takes the following parameters:Parameter 1: Text representation of the control name Parameter 2: FORM array to search the control in.Return Value:Success: Returns the handle for the controlFailure: If the control was not found in the FORM array, displays a Critical error message box and ends program.Func _GetCtrl($sCtrlName, $afrmArray) For $i = 0 to UBound($afrmArray, 1) - 1 If $afrmArray[$i][0] = $sCtrlName Then Return $afrmArray[$i][1] EndIf Next ; Error Handler If $i > UBound($afrmArray, 1) - 1 Then Application_ErrorHandler("Control reference invalid ", _ "Control Name: " & $sCtrlName & @CRLF & _ "Form Name: " & $afrmArray[0][0], "Fatal") SetError(1) EndIf EndFuncApplication_ErrorHandler() function (Creates the Message Box)Func Application_ErrorHandler($sError, $sSolution, $sImpact) If $sImpact = "Non-Fatal" Then MsgBox(8256, "Reset Password", $sError & @CRLF & @CRLF & $sSolution) ElseIf $sImpact = "Fatal" Then MsgBox(8208, "Reset Password", $sError & @CRLF & @CRLF & $sSolution) Exit EndIf EndFuncSo, if we now assign a value to $txtNewPwd, the new syntax would look like:GUICtrlSetData(_GetCtrl("$txtNewPwd, $afrmResetPassword), "!1234ABCD#$")Although the syntax is more lengthy for a simple assignment, the benefits of this approach begin to pay off as we start coding multiple forms.We make the Cancel button functional by using this approach:While 1 $msg = GuiGetMsg() Select Case $msg = $GUI_EVENT_CLOSE ExitLoop Case $msg = _GetCtrl("$cmdCancel", $afrmResetPassword) ExitLoop Case Else ;;;;;;; EndSelect WendThe finished code would look like:expandcollapse popup#include <GUIConstants.au3> Global $afrmResetPassword CreateForm_frmResetPassword($afrmResetPassword) GUISetState(@SW_SHOW, $afrmResetPassword[0][1]) While 1 $msg = GuiGetMsg() Select Case $msg = $GUI_EVENT_CLOSE ExitLoop Case $msg = _GetCtrl("$cmdCancel", $afrmResetPassword) ExitLoop Case Else ;;;;;;; EndSelect Wend Exit Func _GetCtrl($sCtrlName, $afrmArray) For $i = 0 to UBound($afrmArray, 1) - 1 If $afrmArray[$i][0] = $sCtrlName Then Return $afrmArray[$i][1] EndIf Next ; Error Handler If $i > UBound($afrmArray, 1) - 1 Then Application_ErrorHandler("Control reference invalid ", _ "Control Name: " & $sCtrlName & @CRLF & _ "Form Name: " & $afrmArray[0][0], "Fatal") SetError(1) EndIf EndFunc ; Application wide central message handler. ; Displays an error msg and exits the application if the error is fatal. Func Application_ErrorHandler($sError, $sSolution, $sImpact) If $sImpact = "Non-Fatal" Then MsgBox(8256, "Reset Password", $sError & @CRLF & @CRLF & $sSolution) ElseIf $sImpact = "Fatal" Then MsgBox(8208, "Reset Password", $sError & @CRLF & @CRLF & $sSolution) Exit EndIf EndFunc Func CreateForm_frmResetPassword(ByRef $afrmNew) Dim $afrmNew[5][2] $afrmNew[0][0] = "$frmResetPassword" $afrmNew[0][1] = GUICreate("Reset Password", 318, 111, 390, 279) GUICtrlCreateLabel("New passsword:", 11, 13, 131, 13) $afrmNew[1][0] = "$txtNewPwd" $afrmNew[1][1] = GUICtrlCreateInput("", 143, 11, 165, 23) GUICtrlCreateLabel("Confirm new passsword:", 11, 44, 131, 13) $afrmNew[2][0] = "$txtConfirmPwd" $afrmNew[2][1] = GUICtrlCreateInput("", 143, 41, 165, 23) $afrmNew[3][0] = "$cmdOK" $afrmNew[3][1] = GUICtrlCreateButton("OK", 152, 75, 75, 23) $afrmNew[4][0] = "$cmdCancel" $afrmNew[4][1] = GUICtrlCreateButton("Cancel", 233, 75, 75, 23) EndFuncIn the next topic Ill discuss ways to separate the code for multiple forms in separate .au3 files and trapping control events.Any comments/suggestions are welcome.
w0uter Posted November 3, 2005 Posted November 3, 2005 why would you want to make something so complex ? what is wrong with a normal variable (like that comes uit GUIbuilder) My UDF's:;mem stuff_Mem;ftp stuff_FTP ( OLD );inet stuff_INetGetSource ( OLD )_INetGetImage _INetBrowse ( Collection )_EncodeUrl_NetStat_Google;random stuff_iPixelSearch_DiceRoll
SlimShady Posted November 3, 2005 Posted November 3, 2005 why would you want to make something so complex ?what is wrong with a normal variable (like that comes uit GUIbuilder)maybe you should read his post.
w0uter Posted November 3, 2005 Posted November 3, 2005 maby i did. My UDF's:;mem stuff_Mem;ftp stuff_FTP ( OLD );inet stuff_INetGetSource ( OLD )_INetGetImage _INetBrowse ( Collection )_EncodeUrl_NetStat_Google;random stuff_iPixelSearch_DiceRoll
tonedeaf Posted November 4, 2005 Author Posted November 4, 2005 @w0uterwhy would you want to make something so complex ?what is wrong with a normal variable (like that comes uit GUIbuilder)Its not really complex, but its more involved than using the normal methords.The problem with normal GUI creation methords is that after a while it becomes increasing difficult to manage multiple forms. As soon as you exceed two-three forms in your application and the no. of controls increase, it becomes more than apparent that you need some way of implementing a data structure containing the controls for a form.It may not be useful for a program with only one/two forms. But I'm targeting AutoIt programs which can have any number of forms and it would not be complex to manage them.
w0uter Posted November 4, 2005 Posted November 4, 2005 okey, thanks. My UDF's:;mem stuff_Mem;ftp stuff_FTP ( OLD );inet stuff_INetGetSource ( OLD )_INetGetImage _INetBrowse ( Collection )_EncodeUrl_NetStat_Google;random stuff_iPixelSearch_DiceRoll
DiskAI Posted November 10, 2005 Posted November 10, 2005 couple of Q's 1. how to reuse the same gui for multiple instance eg. multiple download window, separate personal chat window etc. 2. how to make the gui skinnable (covers all the forms created) i think
Skysnake Posted September 9, 2014 Posted September 9, 2014 This is magic. What I am wondering is why there is so little activity on this thread. I think this should be included as an advanced tutorial topic. Are there other Help topics dealing with more than basics? And showing how to split a project into multiple include files? This deals with so many different concepts all in one place. Thank you. '?do=embed' frameborder='0' data-embedContent>> '?do=embed' frameborder='0' data-embedContent>> Skysnake Why is the snake in the sky?
Moderators JLogan3o13 Posted September 9, 2014 Moderators Posted September 9, 2014 skysnake, why would you resurrect a 9 year old thread rather than starting a new one?! The language has grown just a touch since 2005; what worked then may not do so now. "Profanity is the last vestige of the feeble mind. For the man who cannot express himself forcibly through intellect must do so through shock and awe" - Spencer W. Kimball How to get your question answered on this forum!
Bert Posted September 9, 2014 Posted September 9, 2014 (edited) This is magic. What I am wondering is why there is so little activity on this thread. Edited September 9, 2014 by DarthCookieMonster The Vollatran project My blog: http://www.vollysinterestingshit.com/
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