ExplorerTreeView 2.0 development diary

The place for threads about version 2.x of TimoSoft ExplorerTreeView.
User avatar
TiKu
Administrator
Administrator
Posts: 832
Joined: 28 Sep 2004, 21:10
Location: München
Contact:

ExplorerTreeView 2.0 development diary

Post by TiKu »

This thread is inspired by a similiar thread at the FileZilla forum. I'll use it to document the process of developing ExplorerTreeView 2.0.

What's done?
- basic treeview features like FullRowSelect, HotTracking, InsertMarkColor, SingleExpand...
- an IMEMode property as known from Microsoft .net
- properties concerning the label-edit field (BackColor, ForeColor, Text, IMEMode, HoverTime)
- 4 classes that wrap tree-items (TreeViewItem), collections of them (TreeViewItems, TreeViewItemContainer) and tree-items that got removed or not yet inserted (VirtualTreeViewItem)
- item management (adding, removing, filtering by some properties, moving by code 8-))
- MultiSelect 8-) (there're 2 modes: SingleLevel and Free)
- CustomDraw 8-)
- ToolTips
- background image support
- FavoritesStyle
- a HitTest() method
- callbacks for item captions, item icons and item buttons
- dozens of events covering all features that are implemented so far
- DisabledEvents (makes time-consuming events deactivatable)
- item sorting
- Drag'n'Drop
- OLE Drag'n'Drop
- property pages

What needs to be done?
- all shell stuff (at the moment it's just a plain treeview control)

What am I currently working on?
Nothing, because I've to learn for exams. :)

TiKu
Last edited by TiKu on 30 Jul 2005, 16:58, edited 12 times in total.
Crunching for Fab36_Folding-Division at Folding@Home. Join Fab36/Fab30! - Folding@Home and BOINC
Boycott DRM! Boycott HDCP!
User avatar
TiKu
Administrator
Administrator
Posts: 832
Joined: 28 Sep 2004, 21:10
Location: München
Contact:

Post by TiKu »

This week I finally finished the public documentation.:D My private one should get finished next week.
Crunching for Fab36_Folding-Division at Folding@Home. Join Fab36/Fab30! - Folding@Home and BOINC
Boycott DRM! Boycott HDCP!
User avatar
TiKu
Administrator
Administrator
Posts: 832
Joined: 28 Sep 2004, 21:10
Location: München
Contact:

Post by TiKu »

Yesterday I finally finished the code cleanup together with the private documentation. :cheers: Several bugs were fixed and several features were improved.
The next step is fixing some open bugs and background image support.
Crunching for Fab36_Folding-Division at Folding@Home. Join Fab36/Fab30! - Folding@Home and BOINC
Boycott DRM! Boycott HDCP!
User avatar
TiKu
Administrator
Administrator
Posts: 832
Joined: 28 Sep 2004, 21:10
Location: München
Contact:

Post by TiKu »

Background image support is complete. It's much better than it is in version 1.x. There're 6 properties:
1) BkImage As OLE_HANDLE
2) BkImageFixed As Boolean
3) BkImageHAlign As BkImageHAlignConstants
4) BkImageHTiled As Boolean
5) BkImageVAlign As BkImageVAlignConstants
6) BkImageVTiled As Boolean

(1) takes a bitmap handle. This means you can't set the background image at design time. But this way it is more flexible, so I don't see it as a big disadvantage.
(2) controls whether the background gets scrolled together with the content.
(3) controls the horizontal alignment of the background bitmap. Valid settings are left, center and right.
(4) controls whether the bitmap gets horizontally tiled. In this case the alignment (3) controls the anchor point of the tiles.
(5) controls the vertical alignment, valid values are top, center and bottom.
(6) controls whether the bitmap gets horizontally tiled. In this case the alignment (5) controls the anchor point of the tiles.

Did I forget any feature? :) If you don't need the new features, you'll love the new background image support anyway, because it's very much faster than in version 1.x and also doesn't have all those drawing bugs (e. g. version 1.x has some during scrolling and item expanding/collapsing).

What's next? Probably Favorites style, but I have not decided yet.
Crunching for Fab36_Folding-Division at Folding@Home. Join Fab36/Fab30! - Folding@Home and BOINC
Boycott DRM! Boycott HDCP!
User avatar
TiKu
Administrator
Administrator
Posts: 832
Joined: 28 Sep 2004, 21:10
Location: München
Contact:

Post by TiKu »

No day without new features. :D
Yesterday I implemented BlendSelectedItemsIcons - in version 1.x it is called DimSelectedItemsIcon. Today I implemented FavoritesStyle, which now produces less flicker than in version 1.x. There's also a new property GroupBoxColor which defines the color the FavoritesStyle's grouping box rectangle is drawn in.

I don't know whether development will continue with the speed of the last 10 days. There're other tasks in my life that I have to do. But I'll try to get Beta 1 out before the end of this year. I know I originally promised it for fall 2003 :oops: and I already gave ExplorerTreeView 2.0 the codename "Duke Nukem" :buck:, but I better release late than never. ;)
So stay patient.

What's next on the list? Probably tooltips.
Crunching for Fab36_Folding-Division at Folding@Home. Join Fab36/Fab30! - Folding@Home and BOINC
Boycott DRM! Boycott HDCP!
User avatar
TiKu
Administrator
Administrator
Posts: 832
Joined: 28 Sep 2004, 21:10
Location: München
Contact:

Post by TiKu »

Tooltips are working. It's working different from version 1.x, but the possibilities are the same.

I've found a small design problem that may produce buffer overflows in the ANSI version. Fixing this is the next thing - followed by the DisabledEvents property that is partially implemented already. This property lets you deactivate all events that are used seldom, but have a big negative influence on performance.
Crunching for Fab36_Folding-Division at Folding@Home. Join Fab36/Fab30! - Folding@Home and BOINC
Boycott DRM! Boycott HDCP!
User avatar
TiKu
Administrator
Administrator
Posts: 832
Joined: 28 Sep 2004, 21:10
Location: München
Contact:

Post by TiKu »

The design problem got fixed and the buffer overflows should be gone. Also the DisabledEvents property is complete.

The following events may get disabled:
- MouseDown, MouseUp, MClick, MouseEnter, MouseHover, MouseLeave, ItemMouseEnter, ItemMouseLeave, MouseMove
- Click, DblClick, MClick, MDblClick, RClick, RDblClick
- EditMouseDown, EditMouseUp, EditMouseEnter, EditMouseHover, EditMouseLeave, EditMouseMove, EditClick, EditDblClick, EditMClick, EditMDblClick, EditRClick, EditRDblClick
- KeyDown, KeyUp, KeyPress, IncrementalSearchStringChanging
- EditKeyDown, EditKeyUp, EditKeyPress
- InsertingItem, InsertedItem
- RemovingItem, RemovedItem
- FreeItemData
- PreCustomDraw, PostCustomDraw
- ItemGetInfoTipText
You disable them in groups. Each dash is a group containing the events behind it.

Next: Item sorting.
Crunching for Fab36_Folding-Division at Folding@Home. Join Fab36/Fab30! - Folding@Home and BOINC
Boycott DRM! Boycott HDCP!
User avatar
TiKu
Administrator
Administrator
Posts: 832
Joined: 28 Sep 2004, 21:10
Location: München
Contact:

Post by TiKu »

Problem with sorting
Damn, we have some kind of problem with item sorting. Let me explain...
To sort a Windows treeview alphabetically in ascending order, you just need to send a message to it and it will sort itself.
If you want to sort it in descending order or by let's say the indices of the state images or whatever, you'll have to use custom sort. This is done by sending a different message which also tells the treeview the address of a callback method to use. This method gets called if 2 items must get compared. It receives the lParam's of those items and returns a value indicating which item should stand first. An item's lParam is the Long value that you access through TreeViewItem.ItemData in ExplorerTreeView 2.0.
So all I have to identify the items during sort are their ItemData values - which are not necessarily unique and usually 0. This really sucks, because it makes it almost impossible to provide powerful sorting features AND let the user associate any Long value with any item.

I already have a solution in my mind, but it will decrease performance and I'll have to change many things.
Crunching for Fab36_Folding-Division at Folding@Home. Join Fab36/Fab30! - Folding@Home and BOINC
Boycott DRM! Boycott HDCP!
User avatar
TiKu
Administrator
Administrator
Posts: 832
Joined: 28 Sep 2004, 21:10
Location: München
Contact:

Post by TiKu »

Last night I implemented everything that's required for custom sorting. Now each item gets an unique ID that never changes (even if the item is moved). The TreeViewItem.ID property replaces the TreeViewItem.Index property. The index was faster, but could change if other items get removed. So actually the unique ID feature not only makes custom sorting possible, but also is more useful in general.
How does the whole thing work now? The TVM_INSERTITEM message gets intercepted, if sent to the SysTreeView32 window. I store the item's lParam in an internal hash map and replace it with a generated unique ID before I forward the message to the SysTreeView32. TVM_GETITEM and TVM_SETITEM messages get intercepted, too. In these cases I return/update the lParam right out of/in the hash map and the SysTreeView32 will never see the message. So the SysTreeView32 stores the item's unique ID as its lParam whereas my code hides this ID from the rest of the system and presents the 'real' lParam instead. It's not 100% reliable (there're some ways to fool my code), but it should work for ~99% of all use cases.

So items now have something like the Key property of the treeview that comes with MS Windows Common Controls. The only difference is that the id gets chosen by the control itself and that it is an integer value instead of a string. String IDs and/or userdefinable IDs would make it too complicated and too slow.

BTW, I also noticed (and fixed it) that the item moving feature crashed with an access violation in the last builds.
Crunching for Fab36_Folding-Division at Folding@Home. Join Fab36/Fab30! - Folding@Home and BOINC
Boycott DRM! Boycott HDCP!
User avatar
TiKu
Administrator
Administrator
Posts: 832
Joined: 28 Sep 2004, 21:10
Location: München
Contact:

Post by TiKu »

Item sorting is working.
There's a property SortOrder which can be set to either ascending or descending. The ExplorerTreeView class has a method SortItems and the TreeViewItem class has one called SortSubItems. Both take up to 4 sorting criteria, a flag indicating whether text compares shall be case sensitive and another one indicating whether sub-sub-items shall be sorted recursively.
There're 4 predefined sorting criteria:
- Text
- Selection state
- State image index
- Custom
If the last one is used, the CompareItems event gets fired that lets you do whatever you want to sort the items.
How are the sorting criteria chosen? They are used in the same order you pass them to the SortItems/SortSubItems method - until the items differ in one of them.

Is this sorting support powerful or not? ;) :twisted: Okay, you have to invoke sorting yourself, but I can't think of a scenario in which automatic sorting would be faster.

Well, now the last missing feature before Beta 1 seems to be Drag'n'Drop.
Crunching for Fab36_Folding-Division at Folding@Home. Join Fab36/Fab30! - Folding@Home and BOINC
Boycott DRM! Boycott HDCP!
User avatar
TiKu
Administrator
Administrator
Posts: 832
Joined: 28 Sep 2004, 21:10
Location: München
Contact:

Post by TiKu »

I'm afraid, Drag'n'Drop will need "some" time. MultiSelect makes it even more difficult than it is anyway. The main problem is to design the control's Drag'n'Drop interface in a way, so that it is easy to use, but still very powerful. OLE Drag'n'Drop will probably complicate it even more.
Crunching for Fab36_Folding-Division at Folding@Home. Join Fab36/Fab30! - Folding@Home and BOINC
Boycott DRM! Boycott HDCP!
User avatar
TiKu
Administrator
Administrator
Posts: 832
Joined: 28 Sep 2004, 21:10
Location: München
Contact:

Post by TiKu »

Non-OLE Drag'n'Drop is... ...well... ...if you're mild, you could call it working. :crazy:

How to start dragging?
There's an event that will notify you if the user starts dragging an item. In response to this event you'll call a method called BeginDrag, which takes a container object with the items to drag and a handle to the imagelist that contains the drag-image. A drag-image? Woohoo! :D Don't ever use it. :crazy: The Windows treeview control has some ugly drawing bugs if things like drop-highlighted items, insertion marks and a drag-image are used together. Without an insertion mark, the drag-image is drawn okay, but flickers a little bit.

Dragging...
Well, where did I stop? BeginDrag... Once you called this method, the DragMouseMove event will get fired on mouse moves. It's probably the best piece of code of the whole Drag'n'Drop support so far. It gives you anything you need to set the drop-highlighted item (i. e. to highlight the potential drop-target as such) and/or to set the insertion mark.

Aborting or dropping
At first you should know that pressing Esc or releasing the left mouse button must be handled by *your* code. I don't really like this solution either, but on the other hand it gives you more control. However, if you want to stop Drag'n'Drop, you just call EndDrag. It takes a Boolean parameter that indicates whether to abort the whole thing. Depending on this parameter, either the AbortedDrag or Drop event gets fired. Both should contain clean-up code like clearing the insertion mark or the drop-highlight selection. In response to the Drop event you should also perform the Drop itself. ExplorerTreeView 2.0 supports item moving by code, so this task is very easy.

What's still not working are expand-on-drag-over and scroll-on-drag. Also the CreateDragImage method can't create a drag-image containing more than one item.

Within the next days, I'll improve some other areas of the control. I need a break from Drag'n'Drop.

Any questions? OLE Drag'n'Drop? Are you joking? :lol: No, seriously, OLE Drag'n'Drop is still far away.
Crunching for Fab36_Folding-Division at Folding@Home. Join Fab36/Fab30! - Folding@Home and BOINC
Boycott DRM! Boycott HDCP!
User avatar
TiKu
Administrator
Administrator
Posts: 832
Joined: 28 Sep 2004, 21:10
Location: München
Contact:

Post by TiKu »

I've redesigned parts of Drag'n'Drop during the last week. Now it's good enough so that I'll start implementing OLE Drag'n'Drop. I've also rewritten the mouse-event detection, so some events behave different now. This step was necessary for Drag'n'Drop.

Here's how Drag'n'Drop is working now:
How to start dragging?
There's an event (ItemBeginDrag) that will notify you if the user starts dragging an item. In response to this event you'll call a method called BeginDrag, which takes a container object with the items to drag and a handle to the imagelist that contains the drag-image. The drag-image still shouldn't be used for Non-OLE Drag'n'Drop, because of the drawing bugs.

Dragging...
Once you called BeginDrag, the DragMouseMove event will get fired on mouse moves. Highlighting the potential drop-target and setting the insertion mark must be done explicitly now. The event proposes a drop-target. If you don't like it, change it.
Auto-expanding and -scrolling gets done via the event: You set a flag whether to auto-expand the potential drop-target. In detail, auto-expansion works as follows: The control has a property DragExpandTime, which defines the number of milliseconds that the control will wait before auto-expanding an item. The code, that fires the DragMouseMove event, checks whether the drop-target is another one than the last time the event was fired. If it changed, the auto-expansion timer is started. If the drop-target changes or if you set the mentioned flag to False before the timer expires, auto-expansion is canceled for this item. Otherwise it gets expanded.
Auto-scrolling works similiar: There's a property DragScrollTimeBase. The DragMouseMove event asks you for the relative scrolling speed and direction for horizontal scrolling as well as for vertical scrolling. The real scrolling speed is calculated using the DragScrollTimeBase and the value that was returned from the event. So if you want it, you can highly customize the scroll-sensitive zone (the default is a 16 pixel wide belt around the client area) and even change scrolling speed depending on the mouse cursor's position. :D

Aborting or dropping
Pressing Esc or releasing the mouse button must still be handled by *your* code. If you want to stop Drag'n'Drop, you just call EndDrag. It takes a Boolean parameter that indicates whether to abort the whole thing. Depending on this parameter, either the AbortedDrag or Drop event gets fired. What you do in response to these events is up to you.

What's next? I'll improve the item-moving feature (I mean the TreeViewItem.Move() method) to make it easier to use. Creating drag-images that contain multiple items needs to be done, too. Well, and of course OLE Drag'n'Drop.
But development will slow down until March 1st, because I have to learn for a very difficult and very important test.
Crunching for Fab36_Folding-Division at Folding@Home. Join Fab36/Fab30! - Folding@Home and BOINC
Boycott DRM! Boycott HDCP!
User avatar
TiKu
Administrator
Administrator
Posts: 832
Joined: 28 Sep 2004, 21:10
Location: München
Contact:

Post by TiKu »

Creating drag-images that contain multiple items is implemented now and I've also completed the improvements to the item-moving feature.
I've detected a complex bug that occurs if MultiSelect gets used together with drag'n'drop. To fix it, I'll reimplement the WM_*BUTTONDOWN and WM_*BUTTONUP handlers one more time.
MultiSelect causes so much trouble that I'm very glad that I've put the whole MultiSelection stuff into #ifdef's, so that I can compile the control without this feature. And that's exactly what I'll do if problems continue. :angry:
Crunching for Fab36_Folding-Division at Folding@Home. Join Fab36/Fab30! - Folding@Home and BOINC
Boycott DRM! Boycott HDCP!
User avatar
TiKu
Administrator
Administrator
Posts: 832
Joined: 28 Sep 2004, 21:10
Location: München
Contact:

Post by TiKu »

I'm currently rewriting great parts of MultiSelect support. At the moment it seems to work for left mouse-button navigation without bugs. It even seems to not interfere with label-editing, SingleExpand and Drag'n'Drop.:)
I hope to get MultiSelect for navigation with the right mouse button done before Monday. MultiSelect support for keyboard navigation needs to be done, too.
Besides that I fixed many bugs.

I wonder when the day will be, that I can start with OLE Drag'n'Drop... :dontknow:
Crunching for Fab36_Folding-Division at Folding@Home. Join Fab36/Fab30! - Folding@Home and BOINC
Boycott DRM! Boycott HDCP!
Post Reply