I will try to compile a script which demonstrates my observations tomorrow, though I fear when I do, the buggy behaviour will be gone.
Anyway, here's a rough overview over what I have so far:
A treeview created via the UDFs - the main file tree showing the files. A proper file explorer needs all kind of operations you are used to, like copy, cut, paste etc. so I did this kind of stuff.
You'd expect these options accessible via a context menu, so I did that one too. The how to do this I found here: http://www.autoitscript.com/forum/topic/...ew-items/page__view__findpost_
My setup so far:
treeview via _GUICtrlTreeView_Create etc. etc.
and context menu via GUICtrlCreateContextMenu
->
; Context menu (fileview) Local $dummy = GUICtrlCreateDummy() Global $ctxmenu = GUICtrlCreateContextMenu($dummy) ; Needs to be hooked up on the dummy Global $contextmenu = GUICtrlGetHandle($ctxmenu) ; Saved for later use, the menu is called via this handle GUICtrlSetOnEvent(GUICtrlCreateMenuItem(LoadStr("Context_New"), $ctxmenu), "NewFile") GUICtrlSetOnEvent(GUICtrlCreateMenuItem(LoadStr("Context_Cut"), $ctxmenu), "CutFile") GUICtrlSetOnEvent(GUICtrlCreateMenuItem(LoadStr("Context_Copy"), $ctxmenu), "CopyFile") GUICtrlSetOnEvent(GUICtrlCreateMenuItem(LoadStr("Context_Paste"), $ctxmenu), "PasteFile") GUICtrlSetOnEvent(GUICtrlCreateMenuItem(LoadStr("Context_Delete"), $ctxmenu), "DeleteFile") GUICtrlCreateMenuItem("", $ctxmenu) GUICtrlSetOnEvent(GUICtrlCreateMenuItem(LoadStr("Context_Refresh"), $ctxmenu), "RefreshFileViewWrapper")
LoadStr is just a function that returns a localized language string. The context menu is show on rightclick - of course.
This is a piece from my WM_NOTIFY:
Case $NM_RCLICK ; right click $mouse = _WinAPI_GetMousePos(True, $main) $hit_test = _GUICtrlTreeView_HitTest($fileview, DllStructGetData($mouse, "X"), DllStructGetData($mouse, "Y")) $selitem = _GUICtrlTreeView_HitTestItem($fileview, DllStructGetData($mouse, "X"), DllStructGetData($mouse, "Y")) If $hit_test = 1 Or $hit_test = 32 Then FileviewLoseSelection() RefreshContextMenu() _GUICtrlMenu_TrackPopupMenu($contextmenu, $main) Return 1 Else If $selitem = 0 Then Return $GUI_RUNDEFMSG _GUICtrlTreeView_SelectItem($fileview, $selitem) _GUICtrlTreeView_SetSelected($fileview, $selitem) $no_selection = False RefreshContextMenu() _GUICtrlMenu_TrackPopupMenu($contextmenu, $main) Return 1 EndIf
I test to see whether the user clicked on an item - if yes, select that item. If no, clear the selection of the treeview (a bit hacky though but sufficient for my purpose) so the user may create new files in the root directory (which is the game dir). That's what FileviewLoseSelection() does.
RefreshContextMenu does a bunch of de-/activation of context menu entries e.g. deactivating the Paste option of no file was selected for cutting/copying:
Func RefreshContextMenu() ConsoleWrite("RefreshContextMenu" & @CRLF) ; Paste operation only accessible if file to paste If Not $file_operation Then _GUICtrlMenu_SetItemDisabled($contextmenu, 3) Else _GUICtrlMenu_SetItemEnabled($contextmenu, 3) EndIf [...]
The weirdness begins now. I wanted to test everything when a 'crash' occured. I looked further into this and could narrow it down to have something to do with the context menu. I discovered, using AutoIt Debugger, that this was no real crash but that my regular end program routine was called. But not only that, I got random inputs on every menu item in my whole GUI. This isn't limited to the context menu but also triggers random entries from the system menu of the GUI:
Global $optmenu = GUICtrlCreateMenu(LoadStr("Menu_Options")) GUICtrlSetOnEvent(GUICtrlCreateMenuItem(LoadStr("Menu_Prefs"), $optmenu), "OpenPreferences") GUICtrlSetOnEvent(GUICtrlCreateMenuItem(LoadStr("Menu_Quit"), $optmenu), "EditorClose") Global $infomenu = GUICtrlCreateMenu(LoadStr("Menu_Info")) GUICtrlSetOnEvent(GUICtrlCreateMenuItem(LoadStr("Menu_About"), $infomenu), "ShowInfo") Global $info_window ; To save the info window Global $prefs_window ; To save the preferences window
There never was a crashed but the Menu_Quit entry was triggered. Sometimes the preferences window opened, sometimes the about screen. Sometimes the new file dialogue opens (first context menu entry), sometimes the file tree is refreshed (6th entry, not counting the separator) or I am asked if I want to delete the file. These ghost inputs occur on two different occasions:
1. The context menu is opened; AutoIt Debugger told me that RefreshContextMenu was called, ConsoleWrite wrote the console but then the execution of RefreshContextMenu was interrupted and the other function kicked in e.g. I get prompted for file deletion. After this interrupting process is done, RefreshContextMenu continues and the context menu opens.
2. I select an entry from the context menu. The entry is processed and when that's finished the random function is done. This often was my 'crash' because Menu_Quit was called. Though I get a crash report from Windows and everything.
After I disabled the creation of the system menu, at least quitting of the program and opening of the preferences stopped. So that's my current status. I have no idea how to access this problem. AutoIt Debugger doesn't give me any more useful information than the interruption of the context refresh function. I'm happy to provide anyone who is willing to help with the full source (~33 MB). I'm desperate. I invested already ~5 hours into finding this bug.
To wrap it all up, here's my creation routine of the GUI and the three elements in question (treeview, system menu, context menu). Maybe someone can make something out of it:
; Create the GUI Opt("GUIOnEventMode", 1) Opt("GUICloseOnESC", 0) Opt("PixelCoordMode", 2) Opt("TrayIconHide", 1) Global $main = GUICreate("OpenClonk Editor", 800, 600, -1, -1, BitOR($WS_CAPTION, $WS_MINIMIZEBOX, $WS_SYSMENU, $DS_CONTEXTHELP, $WS_SYSMENU, $WS_VISIBLE, $WS_CLIPCHILDREN)) GUISetOnEvent($GUI_EVENT_CLOSE, "EditorClose", $main) GUISetOnEvent($GUI_EVENT_PRIMARYUP, "EndDrag", $main) GUISetState(@SW_DISABLE, $main) ; Show splash screen SplashImageOn(LoadStr("General_InitMenu"), ".\res\Splash.jpg", 320, 240) ; Options menu Global $optmenu = GUICtrlCreateMenu(LoadStr("Menu_Options")) GUICtrlSetOnEvent(GUICtrlCreateMenuItem(LoadStr("Menu_Prefs"), $optmenu), "OpenPreferences") GUICtrlSetOnEvent(GUICtrlCreateMenuItem(LoadStr("Menu_Quit"), $optmenu), "EditorClose") Global $infomenu = GUICtrlCreateMenu(LoadStr("Menu_Info")) GUICtrlSetOnEvent(GUICtrlCreateMenuItem(LoadStr("Menu_About"), $infomenu), "ShowInfo") Global $info_window ; To save the info window Global $prefs_window ; To save the preferences window ; Context menu (fileview) Local $dummy = GUICtrlCreateDummy() ; This is necessary because autoit handles context menus poorly. It won't work with _GUICtrlTreeView (TreeView created via autoit UDFs) Global $ctxmenu = GUICtrlCreateContextMenu($dummy) ; Needs to be hooked up on the dummy Global $contextmenu = GUICtrlGetHandle($ctxmenu) ; Saved for later use, the menu is called via this handle GUICtrlSetOnEvent(GUICtrlCreateMenuItem(LoadStr("Context_New"), $ctxmenu), "NewFile") GUICtrlSetOnEvent(GUICtrlCreateMenuItem(LoadStr("Context_Cut"), $ctxmenu), "CutFile") GUICtrlSetOnEvent(GUICtrlCreateMenuItem(LoadStr("Context_Copy"), $ctxmenu), "CopyFile") GUICtrlSetOnEvent(GUICtrlCreateMenuItem(LoadStr("Context_Paste"), $ctxmenu), "PasteFile") GUICtrlSetOnEvent(GUICtrlCreateMenuItem(LoadStr("Context_Delete"), $ctxmenu), "DeleteFile") GUICtrlCreateMenuItem("", $ctxmenu) GUICtrlSetOnEvent(GUICtrlCreateMenuItem(LoadStr("Context_Refresh"), $ctxmenu), "RefreshFileViewWrapper") If $C4GROUP_EXE <> "" Then GUICtrlCreateMenuItem("", $ctxmenu) GUICtrlSetOnEvent(GUICtrlCreateMenuItem(LoadStr("Context_C4GPack"), $ctxmenu), "PackFile") GUICtrlSetOnEvent(GUICtrlCreateMenuItem(LoadStr("Context_C4GUnpack"), $ctxmenu), "UnpackFile") EndIf SplashImageOn(LoadStr("General_InitFiles"), ".\res\Splash.jpg", 320, 240) ; Tree file view Global $fileview = _GUICtrlTreeView_Create($main, 0,0, 200,560, BitOR($TVS_HASBUTTONS, $TVS_HASLINES, $TVS_LINESATROOT, $TVS_SHOWSELALWAYS, $TVS_EDITLABELS, $TVIS_DROPHILITED, $WS_TABSTOP, $TVS_CHECKBOXES), $WS_EX_CLIENTEDGE) InitFileView() Local $hFunc DIM $TVN_BEGINDRAG DIM $TVN_BEGINLABELEDIT DIM $TVN_ENDLABELEDIT ; For drag and drop behaviour inside the treeview Global $drag_item, $next_item, $prev_item, $hover_item, $hover_time ; Drag and drop outside the treeview, explorer extension _OLEInitialize() GUIRegisterMsg($WM_DI_GETDRAGIMAGE, "MY_GETDRAGIMAGE") Global $IDragSourceHelper = _ObjCoCreateInstance($CLSID_DragDropHelper,$IID_IDragSourceHelper,$IDragSourceHelper_vTable) Global $objIDataSource ; Proper detecting of the return key is broken in AutoIt, this is used for a workaround: Global $wProcHandle = DllCallbackRegister("_WindowProc", "int", "hwnd;uint;wparam;lparam") Global $wProcOld = _WinAPI_SetWindowLong($fileview, $GWL_WNDPROC, DllCallbackGetPtr($wProcHandle)) Global Const $VK_RETURN = 0x0D ; Enter key ; For renaming Global $edit_label = False Global $just_edited = "" Global Const $VK_F2 = 0x71 ; F2 key ; For checking .ocd Global $checked_item = 0 Global $checked_path = "" Global $checked_state = False ; Workaround to have the treeview "lose" its selection Global $no_selection = False ; Temporary memory for sorting the elements (after renaming/moving/creation) Global $sort_memory[1] $sort_memory[0] = ""




