System Control Pack v0.98.5 Beta
This is BETA software. It is not guaranteed to do ANYTHING useful at all.
R E A D T H I S N O W ! ! !
I hope that got your attention. This component requires a unit that
provides access to the Win95/NT 4.0 Shell Namespace API. Delphi 2.0 did not
include this import, but the v2.01 update does. Also, Mr. Pat Ritchey was
kind enough to write one, which I think was the basis for Borland's (same
bugs in both units, must be the same). C++Builder 1.0's ShlObj.pas also suffers
from the same problems. Regardless of which you use, you will have to do some
extra work because both contain errors that will prevent this component from
working properly (or even compiling, probably). To implement these changes,
read the ShellFix.txt file that should have been included with this file.
If you use Delphi 3 or higher, or C++Builder 3 or higher, you will not need to
worry about any of this. No bugs (that effect these components anyway).
Description:
Tree view, list view, and combobox controls that act like the controls in the
Windows Explorer.
Contact Information:
The lateset version will always be available on the web at:
http://www.delphifreestuff.com
If you have any questions, comments or suggestions, please use the Delphi
Free Stuff Support Forum at:
http://www.delphifreestuff.com/discus/
If, for some reason, you can not use the web-based support forum, you can
email me at bstowers@delphifreestuff.com. However, the support forum will
always take precedence over direct email since it provides a resource that
others can use when they have a problem. Every message posted to the forum
is emailed directly to this account, so emailing me directly will not get
your message to me any faster. It will only make the message less important
for me to respond to since only one person (you) is benefiting from it
instead of everyone interested. Having said all that, please do email me
directly if it is regarding something that isn't really support related,
i.e. just to say thanks (as novel as that idea is).
Installation:
Delphi 1:
* This component is not compatible with Delphi 1.
Delphi 2, C++Builder 1:
* Select the 'Component | Install' menu item.
* In the Install Components dialog, click the Add button.
* In the Add Module dialog, enter the full path name of the component's
registration unit (the unit that ends with 'Reg.pas', i.e.
'BrowseDrReg.pas') and click OK.
* In the Add Module dialog, click OK.
* The component library will be rebuilt and a new tab named 'DFS' will be
available on the Component Palette.
Delphi 3, 4, 5, C++Builder 3 & 4:
* Do one of the following:
+ Create a new package by selecting File | New and choosing Package from
the New tab in the dialog.
+ Open an existing package file. I suggest you do this if you already
have a package that you like to use for small, third party components.
I specifically have a package named "3rdParty.dpk" that I use for
small components that come from other people. Or, if you are using
several of my components, you might create a "DFS.dpk" package and
use it for all of my DFS components.
* In the resulting package window, click the Add button.
* In the Add dialog, on the Add Unit tab, enter the full path name of the
component's registration unit (the unit that ends with 'Reg.pas', i.e.
'BrowseDrReg.pas') and click OK.
* You may want to add the other source files (*.pas) to the package as
well in the same manner as you did the registration unit. While this is
not required, not doing it will cause compiler warnings when the package
is compiled. The component will function fine either way, but I
personally find the warnings very irritating and am not happy until
every compiler warning and hint is gone. NOTE: If you use C++Builder 3,
do not install the other source units. See Known Issuses section below.
* If this package is new, or it has never been installed, click the
Install button in the package window. If this package is already
installed in Delphi, click the Compile button.
C++Builder 5 and up:
* Perform the "Delphi 3 and up, C++Builder 3 and up" steps above, except
for the last step (Compile or Install).
* Select the package the component has been added to, and choose
Project | Edit Option Source to open the package options in the editor.
* In the entry for PFLAGS, add the "-LUvcl50" option. For example:
* Perform the final step from above, Compile or Install.
* For Borland's official word on this situation, open the C++Builder help
file and search the index for "dsgnintf.dcu" and see the "Compiling
packages with DsgnIntf" section.
Delphi 6 and up:
* Perform the "Delphi 3, 4, 5, C++Builder 3 & 4" steps above, except
for the last step (Compile or Install).
* Add the DesignIDE package to the Requires list of the package into which
the component is being installed.
* Perform the final step from above, Compile or Install.
* This is necessary because of changes to the design-time support units
introduced in Delphi 6. For complete information, see the Del6New.hlp
file in your Delphi 6 Help directory. In the index, search for
"upgrade issues" and in the resulting list of topics, select the
"DsgnIntf renamed and related changes" topic.
Conditional Defines:
These units makes extensive use of conditional defines to control many aspects
of how and what things are compiled. Usually these are used to effect code
size or change how a feature works, but some are also for debugging purposes.
The following is a list of the defines that are used and how. These defines
are all found in the SystemControlPack.inc file. The prefix used in each
name identifies what is effected:
DFS -- Prefix I use for all my defines to avoid clashing with other
defines that may be in use. DFS = Delphi Free Stuff
SCP -- Indicates that the define effects all components. SCP = System
Control Pack
STV -- Indicates that the define effects only the TSystemTreeView
component. STV = System Tree View
SLV -- Indicates that the define effects only the TSystemListView
component.
SCB -- Indicates that the define effects only the TSystemComboBox
component. Currently, there are none of these.
The defines used are as follows:
* DFS_SCP_SYSTREEVIEW, DFS_SCP_SYSLISTVIEW, DFS_SCP_SYSCOMBOBOX: If you
undefine any of these, then that/those components will no longer be
compiled. For example, if you undefined DFS_SCP_SYSLISTVIEW, the
TSystemListView component will not be compiled, and the tree view and
combo box components will no longer have a ListView property to link to.
This resulted in a 70k saving in the compiled EXE of a test app that used
only the TSystemTreeView component. The down side to this is that if you
use TSystemListView for some projects and not for others, you will either
have to leave it enabled for all, or have one heck of a code maintenance
nightmare. One solution to this could be to remove the
DFS_SCP_SYSLISTVIEW define from the include file completely and add it to
the Project | Options | Directories/Conditionals of the design-time
package you install the component in. Then, you would add
DFS_SCP_SYSLISTVIEW to the options of the projects that need it, and leave
it out of those that don't. This would allow you to control what is
compiled into the Delphi IDE independant of what is compiled into your
projects without having to change the SystemControlPack.inc file in
between. I have not tested this solution, but it works in theory. :)
* DFS_STV_FASTMODE and DFS_SLV_FASTMODE: These defines are not enabled by
default. If you enable them, the components will populate/display much
faster. The reason is that the actual item data such as the Caption and
subitem text, the image index, etc. aren't retrieved when the list/tree is
populated. Instead, the system will ask (via a CN_NOTIFY message) for the
data when it needs a particular item's data and it is supplied only then.
So, it doesn't take nearly as long to add a large number of items. But
(there's always a price to be paid), you will lose access to this data via
the Nodes (treeview) or Items property (listview). That means you won't
be able to do stuff like:
ShowMessage(MySysListView.Items[0].Caption);
However, you will still be able to do the equivalent using stuff like:
ShowMessage(MyList.GetFullPath(MyList.Selected));
So, if you need the text or image index stuff, leave the define off. But,
if you don't, turn it on by removing the period and it'll be faster. In my
informal testing, listing my windows directory went from 12 seconds to 2
seconds. You'll only see these big gains on directories with a lot of
files, though. Many thanks go to Andei V. Rasskazov for pointing this
technique out.
* DFS_SLV_USE_ENHLISTVIEW and DFS_SLV_USE_EXTLISTVIEW: These are not enabled
by default. They are useful only if you also have my TEnhListView and
TExtListView components. You will need v3.13 or later of these components
for this to work. Enabling ONE of these (never enable both) will cause
TSystemListView to descend from the corresponding TEnh/ExtListView class,
giving you all of that class' features as well. WARNING: This is just a
simple implemenation currently, and there are likely to be problems. Only
use these if you want to help me work out the bugs in it. Defining either
of these will also cause DFS_SLV_USING_ELV to be defined. I use this
internally when I want to know if either of the above are defined and
I don't care which one. You should not define DFS_SLV_USING_ELV yourself.
* DFS_STV_FILECHANGES: Controls whether the treeview will "watch" the
directory that is currently displayed for changes, i.e. a new directory
or file created, an existing one deleted, etc. and automatically refresh
when this happens. This was originally put in so that this feature could
be turned off during development if nasty bugs were found. However, that
was quite a while back, and "change watching" seems to be quite stable
now. The only reason you might want to turn it off now is to save
yourself the 3.5 kb of space it adds to your compiled EXE. This define
will probably be removed entirely unless someone makes a strong case for
leaving it.
* DFS_DEBUG: This is a define that I use internally for debugging the
components. It causes a unit to be used that is not distributed, so it
is most likely useless to anyone but me.
Working Notes:
* I really need to rip all the namespace stuff out and put it in it's own
class so that you could use it however you wanted, not just in this comp.
* The included test project creates a TSystemTreeView object on the fly so
that you don't have to install the component in your library. I'm
fairly confident that the component is stable, but if you don't want to
install, you don't have to just to see the demo.
* If anyone knows how to determine the type of object you have given it's
PIDL, I'd love to know it. Right now, if it's not a file system object,
you just get it's name. I need to determine other types like the
printer folder, control panel folder, network servers, network
workgroups, etc.
New information: I've noticed that a commercial Explorer replacement that
I have (PowerDesk from Mijenix) has this exact behavior, i.e. if you select
the Printers folder, Recycle Bin, etc. you get just a single "Name" column.
Hey, if a bunch of paid programmers can't figure it out, I probably won't
either, so I'm inclined to call this "as-designed" behavior. Comments?
Items On The To-Do List:
* A few more bugs still in my email.
* CMF_CANRENAME flag for context menu. Can't just add it as it will cause
OLE errors, i.e. system won't handle it. I need to determine if I can
use "magic numbers" to interpret rename and other unhandled commands to
to catch them and process them myself.
* Use timeGetTime to decide if I should show the hourglass or not in
EnumerateFolders methods.
* Change GetItemAttrs so it uses a nice Delphi set instead of API values.
* Do away with ShowFolders/Files and ShowHiddenFolders/Files properties
and replace with a set that includes all the stanadard stuff: hidden,
system, read-only, etc. AttrMask property.
* Add properties for the stuff in the registry key HKCU\Software\Microsoft\
Windows\CurrentVersion\Explorer\Advanced and use those values as default
values for the properties. This has stuff like hide extensions, etc.
* I may or may not implement drag/drop with the shell. In the meantime,
Dieter Steinwedel (dsteinwe@rz.uni-osnabrueck.de) has a fine d-n-d shell
component that works with any TWinControl descendant. It can be found at
http://godard.oec.uni-osnabrueck.de/student_home/dsteinwe/delphi/DietersDelphiSite.htm
There are probably others as well, I haven't looked much.
* "Cut" context menu command does not show the file icon as disabled yet.
* Hidden files have same problem as cut files (item above).
Known Issues:
* C++Builder 3 users: You must install only the registration unit
(SystemControlPackReg.pas) into the package you compile the component into.
If the package also includes the other source files, you will get error
messages about DCLSTD35.LIB, which doesn't exist. It has to do with the
fact that the source lists ImgList in the uses clause, even though I have
properly $IFDEFed it out. Must be some error in the C3 parser that is
causing it to see this unit, and in C3 this unit is some design-time unit or
something. It results in the IDE continuously inserting DCLSTD35.LIB into
the project file, and there's no such file. Manually removing it from the
project does not help, it just sticks it back in. The only way to get it to
stop is to manually edit the code and remove the reference to ImgList, or to
not include the source file in the package. Bizarre.
* C++Builder 3 users: You must edit the source files to remove the ImgList
unit from the uses clauses of the units. I have properly $IFDEFed out
this unit, but some error in the C3 parser is causing it at some point to
see this unit, and in C3 this unit is some design-time unit or something.
It results in the IDE continuously inserting DCLSTD35.LIB into the project
file, and there's no such file. Manually removing it from the project
does not help, it just sticks it back in. The only way to get it to stop
is to manually edit the code and remove the reference to ImgList. Bizarre.
* None of the demos are probably going to work well with all the new stuff.
It's late and I really want to get this stuff out, so I'll update them
in the next version.
* The list view incorrectly thinks that some folders contain file system stuff
when the really don't. For example, it thinks the Control Panel folder
does, so it get's all the columns for a file directory list. This is a bug
introduced with the new way of doing things in v0.96 and I've not yet been
able to figure it out. If anyone has any clues, I'd really appreciate it.
It didn't happen in v0.95, but things were a lot different in the list
population in that version.
* Combo box does not like working with a treeview that doesn't have rfDesktop
as it's root node. I'm not sure if you'd really ever need to have a combo
that used something besides the desktop as a root, so at this point and not
going to invest the somewhat large amount of time to work on doing it. If
you do need this, let me know and I'll add it to the to-do list.
* The tree is hitting the all the sub nodes of a just expanded node again.
For example, when you expand the "My Computer" node, it hits each item; one
of those is likely a floppy drive, and that slows things down as it cranks
on it for a second. No error message, but the delay is irritating. And I
fixed it once before, too!
* Changing the RootFolder of a tree doesn't update a linked listview at design
time. This saved me a ton of work, and it's really not that important at
design-time anyway, is it?
* Double clicking on a computer name in a listview that is linked to a
rfNetHood rooted treeview will not move into that computer.
* If using the Checkboxes property and you cause the treeview window to be
recreated by doing something like changing the BorderStyle property or
something, the checked values will be lost. I will fix this in the future.
* Changing the Color property to anything other than clWindow is strongly
discouraged. The images will still use the clWindow color as their
background, so you'll end up with a pretty odd looking tree/list. The
reason is that if I changed the background color of the image list(s), it
would effect the entire system. That is, Explorer would then have a
tree/list with a clWindow background color but the images would have your
new color around them. The image lists are a shared, system-wide resource
and a change like this simply can not be allowed. There is one alternative:
a copy of the system image list can be made, and that used instead of the
real system image list. It can be changed in any way without effecting the
rest of the system. The problems I have with this are: 1) It's an awful
lot of trouble to implement, 2) It's generally very slow since the system
image list is quite large. You'd have a delay of a second or three before
your app started. If enough people ask me for this to be added, I will
reconsider, but for now I'm just considering it a known issue.
Beta Revision History:
0.98.5 + Added RecreateColumns method to TdfsSystemListView.
+ Fixed problem with SetColumnWidths not using new values until window
was recreated or repopulated.
+ Updated for Delphi 6 compatibility. See updated install directions
above.
0.98.4 + Updated for C++Builder 5 compatibility.
0.98.3 + IShellDetails stuff in SystemControlPack.pas has been removed. I was
investigating this, but found out it was only available on Windows
2000. It was causing compiler problems for C++Builder, so I've
removed it from the source entirely (it was never being used).
+ Fixed problem with FileMask in tree view.
+ Fixed memory leak problem with list view.
0.98.2 + Fixed some nasty problems with rfFileSystem RootFolder type.
+ Fixed bizarre D5 problem with deleting a tree from a form in the IDE.
+ Fixed problem with main win hook not being released when component
was destroyed. Thanks to Matthieu Roger for this.
0.98 + Fixed redeclaration problem in C++Builder 3.
+ Fixed nasty recursion bug when using rfFileSystem RootFolder value.
+ Bill Miller was nice enough to do a component bitmap for the combo box.
+ Had some problems with right-click not bringing up the context menu
in the system and list view under D5. Fixed.
+ Deleting a file in a root directory would cause the list view to "fall
up" one level higher that where it was supposed to be on refresh.
+ Fixed a couple of problems having to do with the read delay timer.
Could totally break it if window handle was recreated. Could get
"Control has no parent window" errors.
+ Changing treeview file mask to exclude the currently selected filename
would cause trouble.
+ Removing a directory that was the selected directory would not refresh
the display.
+ Updated information about the DCLSTD35.LIB Known Issue in C3. See
above.
+ I've removed the TFolderItemData.FileSize property for C++Builder 1 &
3. They didn't work because I use the Delphi Comp data type, and
while Builder has a Comp class for this type of thing, it won't
automatically support Delphi code using Comp. If you need the file
size in C1/C3, you'll have to use the FileSizeHigh and FileSizeLow
properties. If FileSizeHigh is not zero, you know you have a big file
and that you'll have to do the 64-bit math yourself.
+ Resetting would not always do a "full" reset. The system will cache
some kinds of information, and you have to manually invalidate that
cache. The most obvious manifestation of this problem was with a
CD-ROM drive. Resetting would update the item's image, but would not
update it's text.
+ Changing a CD would not update the display.
+ Tree and list view item context menus now show and handle the Rename
context menu item.
0.97 + Delphi 5 compatibility.
+ Renamed to include the 'dfs' prefix in the component name.
+ The DFS_STV_FASTMODE and DFS_SLV_FASTMODE defines were broken (code
wouldn't compile). Thanks to Felipe Rocha Machado for catching this.
+ Sort column/direction of list view wasn't preserved when directory was
changed.
+ Added ChangeToParent methods in tree, list and combo to move up one
level, i.e. "cd .."
+ Added Known Issue item for C++Builder 3 users. See above.
+ Changing FileMask property of listview at run-time would not refresh
the list. Fixed. Thanks to Tamas Demjen for this.
+ DFS_SLV_FASTMODE conditional define has been removed.
+ Setting the tree view Selection property to a UNC path wouldn't work
correctly (i.e. something like \\someserver\somepath\someotherpath).
Lennert Ploeger was kind enough to figure out what was going on and
fix it.
+ FileMask in the tree view was totally broken. Lennert also help on
this one.
+ I think I finally got rid of that pesky removable drive spinning when
it's parent is selected once and for all.
+ Tamas Demjen sent me code to make the combobox respond better to font
changes.
+ Nasty problem fixed when something caused the combobox to be recreated.
Thanks to Joachim Jo Samstag for his help on this.
+ Under Delphi 2, 3, C++Builder 1, and 3 the Color property would not be
honored by the tree or list because of a VCL bug. This was fixed in
version 4 (of both). I've added code sent to me by Chris Wallace to
work around it in prior versions. Many thanks to him.
0.96 + Moved a lot of PItemIDList helper functions into a seperate unit named
PidlHelp. This is mostly an internal thing, and shouldn't effect
component users.
+ Marked public Reset methods as virtual for you folks who want to write
descendants.
+ Now includes a TSystemComboBox written by Andrew Barnes. Andrew was
kind enough to share this with the rest of us and give me permission
to include it in this package. Huge thanks go to him. Read the
comments at the top of SystemComboBox.pas for full information.
Also, this is just the first crack at the combo. There are bound to
be problems, so please report them and provide as much info as you can
so I can duplicate them. Some are already known, see the Known Issues
section.
+ Since Andrew has provided us with the last missing piece (the combo),
I've renamed this thing the "System Control Pack". SystemTreeView was
becoming ever more inadequate as a name.
+ Because the SystemTreeView.pas file was growing ever more out of
control (144k in the last version), and because of some unit reference
issues, I decided to break up everything into smaller, more manageable
units. SystemControlPack.pas now defines base virtual classes for all
the controls that define and implement how they interact with each
other, but implement none of the shell functionality. Each control is
implemented in its own seperate unit descending from these base
classes. Because of all the unit additions/changes/deletions, users of
previous versions should review how the component is installed. Here
is the status of all the unit files in the package now:
SystemControlPack -- New
SystemTreeView -- Heavily modified
SystemListView -- New
SystemComboBox -- New
SystemViewReg -- Deleted (see next)
SystemControlPackReg -- New (renamed SystemViewReg unit)
PidlHelp -- New
SystemView.inc -- Deleted (see next)
SystemControlPack.inc -- New (renamed SystemView.inc and modified)
Delphi 3+ and BCB 3 users, update your packages accordingly.
+ Because all of the major changes being made, I updated the $DEFINE
names to more accurately reflect what they effect. See the
"Conditional Defines" section above for the new names.
+ The $IFDEFs that checked to see if COM objects needed to be manually
reference counted used DFS_COMPILER_2. This was technically correct
as it only needs to be done in Delphi 2 and C++Builder 1, but I've
changed it to use {$IFNDEF DFS_NO_COM_CLEANUP} to more accurately
show what is going on there.
+ TSystemListView is not as tightly integrated with TSystemTreeView as
in previous versions. This a first step towards making it work
completely on its own. However, it is just a first step. It needs
further testing, and some enhancements I'm sure. Please send feedback
if you fool with this issue at all.
+ The new stuff introduced a new bug in the list view, see Known Issues.
0.95 + FileMask property only worked if the system were set up to display
file extensions (in Explorer, View | Folder Options | View tab | "Hide
file extensions for known file types" checkbox was unchecked). This
has been fixed, and FileMask now works properly regardless of this
setting. Note that the setting still effects how the file is displayed
(extension shown or not).
+ File sizes in the list view weren't "commaized". That is, "4305 KB"
was displayed instead of "4,305KB".
+ Large file sizes are now handled properly. In D4, the Int64 type is
used. All others use the Comp type since Int64 isn't available.
+ Updated William Miller's DFSExplorer demo project. See the
DFSExplorerReadMe.Txt file contained in the DFSExplorer.zip file for
his release notes.
0.94 + Even though you could move through a removeable drive without a disk
in the tree with the ReadDelay property, it would still "spin up" when
you hit. It just wouldn't generate an error message. This has been
fixed so that it doesn't "spin up" at all unless you've stopped on it
long enough for it to populate (ReadDelay).
+ Rewrote the TSystemListView.AddNode to make it a bit more efficient and
less messy.
+ I was having sporadic problems with the images not being transparent on
my system. I never could determine if it was my code, or some other
app that was causing it. I've added a little more code to the image
list stuff, and the problem doesn't seem to be occuring now, but as
I said it was sporadic to begin with.
+ The controls did not handle system color changes well. This appears to
be a bug I inherited from the VCL. The window background would change
to the correct color, but the background around the text would not.
I've worked around the problem.
+ I wasn't calling inherited in my WM_TIMER handler. This broke the
automatic editing of tree nodes when user clicked twice in a node.
+ If the tree is reset, it will now remember the selected node. If the
listview is reset, it will remember the focused item.
+ ReadDelay is a little smarter now. It won't delay at startup since
that's pretty silly. It also won't delay on a manually refresh (a
call to the Reset method), since you really wouldn't want it to delay
there either.
+ Added known issue about using the Color property (see above).
+ Added DFSExplorer demo project. A nicer version of the SimpleExplorer
demo written by William Miller.
0.93 + Added a new demo project, SimpleExplorer. It's your basic Explorer
clone, but on a light scale. No toolbar, no Favorites menu, only basic
menu item commands. Just to illustrate that it doesn't take much code
to get basic Explorer functionality with the components. One note: I
used a TSplitter in it, so Delphi 2 is going to complain about that
since it didn't come with Delphi until v3. Just go along with what
Delphi wants to do when you open the project in D2, and it should
compile and run fine, sans splitter of course.
+ Version property now marked as not stored. Doesn't need to be, and
only increases DFM size. Should have always been that way.
+ Cut and paste of the treeview still had problems in the IDE. I
_really_ fixed it this time. Promise. :)
+ TSystemTreeView.ResetTreeView renamed to Reset, and
TSystemListView.Reload renamed to Reset for consitency.
+ Added TSystemTreeView.NodeData and TSystemListView.ItemData public
read-only properties. See the new SimpleExplorer demo app to see how
these can be useful.
+ DeleteNode and DeleteItem only worked for files, and they did not do it
via the system, i.e. it didn't honor the system settings for using (or
not using) the recycle bin.
+ File sizes were still being reported as not working in some situations.
I'm trying yet a another new way of getting the file sizes. It seems
to work for me, even solving a long standing issue of not being able
to get file sizes of open files. But, if it causes you problems, you
can add the DFS_STV_OLDFILESIZE define and it will use the v0.91 file
size code.
+ Added ReadDelay property to the treeview. This makes it behave much
more like Explorer. Set this to the amount of time in milliseconds you
want the tree to delay before populating the listview. It defaults to
500ms, mostly because that seems the closest to Explorer's behavior.
You can probably set it lower and get results that are as good and
make it more responsive to the user. The main place where this is
useful is when you are browsing through the tree and you want to go
through a drive that doesn't have a disk in it (floppy, CD, ZIP, etc).
Before, you'd always get the not accessible error or a long wait if
there was a disk in a slow access drive. Now, it blows right on past
it if you move on before ReadDelay milliseconds.
+ Added TSystemListView.GetSelectedPIDLs function. See SimpleExplorer
project for how it can be useful.
0.92 + On some network drives, the file size of files in the list view could
be reported incorrectly. Thanks to Rob Watt for finding and providing
a fix for this.
+ List view's ShowFolders property didn't work quite completely enough.
It would still show things like drives, which are technically folders.
If ShowFolders is false, it should only display files, as it does now.
+ File changes were not being monitored correctly. Things like files
being added in the current directory would not refresh the display.
Fixed.
+ Don F. Ridgway sent me code to do that attributes column of the list
view. MANY thanks to him for taking care of that To-Do list item.
0.91 + Added OnPopulated event to both tree and list. They fire after all
items have been added to them.
+ Real file masking! I've removed the SimpleMask property (it only let
you mask based on extensions) and replaced it with a FileMask property.
The tree also has this property, and uses it to mask files when
ShowFiles is set to true. Use it much the same as you would any file
mask: '*' is 0 or more of any character, '?' is any one character, ';'
is used to seperate individual masks. So, if you want all executables,
you could do something like '*.exe;*.com;*.bat;*.lnk'. You can get
more fancy if you need to, as well, like '*4*.com' will show all files
with a '4' in them that end with a '.com' extension. Basically, it
should work just the same as a mask in FindFirst/FindNext (although
those aren't used).
+ Fixed known issue of delete/cut/paste of TSystemTreeView in the IDE.
It absolutely hated to be deleted when the Selection (or Directory,
they're the same) property was set to something other than blank. Now
works fine.
+ See updated information on the last item in the Working Notes section.
0.90 + Stupid VCL doesn't update the Item.StateIndex property when the user
clicks on it to check/uncheck it. Only updates it when you change
the value in code. How worthless... Anyway, that made the ItemChecked
property pretty much useless as well. I've fixed it.
+ TSystemListView.GetFullPath screwed up drives. It would return "C:\\"
instead of "C:\". Thanks to Ladislav Dolezel for finding and fixing.
+ Cleaned up the Known Issues list a bit. A bunch of fixed stuff was
still listed.
0.89 + Using several root folder types would make it difficult to work with
assigning a value to Selection property in tree. It now attempts to
convert new Selection values to their relative equivalents
automatically to simplify this.
+ Context menu now supports multiple items. That is, if multiple items
are selected in a listview and the default context menu is requested
(i.e. the user right-clicks), the context menu is valid for all
selected items, not just the first selected.
+ New public method DisplaySelectedContextMenu for listview. Same as
DisplayContextMenu, except it shows menu for all selected items instead
of a specific TListItem.
0.88 + Design-time value of tree's Selection property was not always honored
at run-time.
+ Columns property should not have been published in the listview. It is
now a public proeprty. If you need to add your own columns, you do so
by setting ColumnType to ctUser and writing an OnCreateColumns event
handler that adds the columns at run-time.
+ Added new public method DefaultDblClickAction to listview. This can
be useful if you want to handle the OnDblClick in some situations, but
want normal handling in other situations.
+ SimpleMask didn't work for registered file types if extensions were
hidden. That is, if you set the "Hide file extensions for known file
types" option in Explorer, files of known types would always fail to
match the mask.
+ Using listview's SimpleMask under Delphi 2 would cause AVs because of
an incorrect Release call.
+ SimpleMask would hide files and folders that did not match instead of
just files.
+ Listview didn't display the date/time for folders.
+ Inplace renaming of listview items now renames the item properly, i.e.
if the listview is showing "Autoexec.bat" and you edit it, the file
will be renamed.
+ Added two new public functions to listview, RenameItem and DeleteItem.
+ Added Checkboxes published property and ItemChecked public property to
treeview. These require the updated COMCTL32.DLL be on the system. If
you don't know about the updated COMCTL32.DLL issue, get my
TExtListView component and read the ELV.txt file, especially the
"Redistributing COMCTL32.DLL" section.
0.87a + Updated ItemProp.pas unit. This fixes a known issue with
cut/copy/paste context menu items not working on all installations.
No code in SystemTreeView.pas has changed.
0.87 + The fix introduced in v0.85 broke TSystemTreeView if there was no
TSystemListView attached to it. Stupid programmer...
+ Removable drives would still get hit when being displayed in a
TSystemListView. This was very annoying when those drives were empty.
+ Added Data property to TFolderItemData class. The reasoning is that
the components use the TTreeNode.Data and TListItem.Data properties,
so they aren't available to the component user any more. Now, you can
have the equivalent by doing something like this:
TFolderItemData(Node.Data).Data := mydata;
+ Demo program sometimes blew up on NT.
0.86 + Added SystemView.inc file. This file contains all the conditional
defines used by the unit. There are two new defines in this file that
you may be interested in: DFS_STV_SYSTREEVIEW and DFS_STV_SYSLISTVIEW.
See the Conditional Defines section above for a complete description.
+ DFS_STV_USE_ENHLISTVIEW and DFS_STV_USE_EXTLISTVIEW conditionals added.
These are not enabled by default. See the Conditional Defines section
above for a complete description. WARNING: This is just a simple
implemenation currently, and there are likely to be problems. Only use
these if you want to help me work out the bugs in it.
0.85 + Resetting of a treeview that had a linked listview could cause nasty
problems because the listview kept a pointer that wasn't valid any
longer.
0.84 + Updated to publish the new D3 and D4 properties such as RowSelect,
RightClickSelect, Anchors, etc. Note, this stuff only shows up in the
appropriate version of Delphi. For example, only D4's list/tree view
has an Anchors property, so TSystemTree/ListView only has it if
compiled under D4.
+ Renaming a tree node did not update some internal data, and doing
things like trying to expand the renamed directory would complain about
the old name not existing.
+ Deleting nodes in the tree could cause the automatic refresh stuff to
get confused and cause AVs when the component was destroyed.
+ Setting ShowFiles to TRUE in the tree would cause it to try to watch
for changes in a directory with the name of the file selected instead
of the directory that the file was in.
+ Removed the FShellMalloc._Release call in the finalization section for
D3 and higher. It was there to begin with because there appears to be
a compiler bug with COM objects whose references are gotten in an
initialization section. The compiler is supposed to automatically
insert a release call when the reference "goes out of scope", but
Delphi doesn't do this for stuff in the init section. I was
compensating by inserting the call manually, but it turns out that if
you do this, you'll then get two calls to release, yours and the
missing automatic call that Delphi was supposed to be inserting anyway.
So, I figure it is safer to have the ref count of the COM object to be
too high rather than too low. Go too low, and you could conceivably
end up freeing the shell's IMalloc object and that would be a TRULY
bad thing. Thanks to Grahame Marsh for the spelunking he did on this.
0.83 + The 'KB' abbreviation was hard-coded, it is now a resource string.
+ Folders would show '0 kb' in fast mode instead of being blank like they
are in non-fast mode.
+ Fixed range check error when sorting by column click under Delphi 4.
+ AddNewNode method didn't like adding to root directory nodes.
+ Floppy drive is no longer hit when expanding a tree node that contains
it. MANY thanks to Jacques Bordas for
fixing this EXTREMELY annoying bug.
0.82 + Updated for Delphi 4 compatibility.
0.81 + NT 4 has more than 8 bytes stored in in the registry key used for the
column sizes. This caused problems, but it really shouldn't have.
At any rate, I've modified the code to account for the size being
unknown.
+ Almer. S. Tigelaar emailed me a fix for the "never
ending flicker" problem that some people have reported. I could never
duplicate the problem, so I can only tell you that he said it fixed it
for him. If you still have the problem, please let me know.
0.80 + Unit now uses DFS.INC file for my commone defines.
+ Moved all this crap out of source file to this text file.
+ Changed context menu handling entirely. Components now use my ItemProp
unit (included) that handles it all. I did this because I have the
Send To menu problem solved in ItemProp, and redoing it here seemed
pointless. So, the Send To menu bug (it being empty) is now fixed.
+ Added PopupMenuMethod property to both components. pmmNone means use
no popup menus at all, pmmUser means use only menu in PopupMenu
property, pmmContext means use only system context menu, pmmContextUser
means use system context menu if it can and PopupMenu if it can't.
Items like the Desktop node and listviews with nothing selected are
places where the context menu would not be used and the PopupMenu would
kick in.
+ I've added two new defines to the top of the unit, DFS_STV_FASTMODE and
DFS_SLV_FASTMODE. See Conditional Defines section above.
+ Forgot to override the tree's Notification method. This would cause
violations if a linked list view is deleted before the tree view. Many
thanks to Simon Armstrong for catching this one.
+ File time in TSystemListView could be incorrect in some time zones.
Thanks to Frank Kroeger for providing a fix.
+ Added Reload method to TSystemListView. You can guess what it's for.
+ Shortcut (.LNK) files in the Desktop folder no longer show their .LNK
extension.
+ Wouldn't compile with DFS_STV_FILECHANGES undefined. Thanks to Elmar
Klaus for fixing this.
+ Added Known Issuses section above. Please read it.
+ Changing MultiSelect property of TSystemListView at run-time would
clear the contents of the list view. Actually, anything that recreated
the window would do this. Now properly reloads after window is
recreated. May also have been causing some AVs that people reported
when changing MutliSelect value, but I wasn't able to verify this.
+ TSystemTreeView has a new Directory property. It is identical in
every way to the Selection property. :)
+ Added two read-only properties to TSystemListView: Filename and
FullFilename. Both are array properties that use a TListItem as the
index. Ex:
ShowMessage(MyList.FullFilename[MyList.Selected]);
+ Got rid of the hard-coded column captions for TSystemListView. They
are declared as resourcestrings for D3 and just constants for D2 in the
interface section.
+ Double clicking on an item in TSystemListView now takes the item's
default action (the one in bold on it's context menu). However, if you
have an event handler for OnDblClick, this will not happen.
+ Share and link image overlays weren't correct on all machines. Fixed
by Benedykt Kubica . Many thanks.
+ TSystemTreeView and TSystemListView Items property has been changed to
public visibility and read-only. This stuff should only be read from,
never written to from outside the component.
+ Dropping a TSystemListView on a form with a TSystemTreeView on it will
automatically hook it up to the ListView property of the the tree.
+ TSystemListView would always show the contents of the desktop when the
treeview's root node was selected, even if the root node wasn't the
desktop, i.e. RootFolder was rfCustom and CustomDir set to c:\.
+ Setting MultiSelect property of list view at design-time in forms that
were not auto-created would cause AV's when the form was created and
shown at runtime.
+ Found and fixed a problem with the file/dir thread watcher. Not sure
what problems it may have been causing as it would have been very
sporadic, but creating directories may now be more reliable.
+ Sorting is better now. TSystemListView sorting was broken sometimes,
and it wasn't completely right anyway. Now sorts folders first and
items after. Should sort exactly like explorer now.
+ Now compatible with C++Builder 1 & 3.
+ Added AutoScroll property. This feature was entirely written and
contributed by Aristide Torrelli . I have only
adapted it for use in TSystemListView. Many thanks to him.
+ Palette icon for list view provided by Almer. S. Tigelaar
.
+ SimpleMask property added to TSystemListView. This feature was written
by Rafal Platek and slightly edited by me. To
only list files with specific extension(s), just assign the
extension(s) to this property. For example:
MyList.SimpleMask := 'pas'; // show only .pas files.
MyList.SimpleMask := 'pas,dpr,dfm'; // show common Delphi source files
MyList.SimpleMask := ''; // No masking, show all.
+ The following were done by Fabrice Fouquet (services@cfp47.inba.fr):
* Setting Section property of tree now makes sure it is also visible.
* Hourglass cursor during directory changes.
* Use registry info to size list view columns so they match Explorer's.
* Double-click in listview moves into sub-folder and updates treeview,
too. I enhanced this one so that it would work with non-file
system folders, so if something there breaks, it's my bug not
Fabrice's.
* Column sorting for list view.
0.70 + Turns out I was thick-skulled after all (see 0.65 notes). I was
allocating the memory with GetMem, and that of course does not
initialize the memory (i.e. make sure the pointer variables are set
to NIL). So, I assigned something to the IShellFolder variable,
and Delphi 3 checks the existing value and tries to Release it if
it is not NIL. Well, it's just trash initially, so off it goes
into the weeds... I could go back to the dynamic allocation method
and use the Initialize function to clear it all, but the class is
better anyway.
+ General clean-up.
+ Fixed bug in RenameNode method. It updated the relative PIDL, but
not the fully qualifed PIDL. Thanks to Frank Kroeger
(FKroeger@tkc.de) for finding and fixing this.
+ Shared and link overlay images now work for the tree and list. HUGE
thanks go to Peter Ruskin (PeterRuskin@classic.msn.com) and Lars
Randers (lranders@post2.tele.dk) who both for provided this code.
+ Added ShowFolders property to TSystemListView.
+ Files weren't shown in folders that had no subfolders (ShowFiles
property set to TRUE).
+ Fixed problem that would cause bizarre access violations if you did
anything that caused the window to be recreated. For example, if
you changed the BorderStyle property, you would get this because
the window handle has to be destroyed and recreated. This caused
all the pointers to get freed, but then the pointer values were
restored when the window was recreated -- data is gone, just a load
of invalid pointers.
+ Images were screwed up in Control Panel and Printers folder.
+ Overriden Expand method never called inherited. Broke OnExpanded
event.
0.65 + Yes, it's true; I FINALLY got it working under Delphi 3. I thought
I was just really thick skulled, but turns out that Delphi 3 freaks
out when you try to store COM object references in dynamically
allocated records. I switched the record structure over to a class,
and all works just fine... Go figure. Needed to be done anyway.
Now I need to flesh out the new class so it's more OOP-ish.
0.60 + Well, it compiles under Delphi 3, but it sure doesn't work. I will
get to when I can. Sorry.
+ Added TSystemListView.GetItemAttrs public method so you can get the
attrs of an item to do stuff like testing for if it is a folder:
if (SLV.GetItemAttrs(SLF.Selected) and SFGAO_FOLDER) <> 0 then
// It's a folder
+ Added TSystemListView.GetFullPath public method to get an item with
it's complete path information. This obviously doesn't apply for
things like printers and such.
+ Sorting in the TSystemListView should now work. Set SortType to
something other than stNone.
0.50 + ShowRoot didn't work as it should (as TListView does).
+ rfFileSystem roots wouldn't expand farther than the first level.
+ Some serious problems with EAccessViolations after fiddling with
the component for a while (change RootFolder, etc). I think I have
this all fixed up now. AddRefs and Releases weren't quite right.
+ Selection property is now read and WRITE. That means you can do
something like MyTree.Selection := 'c:\windows\system'; and it will
select that node. Note that this only works with file/directory
stuff, there is no way to do something like MyTree.Selection :=
Control Panel; Also note that the assignment value is relative to
the root type. So, if you want to select a directory when
RootFolder is rfDesktop or rfDrives, you pass the full pathname.
If RootFolder was rfPrograms and your programs directory was
'c:\win\start menu\programs' and you wanted to select
'c:\win\start menu\programs\some folder\subfolder', you would do:
MyTree.Selection := 'some folder\subfolder';
Many thanks to Raymond Chen for his help on walking a PIDL (similar
to walking a dog, but without the pooper-scooper).
+ Added OnAddListItem and OnCreateColumns to the TSystemListView
component. OnCreateColumns is called when ColumnType is set to
ctUser. The old columns are removed and then the event is fired.
The event is responsible for creating the columns it needs.
OnAddListItem is called every time an item is added to the listview.
It passes the new TListItem, which has the Caption property set to
the name of the new item. You should set the ColumnType property
to ctUser and create the columns you need in the OnCreateColumns
event. Then, in the OnAddListItem event, you would add the data
for these new columns by using the passed TListItem's SubItems.Add
method.
+ Updated for compatibility with Delphi 3.
0.40 + At this point, TSystemListView is just an experiment. If you have
problems with it, I will try to help, but I will not devote much
time to it. I'm mainly interested in the tree view. Now, if you
have problem AND a fix, I'll be more than happy to hear about it.
+ Somehow I ended up with two versions of v0.30. I don't have any
idea how it happened, and I've given up trying to merge the two
versions and just gone back to the one with the most functionality.
+ Got rid of the SHGetDataFromIDList call. Only works correctly on
NT 4 with service pack 2, so it's not really a viable alternative
for this.
+ Sorting revisited. Thanks to Detlef Meister
(Meister@rz.fhtw-berlin.de) for sending me some good code to start
with for this. I think sorting is working very well now, but that
is of course only on my machines. Please try it out, and especially
pay attention to see if it sorts in the same order as Explorer. If
you find that sorting is causing terrible problems for some reason,
you can turn it off by undefining STV_DOSORTING below. If all goes
well with it, I'll add it to the list view next.
+ Added read only Selection property. Returns the path name of the
selected node (if it is a file system object). Working on making
it read/write, but it's a pretty hairy problem.
+ CustomDir didn't like UNC names (\\somecomputer\somedirectory).
Working a little better now, but still not right.
+ Many people have asked how to just display drives, i.e. RootFolder
set to rfDrives but without the printers, control panels, etc.
There is no direct support for this at the API level
(SHGetSpecialFolderLocation), but I think I have found a way to do
it. Try the new rfFileSystem root type. Let me know if you have
any problems with it. It should have My Computer as the root node
and then any device that has physical storage capability as child
nodes. If you are interested, search for SFGAO_FILESYSANCESTOR to
see what I'm doing.
0.30 + New feature: Set the value of CustomDir to a valid directory, and
then set RootFolder to rfCustom, and the tree will allow you to
browse from that directory as the root. Also, if you don't want
the root to read something like 'c:\win\system', then use
CustomDirCaption to override it.
+ Now using SHGetDataFromIDList, which is missing from SHLOBJ.PAS.
See step five in ShellFix.txt.
+ If PopupMenu property is has a menu, it is displayed instead of the
context menu.
+ TSystemListView now descends form TCustomListView as it should.
+ Fixed bug. I overrode the Change method of the tree, but forgot to
call inherited method. This broke the OnChangeEvent - never called.
+ Fixed bug that caused serious problems for projects with one of
these saved on a form. When you tried to reopen the form after it
was closed, it would cause many strange things to happen, usually
just a lockup. See the Loaded and CreateWnd methods for the fix.
If you want detailed description, email me and I will explain it.
+ New feature: ShowFiles property. Allows the tree to display items
other than folders in it. I guess ShowFiles isn't the best
description, since also includes things like printers in the
printers folder. Anyone got a better name for it?
+ TSystemListView object has some serious problems, so I've disabled
it in test app until I get time to work on it. I strongly suggest
you stay away from it in this version, unless you want to help me
fix it. To reenable it in the test app, take out the NOLISTVIEW
define at the top of TESTING.PAS.
0.21 + DisplayContextMenu doesn't work for root tree objects. Desktop
doesn't have one, and I fixed that, but don't know what's wrong
with the others.
+ Moved all strings into resource file (ErrorMsgs.r32) except for the
debugging "mem leak" string. Doesn't seem to like loading strings
in an exitproc (finalization section).
+ Could never make up my mind about whether to go with message boxes
or exceptions, so I just added a public property that can be used
to set your preference. I prefer message boxes since there is no
good way to catch the exceptions in an app, so that is the default.
+ Added all the file system report info stuff for list view items
(size, type, date). If anyone knows how to determine the type of
object you have given it's PIDL, I'd love to know it. Right now,
if it's not a file system object, you just get it's name.
0.20 + This unit requires complete boolean eval to be turned off. I've
added the appropriate compiler switches to do this in case it is
turned on in your project.
+ First crack at a TSystemListView component to compliment the tree
view. It is way far from being as functionally complete as the tree
view. Mostly it's to see if it works for everyone at it's simplest
form.
0.11 + Deleted the $I DEFINES.INC file in demo app. Not needed any more.
+ Added GetNodePath. Returns full path given a TTreeNode. Returns
'' if it is not a file system type node (i.e. control panel).
+ If selected node were deleted from another app, it could get pretty
ugly. Fixed.
+ Added palette resource icon for component. Thanks to Basri Kanca
for it.
+ Added three new functions, RenameNode, DeleteNode, AddNewNode.
0.10: + I Feel reasonably confident in the component now. All core
functionality seems to be in place and working.
+ Added ability to rename folders. Thanks to Thomas AW Brown.
+ Fixed problem that would occur if you installed the component in
Delphi (i.e. Component | Install). By default, the Items property
is "stored", so all everything in it is written to the DFM file
that the component is on and that includes the Data property of
each of the tree nodes. This a pointer to memory we allocate, so
having the pointer value stored wouldn't do a whole lot of good,
would it? See the redeclaration of Items below.
+ Added a new unit, FileChange, which provides a TThread descendant
that knows how to watch directories for changes in structure. It
hasn't been well tested, so I have included it only inside $IFDEFs.
It should automatically cause the selected node to be updated if
another app makes changes to that directory's subdir structure.
For example, compile and run the demo. Select a node that is a
directory somewhere on your hard drive. Start explorer and select
that same node in it. Add a new folder to the selected directory
in Explorer. The demo app should automatically update the node to
reflect the change. If you have problems with it, comment out the
$DEFINE FILECHANGES line below.
0.03: + Finally got the damn icon problem fixed. The PIDL wrapper class
was hosing me up somehow. Don't know what was wrong with it, but
its pointer would disappear for some reason. Getting rid of it
cleared up the problem. So much for OOP making my life easier. :)
+ Got ShowRoot working. Thanks to John Cardinal for that.
+ General code clean up.
+ While Mr. Ritchey acknowledged the declaration errors in his
ShellObj unit, he has never answered my request to included a fixed
version of it with this control. So, for now, I'm just going to
include directions on how to fix everything and not worry about.
See the SHELLFIX.TXT file.
0.02: + Updated to use ShlObj, available inthe Delphi 2.01 update. See
NOTE above. Edit the DEFINES.INC file to control which namespace
import unit you want to use. If $D201 is defined, you use
Borland's, otherwise Pat Ritchey's. Also made some more changes to
ShellObj to make it more compatible with Borland's ShlObj version.
If you use Borland's, context menus won't work. See the comments in
the DisplayContextMenu method for an explanation.
+ Context menus (right click) are working, but need a good round of
testing.
+ Added some stuff to the demo project to help with testing.
+ Can now change RootFolder property during execution. Would blow up
before if changed after initial assignment.
rfRecycleBin still blows up... don't know why. It doesn't like
the EnumObjects call in EnumerateFolders.
+ A lot of the code got rewritten to make context menus, icons, etc.
work. A the Golden Rule of PIDLs is that the SH* functions take a
fully qualified path PIDL, and the IShellFolder interface methods
take a relative PIDL. I was using relative PIDLs everywhere. The
result is that more things work now, but the code is probably even
less stable than before. Bang on it.
0.01: + Cleaned up the mess in the USES clauses and the test project.
0.00: + Initial alpha release to limited audience.