idbirch Posted February 27, 2009 Share Posted February 27, 2009 Hello all, I hope someone can kindly point out what I've done wrong to get my script into this mess. I'm working on a large project which consists of a main GUI which spawns further GUIs for performing various tasks. The main GUI sits in a GuiGetMsg() while loop but I have serious problems when I try and launch a secondary GUI which uses WM_NOTIFY. The notify event works fine but when I try and delete the secondary GUI, the whole thing crashes with a "memory could not be read" error. I'm fairly sure I've broken some cardinal rule of programming but if someone could point it out, I'd be most greatful. Here's an example script which reproduces the error: expandcollapse popup#include <ButtonConstants.au3> #include <GUIConstantsEx.au3> #include <GuiListView.au3> #include <WindowsConstants.au3> #include <Array.au3> Global $ListView_QueryResults, $Form_MuliResults, $SelectedRow Global $QueryHits = 3 Global $arrQueryResults[3][3] $arrQueryResults[0][0] = "Computer1" $arrQueryResults[0][1] = "1111" $arrQueryResults[0][2] = "07/01/2009 12:24" $arrQueryResults[1][0] = "Computer1" $arrQueryResults[1][1] = "2222" $arrQueryResults[1][2] = "26/02/2009 08:20" $arrQueryResults[2][0] = "Computer1" $arrQueryResults[2][1] = "3333" $arrQueryResults[2][2] = "26/02/2009 08:24" _ArrayDisplay ( $arrQueryResults, "Dummy return values from an SQL query" ) #Region ### START Koda GUI section ### Form= $Form1 = GUICreate("GUI 1", 237, 175, 192, 124) $Button1 = GUICtrlCreateButton("Button1", 72, 72, 75, 25, 0) GUISetState(@SW_SHOW) #EndRegion ### END Koda GUI section ### While 1 $nMsgMainGUI = GUIGetMsg(1) ;This is the main loop for the master GUI, lots of child windows are created for various other functions ;but most just create their own GUIGetMsg() loop and break out of that once finished, returning control to ;this loop. The problem function is one that requires use of WM_NOTIFY, this crashes the whole script :( Select Case $nMsgMainGUI[0] = $GUI_EVENT_CLOSE and $nMsgMainGUI[1] = $Form1 Exit Case $nMsgMainGUI[0] = $Button1 and $nMsgMainGUI[1] = $Form1 _Function1() EndSelect WEnd Func _Function1() If $QueryHits > 1 Then #Region ### START Koda GUI section ### Form= $Form_MuliResults = GUICreate("Multiple results", 419, 289, 288, 270) $ListView_QueryResults = _GUICtrlListView_Create($Form_MuliResults, "Asset No|Machine ID|Last Scan Time", 16, 64, 386, 174 ) _GUICtrlListView_SetExtendedListViewStyle($ListView_QueryResults, BitOR($LVS_EX_GRIDLINES, $LVS_EX_FULLROWSELECT, $LVS_EX_SUBITEMIMAGES)) _GUICtrlListView_SetColumnWidth($ListView_QueryResults, 0, 100) _GUICtrlListView_SetColumnWidth($ListView_QueryResults, 1, 100) _GUICtrlListView_SetColumnWidth($ListView_QueryResults, 2, 186) GUICtrlCreateLabel("There is more than 1 result for your query, double click to choose one", 16, 16, 360, 17) _GUICtrlListView_AddArray($ListView_QueryResults, $arrQueryResults ) GUISwitch ($Form_MuliResults) GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY") GUISetState(@SW_SHOW) #EndRegion ### END Koda GUI section ### EndIf EndFunc Func WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam) Local $tNMHDR, $hWndFrom, $iCode $tNMHDR = DllStructCreate($tagNMHDR, $ilParam) $hWndFrom = DllStructGetData($tNMHDR, "hWndFrom") $iCode = DllStructGetData($tNMHDR, "Code") $iIDFrom = DllStructGetData($tNMHDR, "IDFrom") Switch $hWndFrom Case $ListView_QueryResults Switch $iCode Case $NM_DBLCLK $tInfo = DllStructCreate($tagNMITEMACTIVATE, $ilParam) $x = DllStructGetData($tInfo, "Index") $SelectedRow = $x ConsoleWrite ("User double clicked item " & $x & @CRLF) _Function2() EndSwitch EndSwitch Return $GUI_RUNDEFMSG EndFunc Func _Function2() GUIRegisterMsg($WM_NOTIFY, '') ;Unregister the WMNOTIFY function GUIDelete ( $Form_MuliResults ) ;Delete the multi results window as it is no longer needed GuiSwitch ( $Form1 ) ;Switch control back to main window $MachineIDtoUse = $arrQueryResults[$SelectedRow][1];Grab ID number of machine that was double clicked by user $StrScanTime = $arrQueryResults[$SelectedRow][2] ;Grab scan time of machine that was double clicked by user ;Run another SQL query using the machine ID and scan time of the machine that was double clicked by user GUISetState ( @SW_ENABLE, $Form1 ) EndFunc Link to comment Share on other sites More sharing options...
Moderators Melba23 Posted February 27, 2009 Moderators Share Posted February 27, 2009 idbirch,I am not sure about "cardinal rules", but I can see a problem in your script.From the ever helpful (because that it why it is there!) Help file on GUIRegisterMessage: "Warning: ... the return to the system should be as fast as possible !!!".You are running another function inside the WM_Notify function, which I do not think counts as "as fast as possible"! Try using a boolean flag to indicate the click within the WM_Notify function, then look for that flag in your While...WEnd loop and run your other function. I have done that successfully in many scripts.Here is a modified version of your script which does not crash when I run it (changed lines are marked by : <<<<<<<<<):expandcollapse popup#include <ButtonConstants.au3> #include <GUIConstantsEx.au3> #include <GuiListView.au3> #include <WindowsConstants.au3> #include <Array.au3> Global $ListView_QueryResults, $Form_MuliResults, $SelectedRow, $fClicked = False; <<<<<<<<<<<<<<<<<<<<<<<<<< Global $QueryHits = 3 Global $arrQueryResults[3][3] $arrQueryResults[0][0] = "Computer1" $arrQueryResults[0][1] = "1111" $arrQueryResults[0][2] = "07/01/2009 12:24" $arrQueryResults[1][0] = "Computer1" $arrQueryResults[1][1] = "2222" $arrQueryResults[1][2] = "26/02/2009 08:20" $arrQueryResults[2][0] = "Computer1" $arrQueryResults[2][1] = "3333" $arrQueryResults[2][2] = "26/02/2009 08:24" _ArrayDisplay ( $arrQueryResults, "Dummy return values from an SQL query" ) #Region ### START Koda GUI section ### Form= $Form1 = GUICreate("GUI 1", 237, 175, 192, 124) $Button1 = GUICtrlCreateButton("Button1", 72, 72, 75, 25, 0) GUISetState(@SW_SHOW) #EndRegion ### END Koda GUI section ### While 1 $nMsgMainGUI = GUIGetMsg(1) ;This is the main loop for the master GUI, lots of child windows are created for various other functions ;but most just create their own GUIGetMsg() loop and break out of that once finished, returning control to ;this loop. The problem function is one that requires use of WM_NOTIFY, this crashes the whole script :( Select Case $nMsgMainGUI[0] = $GUI_EVENT_CLOSE and $nMsgMainGUI[1] = $Form1 Exit Case $nMsgMainGUI[0] = $Button1 and $nMsgMainGUI[1] = $Form1 _Function1() EndSelect If $fClicked = True Then _Function2() ; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< WEnd Func _Function1() If $QueryHits > 1 Then #Region ### START Koda GUI section ### Form= $Form_MuliResults = GUICreate("Multiple results", 419, 289, 288, 270) $ListView_QueryResults = _GUICtrlListView_Create($Form_MuliResults, "Asset No|Machine ID|Last Scan Time", 16, 64, 386, 174 ) _GUICtrlListView_SetExtendedListViewStyle($ListView_QueryResults, BitOR($LVS_EX_GRIDLINES, $LVS_EX_FULLROWSELECT, $LVS_EX_SUBITEMIMAGES)) _GUICtrlListView_SetColumnWidth($ListView_QueryResults, 0, 100) _GUICtrlListView_SetColumnWidth($ListView_QueryResults, 1, 100) _GUICtrlListView_SetColumnWidth($ListView_QueryResults, 2, 186) GUICtrlCreateLabel("There is more than 1 result for your query, double click to choose one", 16, 16, 360, 17) _GUICtrlListView_AddArray($ListView_QueryResults, $arrQueryResults ) GUISwitch ($Form_MuliResults) $fClicked = False ; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY") GUISetState(@SW_SHOW) #EndRegion ### END Koda GUI section ### EndIf EndFunc Func WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam) Local $tNMHDR, $hWndFrom, $iCode $tNMHDR = DllStructCreate($tagNMHDR, $ilParam) $hWndFrom = DllStructGetData($tNMHDR, "hWndFrom") $iCode = DllStructGetData($tNMHDR, "Code") $iIDFrom = DllStructGetData($tNMHDR, "IDFrom") Switch $hWndFrom Case $ListView_QueryResults Switch $iCode Case $NM_DBLCLK $tInfo = DllStructCreate($tagNMITEMACTIVATE, $ilParam) $x = DllStructGetData($tInfo, "Index") $SelectedRow = $x ConsoleWrite ("User double clicked item " & $x & @CRLF) ;_Function2() ; <<<<<<<<<<<<<<<<<<<<<<<< $fClicked = True ; <<<<<<<<<<<<<<<<<<<<<<< EndSwitch EndSwitch Return $GUI_RUNDEFMSG EndFunc Func _Function2() $fClicked = False ; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<< GUIRegisterMsg($WM_NOTIFY, '') ;Unregister the WMNOTIFY function GUIDelete ( $Form_MuliResults ) ;Delete the multi results window as it is no longer needed GuiSwitch ( $Form1 ) ;Switch control back to main window $MachineIDtoUse = $arrQueryResults[$SelectedRow][1];Grab ID number of machine that was double clicked by user $StrScanTime = $arrQueryResults[$SelectedRow][2] ;Grab scan time of machine that was double clicked by user ;Run another SQL query using the machine ID and scan time of the machine that was double clicked by user GUISetState ( @SW_ENABLE, $Form1 ) EndFunc 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...
idbirch Posted February 27, 2009 Author Share Posted February 27, 2009 M23, you are a prince among men I thank you. I did read the GUIRegisterMsg portion of the help file but didn't appreciate that then length of time Function2 took to run was contravening the undefined time limit so thanks very much for pointing it out and for getting me to use boolean for the first time in over 10,000 lines of code! I incorporated the method you demonstrated in my project and it works brilliantly, thanks again for your help. 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