AndyS01 Posted October 22, 2010 Share Posted October 22, 2010 I have a script that creates a file menu and a ListView box with several items and when I click on some of the items, the handler registered to the menu items inadvertantly gets called! Here is my test code: expandcollapse popup#NoTrayIcon #include <GUIConstantsEx.au3> #include <GuiListView.au3> Opt("GUIOnEventMode", 1) ; Change to OnEvent mode Opt('MustDeclareVars', 1) Opt("GUIEventOptions", 1) ;0=default, 1=just notification, 2=GuiCtrlRead tab index Global $hWnd_MainWin Global $iListView_ID Global $iListView_hWnd Global $sNamePWDSep = Opt("GUIDataSeparatorChar") _Main() exit (0) ;;;;;;;;;;;;;;;;;;;;;;;;;; ; _Main() - Main function ;;;;;;;;;;;;;;;;;;;;;;;;;; Func _Main() Local $row, $aItem, $iIndex, $HeaderCols, $aMasterList[7] $hWnd_MainWin = GUICreate("Test", 340 - 16, 300 - 16) ; Create the Main GUI create_menus() $iListView_ID = GUICtrlCreateListView("", 10, 10, 300, 200) $iListView_hWnd = GUICtrlGetHandle($iListView_ID) _GUICtrlListView_AddColumn($iListView_hWnd, "F1", 30) _GUICtrlListView_AddColumn($iListView_hWnd, "F2", 90) $HeaderCols = 2 GUISetState(@SW_SHOW) ; show the GUI $aMasterList[0] = "a|Q" $aMasterList[1] = "b|W" $aMasterList[2] = "c|E" $aMasterList[3] = "d|R" $aMasterList[4] = "e|T" $aMasterList[5] = "f|Y" $aMasterList[6] = "g|U" For $row = 0 To UBound($aMasterList) - 1 $aItem = StringSplit($aMasterList[$row], $sNamePWDSep) $iIndex = _GUICtrlListView_AddItem($iListView_hWnd, $aItem[1], -1, $row) For $ndx = 2 To $HeaderCols _GUICtrlListView_AddSubItem($iListView_hWnd, $iIndex, $aItem[$ndx], $ndx - 1) Next Next GUISetOnEvent($GUI_EVENT_CLOSE, 'Event_GUIClose') ; CLOSE events GUISetState() ; Make everything visible While 1 Sleep(500) WEnd EndFunc ;==>_Main ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; create_menus() - Create the main menu and all of its submenus ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Func create_menus() Local $iID_Menu $iID_Menu = GUICtrlCreateMenu("&File") addMenuItem($iID_Menu, "Open", "handle_menu_open") addMenuItem($iID_Menu, "Save", "handle_menu_SAVE") addMenuItem($iID_Menu, "Save As...", "handle_menu_SAVE_AS") addMenuItem($iID_Menu, "Revert", "handle_menu_revert") addMenuItem($iID_Menu, "Exit", "handle_EXIT_btn") EndFunc ;==>create_menus ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; addMenuItem() - Add a menu item to a menu ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Func addMenuItem($id, $title, $handler = "") Local $sid $sid = GUICtrlCreateMenuItem($title, $id) If ($handler <> "") Then GUICtrlSetOnEvent($sid, $handler) EndIf EndFunc ;==>addMenuItem Func ErrorPopup($msg) MsgBox(0 + 16, "ERROR", $msg) exit (1) EndFunc ;==>ErrorPopup Func Event_GUIClose() exit (0) EndFunc ;==>Event_GUIClose Func handle_EXIT_btn() exit (0) EndFunc ;==>handle_EXIT_btn Func saveToFile() ErrorPopup("saveToFile() entered") EndFunc ;==>saveToFile Func handle_menu_revert() ErrorPopup("handle_menu_revert() entered") EndFunc ;==>handle_menu_revert Func handle_MENU_OPEN() ErrorPopup("handle_MENU_OPEN() entered") EndFunc ;==>handle_MENU_OPEN Func handle_menu_SAVE() ErrorPopup("handle_menu_SAVE() entered") EndFunc ;==>handle_menu_SAVE Func handle_menu_SAVE_AS() ErrorPopup("handle_menu_SAVE_AS() entered") EndFunc ;==>handle_menu_SAVE_AS Run this script and click on some of the ListView items and notice that an Error MsgBox is displayed, saying a certain menu selection has been made. Note that removing, adding or re-arranginh menu items seems to change which handler gets called. Link to comment Share on other sites More sharing options...
Moderators Melba23 Posted October 22, 2010 Moderators Share Posted October 22, 2010 AndyS01,Try not to mix native and UDF commands when creatign controls - it ususally ends in tears. As you created the ListView with GUICtrlCreateListView, you need to add the items with GUICtrlCreateListViewItem.This code works fine for me:expandcollapse popup#NoTrayIcon #include <GUIConstantsEx.au3> #include <GuiListView.au3> Opt("GUIOnEventMode", 1) ; Change to OnEvent mode Opt('MustDeclareVars', 1) Opt("GUIEventOptions", 1) ;0=default, 1=just notification, 2=GuiCtrlRead tab index Global $hWnd_MainWin Global $iListView_ID Global $iListView_hWnd Global $sNamePWDSep = Opt("GUIDataSeparatorChar") _Main() Exit (0) ;;;;;;;;;;;;;;;;;;;;;;;;;; ; _Main() - Main function ;;;;;;;;;;;;;;;;;;;;;;;;;; Func _Main() Local $row, $aItem, $iIndex, $HeaderCols, $aMasterList[7] $hWnd_MainWin = GUICreate("Test", 340 - 16, 300 - 16) ; Create the Main GUI GUISetOnEvent($GUI_EVENT_CLOSE, 'Event_GUIClose') ; CLOSE events create_menus() $iListView_ID = GUICtrlCreateListView("F1|F2", 10, 10, 300, 200) $iListView_hWnd = GUICtrlGetHandle($iListView_ID) _GUICtrlListView_SetColumnWidth($iListView_ID, 0, 30) _GUICtrlListView_SetColumnWidth($iListView_ID, 1, 90) $aMasterList[0] = "a|Q" $aMasterList[1] = "b|W" $aMasterList[2] = "c|E" $aMasterList[3] = "d|R" $aMasterList[4] = "e|T" $aMasterList[5] = "f|Y" $aMasterList[6] = "g|U" For $row = 0 To UBound($aMasterList) - 1 GUICtrlCreateListViewItem($aMasterList[$row], $iListView_ID) Next GUISetState() ; Make everything visible While 1 Sleep(500) WEnd EndFunc ;==>_Main ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; create_menus() - Create the main menu and all of its submenus ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Func create_menus() Local $iID_Menu $iID_Menu = GUICtrlCreateMenu("&File") addMenuItem($iID_Menu, "Open", "handle_menu_open") addMenuItem($iID_Menu, "Save", "handle_menu_SAVE") addMenuItem($iID_Menu, "Save As...", "handle_menu_SAVE_AS") addMenuItem($iID_Menu, "Revert", "handle_menu_revert") addMenuItem($iID_Menu, "Exit", "handle_EXIT_btn") EndFunc ;==>create_menus ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; addMenuItem() - Add a menu item to a menu ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Func addMenuItem($id, $title, $handler = "") Local $sid $sid = GUICtrlCreateMenuItem($title, $id) If ($handler <> "") Then GUICtrlSetOnEvent($sid, $handler) EndIf EndFunc ;==>addMenuItem Func ErrorPopup($msg) MsgBox(0 + 16, "ERROR", $msg) Exit (1) EndFunc ;==>ErrorPopup Func Event_GUIClose() Exit (0) EndFunc ;==>Event_GUIClose Func handle_EXIT_btn() Exit (0) EndFunc ;==>handle_EXIT_btn Func saveToFile() ErrorPopup("saveToFile() entered") EndFunc ;==>saveToFile Func handle_menu_revert() ErrorPopup("handle_menu_revert() entered") EndFunc ;==>handle_menu_revert Func handle_MENU_OPEN() ErrorPopup("handle_MENU_OPEN() entered") EndFunc ;==>handle_MENU_OPEN Func handle_menu_SAVE() ErrorPopup("handle_menu_SAVE() entered") EndFunc ;==>handle_menu_SAVE Func handle_menu_SAVE_AS() ErrorPopup("handle_menu_SAVE_AS() entered") EndFunc ;==>handle_menu_SAVE_ASI know I am using _GUICtrlListView_SetColumnWidth, but this is one of the UDF commands that you can use on a native ListView, do not ask me why though! 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...
AndyS01 Posted October 22, 2010 Author Share Posted October 22, 2010 The problem is that in the actual script, I want to do column sorting using the Quick Sort. The only way I could see to do that was to call the _GUICtrlListView_UnRegisterSortCallBack() function. In the F1 help example for that function, it mixes the 2 methods. I went back to the original script and made the changes you suggested and, indeed, I didn't have the menu callback problem. However, the Quick Sort functionality stopped working. I tried using _GUICtrlListView_Create() to create the ListView, but then I needed to get the ID of the ListView control for some other operations in the script and I cannot figure out how to get the ListView's ID (to convert an ID to a handle, I call GUICtrlGetHandle($id), but I could not find an operation that does the reverse). If I could solve this issue, I could try it on my actual script. And ideas? Link to comment Share on other sites More sharing options...
Moderators Melba23 Posted October 22, 2010 Moderators Share Posted October 22, 2010 (edited) AndyS01, I needed to get the ID of the ListView control for some other operations in the scriptWhat operations are these? There may be a way around it. Thanks for pointing out that the Help file example mixing the native and UDF commands - I (and many others here) try not to mix them unless I absolutely must and it is interesting to see how they have been intermixed here. I will have another look at your original script and see if I can solve the problem while retaining the ListView code as you had it. M23 Edit, I now know why the ListView items action the menu items. AutoIt uses the ControlID of a control to action OnEvent handlers. The handlers are also reacting to the Index numbers of the ListView rows - AutoIt is picking up the "ListView Row Selection" message and treating it as the same numbered "Control Actioned" message. As a short-term fix, you can solve the problem by creating a dummy control after each ListView Item - this eats up the ControlID numbers to make sure that you "real" ControlIDs are always higher than the Index numbers of the ListView: $iIndex = _GUICtrlListView_AddItem($iListView_hWnd, $aItem[1], -1, $row) GUICtrlCreateDummy() You then create the menu controls and any other controls after the ListView. Like I said, this is a short-term fix as if you have a dynamic ListView this might pose a serious problem. So my view that you should not mix the native and UDF functions remains unchanged. As I said above, let me know why you need the ID of the ListView control and there might well be a way around it. I am off to study this whole thing a bit closer. M23 Edited October 22, 2010 by Melba23 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...
AndyS01 Posted October 22, 2010 Author Share Posted October 22, 2010 Problem solved. When I created the ListBox using GUICtrlCreateListView() and added items using GUICtrlCreateListViewItem() as you suggested, after some tweaking, the Quick Sort now works. Whew! Thank you for your help. Link to comment Share on other sites More sharing options...
Moderators Melba23 Posted October 22, 2010 Moderators Share Posted October 22, 2010 (edited) AndyS01,You problem solved, but a wider problem remains. See above for an explanation of what was going on. M23Edit:The bigger problem is also solved. I have just noticed that you were setting $iParam when you used _GUICtrlListView_AddItem. This is what AutoIt uses to store the ControlID when it creates ListView items with the native control - hence AutoIt thought that this was a native control and fired the event handler. If you use this:$iIndex = _GUICtrlListView_AddItem($iListView_hWnd, $aItem[1])to create the items, you do not get the interaction we saw earlier.So you can now use either way to create your ListView - although as you can guess, I strongly recommend the "single source" method! Thnaks for that - a lot of fun sorting it out. M23 Edited October 22, 2010 by Melba23 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...
AndyS01 Posted October 22, 2010 Author Share Posted October 22, 2010 Oh-Oh, the Quick Sort is now NOT doing an actual sort. It changes the direction arrow icon in the column header, but doesn't actually sort anything. Upon investigation, I see that the Quick Sort (__GUICtrlListView_Sort) uses the $param value to find the text for the items to compare. I see that the sort callback function is always being passed the $param values of 0,0 for it's parameters. It uses the $LVFI_PARAM flag in the $tagLVFINDINFO structure, so the $param must be present and must be unique among all of the ListView items. That's why I stored the row number there. So where are we now? If I use GUICtrlCreateListViewItem() to create the ListView items, then the Quick Sort has no unique data in the $param for each item. It looks like I have to use the _GuiCtrlListView_Create() function to create the ListView, but then I have the problem where I cannot get the control ID, which I need for other operations (such as GUICtrlSetPos() when the window gets resized). Am I getting wrapped around the axel? Link to comment Share on other sites More sharing options...
AndyS01 Posted October 22, 2010 Author Share Posted October 22, 2010 I bit the bullet and changed the other functions to use handles instead of IDs and it looks like everything is working correctly. I still had to specify the row number in the $param value, but it didn't mess up the click handling because I no longer mix native and UDF function calls for the listbox. Link to comment Share on other sites More sharing options...
Moderators Melba23 Posted October 23, 2010 Moderators Share Posted October 23, 2010 AndyS01, Excellent news. 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...
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