Tjalve Posted February 9, 2017 Share Posted February 9, 2017 Hi everyone. Im creating a GUI for an application. Im usinga treeview item and i want to add some information to the side of the treeview based on what cilditem you are pressing. For the moment i have a "get info" button that works. But that means that you have to select your child in the treeview, and then press a button to gte the info. I want the info to be visable as soon as you select it. With uther controls you can just add it to the loop but it doesnt seem to work with tyhe UDF version of the treeview control. Is there anything I can do? #include <GUIConstantsEx.au3> #include <GuiTreeView.au3> #include <MsgBoxConstants.au3> #include <WindowsConstants.au3> ;~ Create GUI dim $guilabel[7] local $currentlevel = 1 Local $hGui = GUICreate( "Grejs", 1000, 500, 600, 300, BitOR( $GUI_SS_DEFAULT_GUI, $WS_MAXIMIZEBOX, $WS_SIZEBOX ) ) Local $iBorderWidth = 4, $aPos = WinGetClientSize( $hGui ) $idTV = _GUICtrlTreeView_Create($hGui, $iBorderWidth, $iBorderWidth, $aPos[0]-2*$iBorderWidth-400, $aPos[1]-2*$iBorderWidth-30 ) $root_level = _GUICtrlTreeView_Add($idTV,0,"Root") $item1 = _GUICtrlTreeView_AddChild($idTV, $root_level, "child1") $item2 = _GUICtrlTreeView_AddChild($idTV, $root_level, "child2") $item3 = _GUICtrlTreeView_AddChild($idTV, $root_level, "child3") ;~ Start Gui GUISetState() While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE ExitLoop Case $idTV MsgBox(0,"","") EndSwitch WEnd GUIDelete($hGui) Exit In this example, i want the msgbox to appear whenevr i select something in the treeview. It ios not my full code, but its an example of the problam i have. Help is much appritiated /G Link to comment Share on other sites More sharing options...
Moderators Melba23 Posted February 9, 2017 Moderators Share Posted February 9, 2017 Tjalve, Here you go: expandcollapse popup#include <GUIConstantsEx.au3> #include <GuiTreeView.au3> #include <MsgBoxConstants.au3> #include <WindowsConstants.au3> ; Flag for TV selection change Global $hItemSelected = 9999 ;~ Create GUI dim $guilabel[7] local $currentlevel = 1 Local $hGui = GUICreate( "Grejs", 1000, 500, 600, 300, BitOR( $GUI_SS_DEFAULT_GUI, $WS_MAXIMIZEBOX, $WS_SIZEBOX ) ) Local $iBorderWidth = 4, $aPos = WinGetClientSize( $hGui ) $hTV = _GUICtrlTreeView_Create($hGui, $iBorderWidth, $iBorderWidth, $aPos[0]-2*$iBorderWidth-400, $aPos[1]-2*$iBorderWidth-30 ) $root_level = _GUICtrlTreeView_Add($hTV,0,"Root") $item1 = _GUICtrlTreeView_AddChild($hTV, $root_level, "child1") $item2 = _GUICtrlTreeView_AddChild($hTV, $root_level, "child2") $item3 = _GUICtrlTreeView_AddChild($hTV, $root_level, "child3") ;~ Start Gui GUISetState() GUIRegisterMsg($WM_NOTIFY, "_WM_NOTIFY") While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE ExitLoop EndSwitch ; If flag set If $hItemSelected <> 9999 Then ; Here is the action MsgBox($MB_SYSTEMMODAL, "Selected", _GUICtrlTreeView_GetText($hTV, $hItemSelected)) ; Clear flag $hItemSelected = 9999 EndIf WEnd GUIDelete($hGui) Exit Func _WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam) #forceref $hWnd, $iMsg, $wParam ; Create NMTREEVIEW structure Local $tStruct = DllStructCreate("struct;hwnd hWndFrom;uint_ptr IDFrom;INT Code;endstruct;" & _ "uint Action;struct;uint OldMask;handle OldhItem;uint OldState;uint OldStateMask;" & _ "ptr OldText;int OldTextMax;int OldImage;int OldSelectedImage;int OldChildren;lparam OldParam;endstruct;" & _ "struct;uint NewMask;handle NewhItem;uint NewState;uint NewStateMask;" & _ "ptr NewText;int NewTextMax;int NewImage;int NewSelectedImage;int NewChildren;lparam NewParam;endstruct;" & _ "struct;long PointX;long PointY;endstruct", $lParam) If DllStructGetData($tStruct, "hWndFrom") = $hTV Then Switch DllStructGetData($tStruct, "Code") ; If item selection changed Case $TVN_SELCHANGEDA, $TVN_SELCHANGEDW Local $hItem = DllStructGetData($tStruct, "NewhItem") ; Set flag to selected item handle If $hItem Then $hItemSelected = $hItem EndSwitch EndIf EndFunc Note that I changed the variable in which you store the return from _GUICtrlTreeView_Create to reflect the fact that you get a handle and not a ControlID - please ask if you do not understand why this is important (or if you have any other questions). M23 Skysnake 1 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...
Tjalve Posted February 10, 2017 Author Share Posted February 10, 2017 Hi Melba23 and thank you for your replay. That work flawlessly! However i still dont really understand. I can deffenently use your code (and i will) but it would be nice to unerstand what is happening. If i understand it correctly, the UDF fuctions doesnt return a ControlID, but a handle. I suspect there is a good reson for it, but thats boyond my understanding. Anyways, To use Switch and GuiGetMsg() i need a controlID. And since the function does not return one, it wont work. In your case you are using an IF-statement to check if the itemselected varible has changed. What i dont understand is how that varible change. I see your function and I see some kind of DLL call ore something. But there is no way i would be able to write that myself. So is there some kind of logic to it? Thank you again for your assistance? Link to comment Share on other sites More sharing options...
Moderators Melba23 Posted February 10, 2017 Moderators Share Posted February 10, 2017 Tjalve, First, let us deal with handles and ControlIDs. Windows handles are unique identifiers that the OS uses to keep track of everything on the system, such as GUIs and controls, which continually send messages around the system so that everything in the system knows what is going on (which GUI is active, which control has just been actioned, which key was pressed, etc, etc). These messages contain all sorts of data, but essentially explain "which control has just done what". AutoIt tries to make life simple for you by using ControlIDs to identify its native controls - theses IDs are actually the indIces of an internal array of all controls maintained by AutoIt. So when you look for these ControlIDs in a GUIGetMsg loop you are asking AutoIt to access the Windows message stream and pick put those messages which refer to that control - the OnEvent commands work in a similar manner. Now to how the script I posted works. As the UDF functions return handles and not ControlIDs (which as explained above are only returned by AutoIt native functions) we cannot use a GUIGetMsg loop to look for messages, so we have to do it ourselves rather than relying on AutoIt to do it for us. This is where the GUIRegisterMsg command comes into play - it peeks into the Windows message stream and lets us see what is happening. In the script above we are asking to look at WM_NOTIFY messages - a pretty comprehensive set which, amongst many other things, covers selecting items in a TreeView. When a WM_NOTIFY message is detected in the stream AutoIt then runs the allocated function or "handler" where we can examine the message in detail: We create a data structure to look at the detailed content of the message - this data is stored by Windows and we use one of the message parameters ($lParam) to access it. We then check that this message was indeed sent by the treeview by looking inside the data structure - we can ignore the vast majority of messages which have been sent by other controls. Finally we check if the message deals with a change of the selected item in the treeview - and if it does than we know that we have found the message we were looking for. And there you have it - because the treeview was created by a UDF and not by an internal AutoIt function, we had to recreate what AutoIt does for us "under the hood" and peer into the Windows message stream ourselves to intercept the message telling us that the user had selected another item in the treeview. You can see the same thing happening with tab controls if you read the Tabs tutorial in the Wiki - if you create the tab with the UDF you need to do a lot more work to make it work correctly. I hope that the above explanation makes you realise how much AutoIt does for you behind the scenes - please ask again if anything is still unclear. M23 Skysnake and spudw2k 2 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...
Skysnake Posted February 10, 2017 Share Posted February 10, 2017 Great @Melba23! Put this somewhere in the Help file? Skysnake Skysnake Why is the snake in the sky? Link to comment Share on other sites More sharing options...
Tjalve Posted February 14, 2017 Author Share Posted February 14, 2017 On 2017-02-10 at 2:44 PM, Melba23 said: Tjalve, First, let us deal with handles and ControlIDs. Windows handles are unique identifiers that the OS uses to keep track of everything on the system, such as GUIs and controls, which continually send messages around the system so that everything in the system knows what is going on (which GUI is active, which control has just been actioned, which key was pressed, etc, etc). These messages contain all sorts of data, but essentially explain "which control has just done what". AutoIt tries to make life simple for you by using ControlIDs to identify its native controls - theses IDs are actually the indIces of an internal array of all controls maintained by AutoIt. So when you look for these ControlIDs in a GUIGetMsg loop you are asking AutoIt to access the Windows message stream and pick put those messages which refer to that control - the OnEvent commands work in a similar manner. Now to how the script I posted works. As the UDF functions return handles and not ControlIDs (which as explained above are only returned by AutoIt native functions) we cannot use a GUIGetMsg loop to look for messages, so we have to do it ourselves rather than relying on AutoIt to do it for us. This is where the GUIRegisterMsg command comes into play - it peeks into the Windows message stream and lets us see what is happening. In the script above we are asking to look at WM_NOTIFY messages - a pretty comprehensive set which, amongst many other things, covers selecting items in a TreeView. When a WM_NOTIFY message is detected in the stream AutoIt then runs the allocated function or "handler" where we can examine the message in detail: We create a data structure to look at the detailed content of the message - this data is stored by Windows and we use one of the message parameters ($lParam) to access it. We then check that this message was indeed sent by the treeview by looking inside the data structure - we can ignore the vast majority of messages which have been sent by other controls. Finally we check if the message deals with a change of the selected item in the treeview - and if it does than we know that we have found the message we were looking for. And there you have it - because the treeview was created by a UDF and not by an internal AutoIt function, we had to recreate what AutoIt does for us "under the hood" and peer into the Windows message stream ourselves to intercept the message telling us that the user had selected another item in the treeview. You can see the same thing happening with tab controls if you read the Tabs tutorial in the Wiki - if you create the tab with the UDF you need to do a lot more work to make it work correctly. I hope that the above explanation makes you realise how much AutoIt does for you behind the scenes - please ask again if anything is still unclear. M23 I applaud you sir! Simple and understandable explanation. As i said, I probably would not be able to write it myself (maybe if i copy and paste some of your code :P). But now, atleast i understand whats going on. Great summary and many thanks! Link to comment Share on other sites More sharing options...
corgano Posted June 7, 2017 Share Posted June 7, 2017 I faced this problem too, my solution was a bit simpler: $oldItem = "" While 1 $nMsg = GUIGetMsg() Switch $nMsg Case $GUI_EVENT_CLOSE Exit endSwitch $newItem = _GUICtrlTreeView_GetSelection($TreeView1) If $newItem <> $oldItem Then $oldItem = $newItem ;do stuff here with $newItem endif wend Maybe not as optimum, but straightforward. 0x616e2069646561206973206c696b652061206d616e20776974686f7574206120626f64792c20746f206669676874206f6e6520697320746f206e657665722077696e2e2e2e2e 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