Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

TreeCtrl-support via DLLCall


  • Please log in to reply
60 replies to this topic
Micha
  • Members
  • 539 posts
  • Last active: Dec 31 2011 01:43 PM
  • Joined: 15 Nov 2005
Hi,
here is my first try for TREECONTROL - support for Autohotkey. (V0.4)

I have done that work, because I was interested in how to achieve it and I hope somebody could need it.

Please post if you need other- or more things to be supported.
Until now it is not more than a little demo that shows that CTreeCtrl-support can be made via DLL-Call until it's supported natively by autohotkey

Here what it can:

(All functions begin with Tree!!)

TreeGetCount : Get the number of expanded nodes of a treectrl
TreeGetBkColorRGB: Returns the color of the backgroundwindow of the treecontrol (RGB)
TreeSetBkColorRGB: Sets a new color for the background of the treecontrol
TreeGetTextColorRGB: Returns the color of the text of a treecontrol
TreeSetTextColorRGB: Sets a new color for the text of the treecontrol
TreeGetRootItem: Retrieve the handle of the rootitem (You use it for the next functions)
TreeGetNextItem: Get the next item of the same parent
TreeItemHasChildren: Returns if the current entry has childitems
TreeExpandCollapse: Expand or collapses the current entry
TreeGetItemRect: Gets the size of the Rect around one entry
TreeGetItemText: Retrieve the current text of an treecontrol-entry
TreeSetItemText: Sets a new text.
TreeCreate: Create a TreeCtrl on an AHK-Window
TreeGetNMHDR: When a message arrives, an eventhandler is called. lParam is the pointer to a struct with additional infos. That functioncall retrieves the values: HWND of the control, ID of the Control, MessageCode
TreeGetSelectedItem: Retrieves the HTREEITEM of the currently selected item.

Please see the AHK-script, too!

If you run it, the following will happen:
First you have to open an explorer-window and editing the variable "TestPath=XXX" in the script. XXX should be the title of the explorer or any window with a TreeCtrl. Next edit the variable
HomePath=AHKTreeSupport\Debug\AHKTreeSupport.dll to point to the dll.

BE CAREFUL: I have tested the script a lot of times, but if you run it with an explorer, do not blame me if it deletes entries(files/folders). It is NOT implemented such a feature, but everything could happen, if your computer has a hiccup. :-)

It tells you how many expanded entries are in the TreeCtrl.
Than it tells you the red/green/blue-values of the background.
It sets a new color for the background (If you close the window, the changed colors are gone, so don't worry!)
It tells you the handle of the rootitem, the textcolor (RGB-value) and it changes the textcolor
It shows a dlg with the name of the first entry and if the entry has a child
Then you see the left-right/top-bottom values for the RECT around the text
Now you're in a loop
{
it shows you the name of next/child item, expands it (if possible)
shows you the rect-pixel-size and if the entry has a child
}

The example is full of messageboxes, thus you can stop the script at any time


Tell me, what you need as expansion and I will try to enhance the dll.

Here is the code:
Script1 (Shows Entries of an existing TreeCtrl): TestTreeCtrl.ahk

Script2 (Dumps the Tree to a file): DumpTreeCtrl.ahk

Script3 (How to create a Tree on a AHK-Wnd): guiTestTreeCtrl.ahk

Script4 (Like Script 3 but with an eventhandler to retrieve the selected Item): guiTestTreeCtrlNotify.ahk
-> Download the scripts

DLL: https://ahknet.autoh...TreeSupport.dll

If you have problems to get the dll working, you will need new MS-Dlls (mfc80.dll, msvcr80.dll) please download the 2 Archives, unpack them and start the vcredist_x86.exe. It will install the needed dlls
https://ahknet.autoh...6.sfx.part1.exe
https://ahknet.autoh...6.sfx.part2.rar
There's a uploadlimit of 2 MB, thus I had to split the Archives

To use the script that dumps the content of a tree to a file, I had done the following:
On your Desktop click with the right mouse-button on "My computer" and choose the fourth entry "manage" (german:Verwaltung).
Open the script and adjust the variable "TestPath" with the title of the window.
After saving start the script. It writes a file c:\x.txt with the Tree-contents

Ciao
Micha

Chris
  • Administrators
  • 10727 posts
  • Last active:
  • Joined: 02 Mar 2004
I know this will be immediately useful to some people because there have been requests for it.

I'm not sure if it's possible, but it would be interesting to see if this could be done purely with DllCall with no external DLL file. I realize that would be a lot of development time, and perhaps it would reduce performance too much.

In any case, thanks for posting this solution for TreeView manipulation and data extraction.

Micha
  • Members
  • 539 posts
  • Last active: Dec 31 2011 01:43 PM
  • Joined: 15 Nov 2005
Hi Chris,
I'm sure, it can be done via Dllcall without an extra dll, but sometimes you have to create a TVITEM-struct to pass it to the SendMessage-function as parameter. This would be a great and perhaps error-prone job.

Of cource if you do not need an extra dll, it's much better, but you have to do a lot of extra, painful work which the dll could do internal.

Primary I will enhance the dll-solution.
If there is enough time, I will try to write few helper-functions to achive the same without a dll

Ciao
Micha

Grendel
  • Members
  • 25 posts
  • Last active: Mar 17 2007 07:11 PM
  • Joined: 18 Nov 2005
Micha, can you tell me, why this error appears ???

error while calling TreeGetRootItem Errorlevel: -3
greets Grendel

Micha
  • Members
  • 539 posts
  • Last active: Dec 31 2011 01:43 PM
  • Joined: 15 Nov 2005
Hi,
this is the errorcode from autohotkey.
From the help (dllcall):

-3: The specified DllFile could not be accessed. If no absolute path was specified for DllFile, the file must exist in the system's PATH or in A_WorkingDir. This error might also occur if the user lacks permission to access the file.


Adjust the variable "Homepath" in the script to point to the dll.
I.e: move the dll to the same folder as the script and set
Homepath=AHKTreeSupport.dll

It you still have problems, you could use the program "Dependency Walker" "depends.exe".
Open the AHKTreeSupport.dll with that program. If there is a problem, you will see red symbols in front of the dll. Perhaps you do not have the correct Microsoft-runtime installed.

I've used a new compiler from Microsoft. If that is the problem, I will post a dll compiled with an older compiler.

Ciao
Micha

Micha
  • Members
  • 539 posts
  • Last active: Dec 31 2011 01:43 PM
  • Joined: 15 Nov 2005
If you have still the problem with

error while calling TreeGetRootItem Errorlevel: -3

please download the ZIP mfc_dlls.zip.

If you haven't installed the new vcredist.exe from Microsoft, these files are missing and my dll can't be loaded by the OS.
Please put these files in the same folder where you have saved my dll.

Ciao
Micha

Micha
  • Members
  • 539 posts
  • Last active: Dec 31 2011 01:43 PM
  • Joined: 15 Nov 2005
I have seen a post where a user wants to have a TreeCtrl on an AHK-GUI-Window. ---->
Posted Image
That is an AHK-GUI-Window.

I have expanded my DLL to support the creation of treecontrols.

The Samplescript to draw a treecontrol on a gui is guiTestTreeCtrl.ahk

I know, that the script is very big, but don't panic: A lot of code is only for errorhandling.
If you like, you can delete the lines (if nRC == 0 MsgBox error....)

Do you need more support for Treecontrols? -> Let me know

Ciao
Micha

Micha
  • Members
  • 539 posts
  • Last active: Dec 31 2011 01:43 PM
  • Joined: 15 Nov 2005
Updated links and added download for the needed MFC-DLLs

POINTS
  • Members
  • 290 posts
  • Last active: Oct 13 2010 02:12 AM
  • Joined: 17 Jan 2006
Quick question, how do you control the position of where you place the tree?

I got the sample code to work but I don't see where in the code you can choose a placement if we want to add other things like buttons.

Here's a sample (without any trees):

Gui, Add, Button, x36 y310 w110 h50, 
Gui, Add, Button, x166 y310 w110 h50, 
Gui, Add, Button, x316 y310 w110 h50, 
Gui, Add, Button, x316 y230 w110 h50, 
Gui, Add, Button, x316 y170 w110 h50, 
Gui, Add, Button, x316 y60 w110 h50, 
Gui, Show, x270 y110 h377 w477, A Simple GUI layout
Return

GuiClose:
ExitApp


How do we place the tree in the upper left corner for example?

Micha
  • Members
  • 539 posts
  • Last active: Dec 31 2011 01:43 PM
  • Joined: 15 Nov 2005
Something like that?:
Posted Image
Have a look after the line ;set coordinates like after gui, add, button


;Load the dll
HomePath=AHKTreeSupport.dll
hModule := DllCall("LoadLibrary", "str", HomePath) 
Gui, Add, Button, x36 y310 w110 h50, 
Gui, Add, Button, x166 y310 w110 h50, 
Gui, Add, Button, x316 y310 w110 h50, 
Gui, Add, Button, x316 y230 w110 h50, 
Gui, Add, Button, x316 y170 w110 h50, 
Gui, Add, Button, x316 y60 w110 h50, 
Gui, Show, x270 y110 h377 w477, A Simple GUI layout
;Get HWND of the dialog 
WinGet, HWND, ID, A Simple GUI layout
;Set Treestyle
dwexStyle := 0x10000000 | 0x01 | 0x02 | 0x04
dwStyle = 0
;set coordinates like after gui, add, button
x = 45
y = 55
width = 250
height = 230
;Set an ID for the TreeControl
nID = 1234
;Create the Control
TreeHWND := DllCall("AHKTreeSupport\TreeCreate", DWORD, dwexStyle, DWORD, dwStyle, int, x, int, y, int, width, int, height, DWORD, HWND, int, nID, "Cdecl Int")
if (errorlevel <> 0) || (nRC = 0)
{
	MsgBox error while calling TreeCreate Errorlevel: %errorlevel% - RC: %nRC%
	return
}

the following is UNIMPORTANT, but shows how to enter dummy-items
; !!UN!!-IMPORTANT !!!!!!!!!!!! Add Dummyentries
Text2Insert=Dummytext
TreeHwnd := GetChildHWND(HWND, "SysTreeView321")
InsertText2TreeView(TreeHwnd, 0, -0x0FFFE, 0, Text2Insert)
return
	
InsertText2TreeView(TreeHwnd, hParent, hLastInsertedItem, counter, Text2Insert)
{	
	if counter > 3
		return

	loop, 3
	{		
		NewText2Insert = %Text2Insert%%A_INDEX%		
		;MsgBox, %TreeHwnd% %hParent% %hLastInsertedItem% %counter%
		nRC := DllCall("AHKTreeSupport\TreeInsertItem", DWORD, TreeHwnd, Str, NewText2Insert, DWORD, hParent, DWORD, hLastInsertedItem, "Cdecl Int")
		if (errorlevel <> 0) || (nRC = 0)
		{
			MsgBox error while calling TreeInsertItem Errorlevel: %errorlevel% - RC: %nRC%
			return
		}
		nCode = 2 ;1=Collapse / 2=Expand / 3=toggle / 0x4000=expand partial / 0x8000=collapsereset 
		nRCExpand := DllCall("AHKTreeSupport\TreeExpandCollapse", UINT, TreeHwnd, UINT, hParent, UINT, nCode, "Cdecl Int")
		if (errorlevel <> 0) ;|| (nRC = 0)
		{
			MsgBox error while calling TreeExpandCollapse Errorlevel: %errorlevel%
			; return
		}					
		InsertText2TreeView(TreeHwnd, nRC, hLastInsertedItem, counter+1, Text2Insert)
	}	
}
Return 

GetChildHWND(ParentHWND, ChildClassNN)
{
	WinGetPos, ParentX, ParentY,,, ahk_id %ParentHWND%
	if ParentX =
		return  ; Parent window not found (possibly due to DetectHiddenWindows).
	ControlGetPos, ChildX, ChildY,,, %ChildClassNN%, ahk_id %ParentHWND%
	if ChildX =
		return  ; Child window not found, so return a blank value.
	return DllCall("WindowFromPoint", "int", ChildX + ParentX, "int", ChildY + ParentY)
}

GuiClose: 
ExitApp 

Hope that helps.
The TreeControl isn't an easy control. Even if programming in C, you could have a lot of fun :cry:

POINTS
  • Members
  • 290 posts
  • Last active: Oct 13 2010 02:12 AM
  • Joined: 17 Jan 2006
thanks I'll give it a try. I took a C++ class on how to make windows programs but it was ridiculously difficult. Visual Basic is just as bad without documentation (MSDN might help?). AHK looks like the best alternative with it's great documentation, this wonderful forum and even a gui creater (http://www.autohotke...topic.php?t=775).

POINTS
  • Members
  • 290 posts
  • Last active: Oct 13 2010 02:12 AM
  • Joined: 17 Jan 2006
after banging my head on the wall...

Don't forget to change this line:
WinGet, HWND, ID, A Simple GUI layout

to whatever your window is called.

Thanks for the help! It looks like it will fine now.

POINTS
  • Members
  • 290 posts
  • Last active: Oct 13 2010 02:12 AM
  • Joined: 17 Jan 2006
One last thing:

Add trees to the wish list! It would be awesome if you could add this Chris, but this is great for now.

POINTS
  • Members
  • 290 posts
  • Last active: Oct 13 2010 02:12 AM
  • Joined: 17 Jan 2006
Is there a way to make it non-recursive?

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;   Tree Menu   ;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
nRC := 0
Text2Insert=Dummytext
TreeHwnd := GetChildHWND(HWND, "SysTreeView321")
InsertText2TreeView(TreeHwnd, 0, -0x0FFFE, 0, Text2Insert)
InsertText2TreeView(TreeHwnd, nRC, -0x0FFFE, 0, "blah")
InsertText2TreeView(TreeHwnd, nRC, -0x0FFFE, 0, "blah2")
return
   
InsertText2TreeView(TreeHwnd, hParent, hLastInsertedItem, counter, Text2Insert)
{   
   ;if counter > 3
      ;return

   ;loop, 3
   ;{      
      NewText2Insert = %Text2Insert%%A_INDEX%      
      ;MsgBox, %TreeHwnd% %hParent% %hLastInsertedItem% %counter%
      nRC := DllCall("AHKTreeSupport\TreeInsertItem", DWORD, TreeHwnd, Str, NewText2Insert, DWORD, hParent, DWORD, hLastInsertedItem, "Cdecl Int")
      if (errorlevel <> 0) || (nRC = 0)
      {
         MsgBox error while calling TreeInsertItem Errorlevel: %errorlevel% - RC: %nRC%
         return
      }
      nCode = 1 ;1=Collapse / 2=Expand / 3=toggle / 0x4000=expand partial / 0x8000=collapsereset
      nRCExpand := DllCall("AHKTreeSupport\TreeExpandCollapse", UINT, TreeHwnd, UINT, hParent, UINT, nCode, "Cdecl Int")
      if (errorlevel <> 0) ;|| (nRC = 0)
      {
         MsgBox error while calling TreeExpandCollapse Errorlevel: %errorlevel%
         ; return
      }               
      ;InsertText2TreeView(TreeHwnd, nRC, hLastInsertedItem, counter+1, Text2Insert)
   ;}   
}
Return

For example make blah a subset of Dummytext.

POINTS
  • Members
  • 290 posts
  • Last active: Oct 13 2010 02:12 AM
  • Joined: 17 Jan 2006
sorry fixed it myself :oops:

just add:

  global nRC

in the function.