dcl_Tree

Started by Zibster, February 01, 2008, 01:54:53 AM

Previous topic - Next topic

Zibster

Hello,

I have problem with Lisp code, maybe someone can to help me...
In OnInitialize I have:

(dcl_Tree_Clear bik_Bloki_frmBloki_TreeControl11)
(dcl_Tree_AddParent  bik_Bloki_frmBloki_TreeControl11
  (list (list "Cars" "C1")
   (list "Animals" "A1")
   (list "Plants" "P1"))
  );
  (dcl_Tree_AddChild  bik_Bloki_frmBloki_TreeControl11
    (list (list "C1" "Os" "C1.1")
     (list "C1" "Tr" "C1.2")
     (list "C1" "Cm" "C1.3"))
  );

etc. etc.

But I need this TreeControl to fill up folders with automatically (μ-recursive function)
For example:
1. start folder:  Location  = "c:/Bloki/"
2. function code:


(defun MakeFTree (Location / DirList Path AllPath LstTL)
 
  (defun MakeDirList (Arg / TmpList)
   
    (cond
      (
       (setq TmpList (cddr (vl-directory-files Arg nil -1)))
       (setq DirList (append DirList (mapcar '(lambda (z) (strcat Arg "/" z)) TmpList)))
       (foreach Item TmpList (MakeDirList (strcat Arg "/" Item)))
       (setq LstTL (cons TmpList LstTL))
      )
    );end cond
  );end MakeDirList

  (cond
   ((= (type Location) 'STR)
    (if (member (substr Location (strlen Location) 1) (list "/" "\\"))
      (setq Location (substr Location 1 (1- (strlen Location))))
    );end if
    (MakeDirList Location)
  ))
);end MakeFTree


3. where I shoud to add this: (dcl_Tree_AddParent ...) and (dcl_Tree_AddChild ...) in the code?
In my disk the folder trees look like:
c:\Bloki\Cars\
c:\Bloki\Cars\Os
c:\Bloki\Cars\Os\S1
c:\Bloki\Cars\Os\S1\S1.1
c:\Bloki\Cars\Os\S1\S1.2
c:\Bloki\Cars\Os\S1\S1.1\...  deep and deep
c:\Bloki\Cars\Os\S2
c:\Bloki\Cars\Os\S3
c:\Bloki\Cars\Tr
c:\Bloki\Cars\Tr\T1
c:\Bloki\Cars\Tr\T2
c:\Bloki\Cars\Tr\T2\T2.2\....  deep and deep
c:\Bloki\Cars\Cm
....
etc.



BazzaCAD

It's pretty difficult to populate the whole directory structure in one shot.
And if you try to do it on your forms "OnInitialize" and have lots of sub-folders, it can take a long time & cause your form not to show for a few seconds.
It's better to use the "OnItemExpanding" event and look at the next level down then add the children to that item.
Just like Win. Explorer does. Notice how it always has the "+" next to all the folder even when there's nothing in that folder.
Then when you click the "+" it goes away, since it now knows there's nothing under it....
I'll try to put an example together of this, since it's been asked a few times before.
a.k.a.
Barry Ralphs
barryDOTralphsATgmailDOTcom

JMack

#2
I totally agree with Bazza.

I really like the tree control.  A neat thing I've done with the tree control is create string keys that are actually functions.  When a user double clicks, exxpands, selects or does anything the string key is converted into a function and executes.  If there is no function nothing happens.
For example;

An item has a string key called "MyTitleBlockInitials".  When the user double clicks that item the this function executes (MyTitleBlockInitials_OnDblClicked TreeControl).  The tree control is also passd to the function so the function can manipulate the control if required.

Hopefully the below code is readable enough and can give a sense of what i've done.


;;Double Click Event
(defun c:HDResidential_frmHD_TreeControlSettings_OnDblClicked (/ strKey)
  (if
    (setq strKey (DCL_Tree_GetSelectedItem HDResidential_frmHD_TreeControlSettings))
    (HDF_ODCLTreeView_ExecuteKey (vl-princ-to-string strKey) "OnDblClicked" HDResidential_frmHD_TreeControlSettings)
  )
  nil
)
;;Item Expanding  Event
(defun c:HDResidential_frmHD_TreeControlSettings_OnItemExpanding (strtext strKey /)
  (HDF_ODCLTreeView_ExecuteKey (vl-princ-to-string strKey) "OnItemExpanding" HDResidential_frmHD_TreeControlSettings)
  nil
)
;;Helper function to execute the function related to the key
(defun HDF_ODCLTreeView_ExecuteKey (strTreeKey strFunctionType eTreeControl / fun strFunction varReturn)
  (setq strFunction (strcat strTreeKey "_" strFunctionType))
  (if
    (setq fun (eval (read strFunction)))
    (setq varReturn (eval (fun eTreeControl)))
  )
  varReturn
)

;;;sample function of a double click function
;;;when the user double clicked the tree item with the string key named "HDC_Update_SettingsAutoUpdateP" this function executes and changes the icon to checked or unchecked.
;;;There is a lot more to it but hopefully you can get an idea how to manage complex trees with string keys as functions.
(defun HDC_Update_SettingsAutoUpdateP_OnDblClicked (eTreeControl / varReturn)
  (if
    (HDC_Reg_GetSettingsKey "AutoUpdate")
    (HDC_Reg_PutSettingsKey "AutoUpdate" nil)
    (HDC_Reg_PutSettingsKey "AutoUpdate" 1)
  )
  (setq varReturn (HDC_Reg_GetSettingsKey "AutoUpdate"))
  (if
    eTreeControl
    (HDC_Settings_SetCheckMark eTreeControl "HDC_Update_SettingsAutoUpdateP" varReturn)
  )
  varReturn
)


Cheers

owenwengerd

Quote from: Zibster on February 01, 2008, 01:54:53 AM
But I need this TreeControl to fill up folders with automatically (μ-recursive function)

Have you considered using a file dialog form instead? That way you can let Windows do the work for you. :)
Owen Wengerd (Outside The Box) / ManuSoft

BazzaCAD

Quote from: owenwengerd on February 01, 2008, 03:53:19 PM
Quote from: Zibster on February 01, 2008, 01:54:53 AM
But I need this TreeControl to fill up folders with automatically (μ-recursive function)

Have you considered using a file dialog form instead? That way you can let Windows do the work for you. :)

Because it can't do cool stuff like this...


[attachment deleted by admin]
a.k.a.
Barry Ralphs
barryDOTralphsATgmailDOTcom

owenwengerd

Owen Wengerd (Outside The Box) / ManuSoft

BazzaCAD

a.k.a.
Barry Ralphs
barryDOTralphsATgmailDOTcom

owenwengerd

Quote from: BazzaCAD on February 01, 2008, 09:17:40 PM
Really can it? In it's current state?

It can, but you have to cheat and install a shell extension that creates the effect you're going for in Windows Explorer as well as all file dialogs.
Owen Wengerd (Outside The Box) / ManuSoft

DeanMc

I use to have the same problem (both with deep folder structures and with load times) BUT about a year ago I began using DOSLIB for almost all my file/folder tools (as well as some other functions).  Know I load an entire directory structure into the tree using mapcar and it's very fast.  In fairness to everyone I do "throttle" the loading of sub-folders (e.g. it only loads 5 folder deep) on the initial loading of the form.  I also have a general progress dialog that I use anytime one of my dialogs needs to indicate to the user it's "doing something".

Just some benchmarks for ya - I tested this method using DOSLIB in conjunction with the tree control to load the root of one of my terrabox external drives with approx. 560 GB stored and it took about 45 seconds (with the throttle turned on - 1.25 minutes with it off).

Also, I tested the shell extension mentioned before (cool idea by the way) the only draw back to it is if the drive is not indexed then it can take a little time for explorer to populate the files/folders (but that only depends on the capacity and performance of the workstation/network connection).

So, it's half a dozen in one hand, six in the other.  I prefer not using a shell extension because it's another loader I have to deal with during deployment and normalization.  DOSLIB is an ARX I can demand load and code against.  I also dont have to worry about users deleting or farting around with it.

Cheers

Zibster

Hi Owen,

can you show me example lisp and odcl code, how to use ActiveX "Microsoft Tree View Control 6.0 (SP4)" or others TreeView control?
What I should to write in here: 
(dcl_RegisterActiveXCtrl 
  ActiveXFileName [as String])
    ??

and this:
(dcl_AxObject_Release 
   OleObject [as List])
  ??

because I have error message... "no function definition: DCL_AXOBJECT_RELEASE" ...

I will be really thankful...
Zbyszek

Zibster

#10
Hi,

I still try to use ActiveX "mscomctl.ocx"  :-\


...
(dcl_RegisterActiveXCtrl "c:/windows/system32/mscomctl.ocx")
(dcl_AxControl_DoMethod bik_Bloki_frmBloki_TreeCtrl10 "c:/windows/system32/mscomctl.ocx")
(setq OleObject (dcl_AxControl_GetProperty bik_Bloki_frmBloki_TreeCtrl10 "Nodes"))(print OleObject)  ;return: <Nazwa elementu: 663b400>
(dcl_AxControl_SetProperty bik_Bloki_frmBloki_TreeCtrl10 "Nodes" "TEST")

(dcl_AxObject_Close)
...


after this line: (dcl_AxControl_SetProperty bik_Bloki_frmBloki_TreeCtrl10 "Nodes" "TEST") AutoCAD show message (attach). Can someone to explain me what I do wrong? Why in "Intelligent help":
AutoLISP Set Property Syntax:
(dcl_AxControl_SetProperty bik_Bloki_frmBloki_TreeCtrl10 "Nodes" NewValue [as INodes])

is nothing about VT_FONT and VT_BSTR, and what is it?

I was looking for this here: http://msdn2.microsoft.com/en-us/library/ms688421(VS.85).aspx
and http://msdn2.microsoft.com/en-us/library/aa443492(VS.60).aspx
but don't uderstand...

Zbyszek







[attachment deleted by admin]

owenwengerd

I am currently in the middle of making some changes to the way that intelligent help displays information about ActiveX controls. In Alpha 5, this change is not yet completed, and as a result you do not see the "INodes" interface listed in the intelligent help browser. In any case, the Nodes property is a type of ACtiveX interface called "INodes" (which is a collection of "INode" interfaces).

If you want to work with ActiveX objects, it would probably be useful for you to use a "type library browser" to view the type library of the object you're working with. Intelligent help attempts to display a minimal reference based on the type library, but viewing it in a type library browser will provide much more information (such as description text and help text where it is provided).

I'm not sure why the error message you received mentions the VT_FONT variant type, because that is not correct. VT_FONT is one of several dozen "variant types" in COM.

In the case of the tree control, I have no experience with it, however I'll try to provide some tips so you can experiment with it. I looked at the type library with a type library browser, and it shows me that the INodes interface has an 'Add' method that returns a new INode as follows:

(dcl_AxControl_DoMethod <tree-control> "Add" <optional Relative> <optional Relationship> <optional Key> <optional Text> <optional Image> <optional SelectedImage>)

The arguments are more fully described at:
http://msdn2.microsoft.com/en-us/library/aa443386(VS.60).aspx

To test the tree control, I tried the following:

(setq Nodes (dcl_AxControl_GetProperty <tree-control> "Nodes"))
; now Nodes is an OLE Object, and we use (dcl_AxObject_*) syntax
(Setq NewNode (dcl_AxObject_DoMethod Nodes "Add"))
; NewNode is also an OLE Object
(dcl_AxObject_SetProperty NewNode "Text" "MyNewTreeItem")
; this should work, but the call into the tree control fails with a COM error
(setq text (dcl_AxObject_GetProperty Node "Text")) ;this works fine
(dcl_AxObject_Close NewNode) ;release the node
(dcl_AxObject-Close Nodes) ;release the nodes collection

I'm not sure why the call to set the 'Text' property fails, but I will investigate this. The code above should work, and at least it can demonstrate the basic steps.
Owen Wengerd (Outside The Box) / ManuSoft