S0mbre Posted November 12, 2010 Share Posted November 12, 2010 I implement 2 windows in my script: the main form ($gui) and a modal dialog ($gui2). To handle message processing, I use the advanced function GUIGetMsg(1) (as described in the Wiki article on managing multiple GUIs). $gui2 is evoked by pressing a button on $gui. $gui is then disabled and the while loop should go through $gui2 until the 'close' message is received. Then $gui2 is deleted and $gui is re-enabled and activated. Everything, as you see, 'as the doctor prescribes'.Everything was alright until I added a button to $gui2 (the dialog). When I did that, the message hadling routine continually received messages from this button even when $gui2 is not yet created! Can anyone explain to me how's that?Here's my code.Main form creation func:expandcollapse popupFunc GUI_Main() $gui = GUICreate("Перенос файлов", 400, 330) $lab_fromdir = GUICtrlCreateLabel("ИЗ (папка):", 10, 5, 380) GUICtrlSetColor(-1, 0x0000ff) $edit_fromdir = GUICtrlCreateEdit(@DesktopDir, 10, 20, 355, 20, BitOR($ES_AUTOVSCROLL, $ES_AUTOHSCROLL)) $btn_browse_fromdir = GUICtrlCreateButton("...", 370, 20, 20, 20) $lab_todir = GUICtrlCreateLabel("В (папка):", 10, 50, 380) GUICtrlSetColor(-1, 0x0000ff) $edit_todir = GUICtrlCreateEdit(@DesktopDir, 10, 65, 355, 20, BitOR($ES_AUTOVSCROLL, $ES_AUTOHSCROLL)) $btn_browse_todir = GUICtrlCreateButton("...", 370, 65, 20, 20) $lab_fname_mask = GUICtrlCreateLabel("Имя файла содержит (если любой файл - оставить пустым):", 10, 100, 380) GUICtrlSetColor(-1, 0x751E29) $edit_fname_mask = GUICtrlCreateEdit("", 10, 115, 380, 20, BitOR($ES_AUTOVSCROLL, $ES_AUTOHSCROLL)) GUICtrlSetBkColor(-1, 0xffff00) $lab_fext_mask = GUICtrlCreateLabel("Расширение файла, напр. ""mp3"" (если любое - оставить пустым):", 10, 140, 380) GUICtrlSetColor(-1, 0x751E29) $edit_fext_mask = GUICtrlCreateEdit("jpg", 10, 155, 380, 20, BitOR($ES_AUTOVSCROLL, $ES_AUTOHSCROLL)) GUICtrlSetBkColor(-1, 0xffff00) $btn_options = GUICtrlCreateButton("Опции...", 10, 180, 80, 25) $btn_start = GUICtrlCreateButton("Старт", 150, 235, 100, 30) $lab_prog = GUICtrlCreateLabel("Прогресс выполнения:", 10, 275, 140) GUICtrlSetColor(-1, 0xff0000) $lab_prog1 = GUICtrlCreateLabel("...", 150, 275, 240) GUICtrlSetColor(-1, 0x246B15) $pr_files = GUICtrlCreateProgress(10, 295, 380, 20, $PBS_SMOOTH) GUICtrlSetBkColor(-1, 0) GUICtrlSetColor(-1, 0x00ff00) GUICtrlSetData(-1, 0) GUICtrlSetState(-1, $GUI_SHOW) GUISetState() EndFuncThe dialog func:Func GUI_Options() $gui2 = GUICreate("Опции", 400, 250, -1, -1, $DS_MODALFRAME) $btn_set = GUICtrlCreateButton("Сохранить", 10, 180, 80, 25) ; THAT'S THE BUTTON!!! $cb_movefiles = GUICtrlCreateCheckbox("Перенос файлов (если ВЫКЛ, будут копироваться)", 10, 10, 290, 20) GUICtrlSetState(-1, $g_b_movefiles) $cb_overwrite = GUICtrlCreateCheckbox("Перезапись файлов (если ВЫКЛ, будут переименовываться)", 10, 30, 330, 20) GUICtrlSetState(-1, $g_b_overwrite) GUISetState(@SW_SHOW) EndFuncThe code:expandcollapse popupGUI_Main() While True $msg = GUIGetMsg(1) ; ADVANCED MSG HANDLING switch $msg[1] Case $gui ; IF MAIN FORM msgbox(0, "", "FORM 1") switch $msg[0] Case $btn_browse_fromdir ; Case $btn_browse_todir ; Case $btn_options GUISetState(@SW_DISABLE, $gui) ; DISABLE THIS FORM GUI_Options() ; EVOKE DIALOG Case $btn_start ; Case $GUI_EVENT_CLOSE ExitLoop EndSwitch Case $gui2 ; DIALOG FORM msgbox(0, "", "FORM 2") switch $msg[0] Case $btn_set msgbox(0, "", "Message sent by BUTTON!") ; THIS MESSAGE KEEPS SHOWING UP!!! Case $GUI_EVENT_CLOSE GUIDelete($gui2) ; DELETE THIS FORM GUISetState(@SW_ENABLE, $gui) ; RE-ENABLE MAIN FORM WinActivate($gui) ; ACTIVATE MAIN FORM EndSwitch EndSwitch WEndThe script continually walks into Case $btn_set EVEN WHEN $gui2 IS YET TO BE CREATED! Link to comment Share on other sites More sharing options...
Tvern Posted November 12, 2010 Share Posted November 12, 2010 (edited) If there is no message, $msg[1] will be 0x00000000 and because you have not created the GUI yet, $gui2 will be 0. A similar match then occurs for the non existant button. To stop this you could tell the script to continue if $msg[1] = 0 like this: (line 4 and 5) While True $msg = GUIGetMsg(1) ; ADVANCED MSG HANDLING switch $msg[1] Case 0 ContinueLoop ;don't do anything if there is no message. Case $gui ; IF MAIN FORM msgbox(0, "", "FORM 1") switch $msg[0] Case $btn_browse_fromdir ; Case $btn_browse_todir ; Case $btn_options GUISetState(@SW_DISABLE, $gui) ; DISABLE THIS FORM GUI_Options() ; EVOKE DIALOG Case $btn_start ; Case $GUI_EVENT_CLOSE ExitLoop EndSwitch Case $gui2 ; DIALOG FORM msgbox(0, "", "FORM 2") switch $msg[0] Case $btn_set msgbox(0, "", "Message sent by BUTTON!") ; THIS MESSAGE KEEPS SHOWING UP!!! Case $GUI_EVENT_CLOSE GUIDelete($gui2) ; DELETE THIS FORM GUISetState(@SW_ENABLE, $gui) ; RE-ENABLE MAIN FORM WinActivate($gui) ; ACTIVATE MAIN FORM EndSwitch EndSwitch WEnd Edit: removed my debug line. Edited November 12, 2010 by Tvern Link to comment Share on other sites More sharing options...
Spiff59 Posted November 12, 2010 Share Posted November 12, 2010 My read on this is... You had to pre-declare the $gui2 and $btn_set variables as a globals at the top of your source to avoid a compile error. So, prior to the creation of your child GUI, where $gui2 and $btn_set are assigned control ID's, they have a value of 0. GUIGetMsg() returns a value of zero when no events have occured, so it mistakenly trips both your case tests for $gui2 and $btn_set. Some options might be: Put your switch statements inside "If Msg <> 0 Then" tests. Use seperate GetMsg() control loops for each GUI. Link to comment Share on other sites More sharing options...
S0mbre Posted November 12, 2010 Author Share Posted November 12, 2010 I did declare all the GUI variables ()as Global) before running the functions. Actually, I've found the solution to this problem by merely changing lines like Case $gui_dlg in the switch statement to the explicit Case $msg[1] = $gui_dlg I still don't get it why the first variant caused the problem... Link to comment Share on other sites More sharing options...
Tvern Posted November 12, 2010 Share Posted November 12, 2010 Read both our posts again. Spiff assumed you did declare the variables as global, simply because that's the only way the script will run. The problem is that those variables are empty untill you put something in it and this evaluate as 0. When there is no message GuiGetMsg returns 0x00000000, which also evaluates as 0. You are then evaluating 0 = 0, which ofcoarse is True, meaning the cose associated with a button press is executed. Your workaraound will work, but it creates confusing code and I think you are misunderstanding the way a Switch statement works. (no time to explain right now, maibe some other time) The proper way to do it is by either: Skipping the loop if there is no message, as shown in the previous examples. (mine should work with a simple cut and paste). Declaring the Global variables with an initial value that will never match the value of GUIGetMsg. (I think -1 would work for instance) Link to comment Share on other sites More sharing options...
Moderators Melba23 Posted November 12, 2010 Moderators Share Posted November 12, 2010 S0mbre,Reading the Managing Multiple GUIs tutorial in the Wiki might prove useful. 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...
S0mbre Posted November 17, 2010 Author Share Posted November 17, 2010 Read both our posts again. Spiff assumed you did declare the variables as global, simply because that's the only way the script will run.The problem is that those variables are empty untill you put something in it and this evaluate as 0.When there is no message GuiGetMsg returns 0x00000000, which also evaluates as 0.You are then evaluating 0 = 0, which ofcoarse is True, meaning the cose associated with a button press is executed.Your workaraound will work, but it creates confusing code and I think you are misunderstanding the way a Switch statement works. (no time to explain right now, maibe some other time)The proper way to do it is by either:Skipping the loop if there is no message, as shown in the previous examples. (mine should work with a simple cut and paste).Declaring the Global variables with an initial value that will never match the value of GUIGetMsg. (I think -1 would work for instance)Actually, I did insert the "Case 0 ContinueLoop" statement and it worked fine, thank you! To reply to your conjecture that I don't understand the way Switch works, I am bound to return a negative answer: I do know that. I just didn't know that GuiGetMsg returns zero when there's no message. Link to comment Share on other sites More sharing options...
Tvern Posted November 17, 2010 Share Posted November 17, 2010 To reply to your conjecture that I don't understand the way Switch works, I am bound to return a negative answer: I do know that. I just didn't know that GuiGetMsg returns zero when there's no message. Sorry about that, I was in a bit of a hurry when I wrote it. What I meant was more along the lines of: Yes your solution works, but do you know why? When you write it out it gets a lot more complicated than it has to be and as such I would advise a different solution. (like the Case 0 solution) I attempted to write out the steps of your solution to clarify why it works, but found it to be unconstructive at the time. Here's another try: I will probably be corrected on parts of this, but this is sort of what happens. #region in case of no message returned: Switch $msg[1] Case $msg[1] = $gui_dlg EndSwitch Switch 0x00000000 ;There is no handle Case 0x00000000 = 0 ;There is no value in $gui_dlg EndSwitch Switch False ;The empty handle translates to False Case True ;The empty handle is equal to the empty $gui_dlg EndSwitch ;obviously true isn't false, so the code doesn't run #endregion #region in case of a message returned by $gui_dlg: Switch 0x000F1D02 Case 0x000F1D02 = 0x000F1D02 EndSwitch Switch True ;the handle is something, so in a comparison to a boolean it will equate to True Case True ;The expression is True EndSwitch ;obviously True is True, so the code runs #endregion Link to comment Share on other sites More sharing options...
S0mbre Posted November 18, 2010 Author Share Posted November 18, 2010 Sorry about that, I was in a bit of a hurry when I wrote it. What I meant was more along the lines of: Yes your solution works, but do you know why? When you write it out it gets a lot more complicated than it has to be and as such I would advise a different solution. (like the Case 0 solution) I attempted to write out the steps of your solution to clarify why it works, but found it to be unconstructive at the time. Here's another try: I will probably be corrected on parts of this, but this is sort of what happens. #region in case of no message returned: Switch $msg[1] Case $msg[1] = $gui_dlg EndSwitch Switch 0x00000000 ;There is no handle Case 0x00000000 = 0 ;There is no value in $gui_dlg EndSwitch Switch False ;The empty handle translates to False Case True ;The empty handle is equal to the empty $gui_dlg EndSwitch ;obviously true isn't false, so the code doesn't run #endregion #region in case of a message returned by $gui_dlg: Switch 0x000F1D02 Case 0x000F1D02 = 0x000F1D02 EndSwitch Switch True ;the handle is something, so in a comparison to a boolean it will equate to True Case True ;The expression is True EndSwitch ;obviously True is True, so the code runs #endregion Thank you for this detailed reply. I think I understand now 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