TExtListView & TEnhListView v3.15

NOTE:  Delphi 4 has most all of the TExtListView stuff in it's TListView now,
  even virtual mode (OwnerData).  So, I will likely change the course of this
  component's developement in the not too distant future.  I'll keep fixing
  bugs in this for the non-D4 users out there, but I probably won't be adding
  any significant new features.  Instead, I'll probably start working on a
  descendant of D4's TListView that adds the stuff that's in TEnhListView right
  now.  If you have strong feelings and REASONS about why I should not do this,
  you'd better let me know.

Description:
  TEnhListView is a list view control that provides enhanced functionality
    such as:
      * Automatic sorting of text, numeric, and date columns
      * Ability to automatically save and restore user column width settings
      * Owner drawing events
    This functionality does NOT require the updated COMCTL32.DLL from Microsoft.

  TExtListView is a list view control that provides all functionality of
    TEnhListView, plus provides access to the new features of the list view
    control found with MS Internet Explorer 4.0, et. al.  This functionality
    DOES require the updated COMCTL32.DLL from Microsoft.  The COMCTL32.DLL file
    must be version 4.72.xxx or later for all functionality in this component
    to work.  Earlier versions *may* work, but are not supported (i.e. don't
    email me if you aren't using the latest version of COMCTL32.DLL).

Contact Information:
  Feel free to contact me if you have any questions, comments or suggestions
  at bstowers@pobox.com.
  The lateset version will always be available on the web at:
    http://www.pobox.com/~bstowers/delphi/

Installation:
  To install, add the ELV_Reg.pas file as you would any other component.  Trying
  to add EnhListView.pas and/or ExtListView.pas will not work, ELV_Reg.pas is
  the file that registers the components in these two files.  You still need
  these files in the same directory, along with DFS.INC and ELV_Reg.dcr.

Installing the Help File:
  Delphi 3:
    * Copy ELV.hlp and ELV.cnt to your Delphi\Help directory.
    * Edit the DELPHI3.CNT file and add the following line to the Index section:
        :Index Extended List View Reference =ELV.hlp
    * Delete the hidden Delphi3.Gid file.

  Delphi 2:
    * Copy ELV.hlp, ELV.kwf and ELV.cnt to your Delphi\Help directory.
    * Use the HelpInst tool included with Delphi to install the ELV.Kwf
      into Delphi\Bin\Delphi.Hdx file.

Redistributing COMCTL32.DLL:
  Microsoft used to have a really nasty redistribution policy about
  COMCTL32.DLL:  To redistribute it, you have to distribute Internet Explorer
  with your app.  Well, they've finally unpuckered a little bit (probably
  because enough people griped long and loud enough (like Ron Burk in his
  Windows Developer's Journal editorials and mail responses, THANKS RON!).
  Anyhoo, here are links where you can find official redistribution information,
  which is much more acceptable than it used to be:

  http://www.microsoft.com/permission/copyrgt/cop-soft.htm#Freq
    This page lists general Microsoft copyright info, and address the
    COMCTL32.DLL issue in particular.  Of greatest note is item #3 which grants
    permission to redistrubute a self-extracting archive provided by MS which
    contains the DLL.

  http://www.microsoft.com/msdn/downloads/files/40Comupd.htm
    This page includes a link to the most current version (v4.72 as of this
    writing) of COMCTL32.DLL in a self-extracting archive, and it even gives
    directions on how to call it from your setup program so that it is "quiet",
    that is it doesn't pop up a dialog over your installl program if you don't
    want it to.

  http://www.microsoft.com/msdn/downloads/files/40Comupd.exe
    This is the link to the most current redistributable package.  About 500k,
    sheesh, but at least it's better than 20 or 30 meg that was required before.

  Many thanks to Arentjan Banck <ajbanck@davilex.nl> for passing these links
  along to me.


Notes & Credits:
  * This component uses several types defined in the COMMCTRL unit when it can.
    If you add an event handler and then receive a compiler error about an
    unknown type, you likely need to add COMMCTRL to your unit's uses clause.
  * For the full documentation on all the new list view stuff as implemented in
    the latest COMCTL32.DLL, have a look at Microsoft's documentation at:
    http://www.microsoft.com/msdn/sdk/inetsdk/help/itt/CommCtls/ListView/ListView.htm#ch_listview
    Also, you can find information on all the updates to COMCTL32.DLL at:
    http://www.microsoft.com/msdn/sdk/inetsdk/help/itt/CommCtls/CommCtls.htm#book_cc
  * TestVM is a very good demonstration of virtual mode.  It was created by
    and is redistributed here by permission of John Newln.  I have made only
    small modifications for compatibility with the new 3.00 version.
  * The owner drawn header stuff is based on work sent to me by Rafal Smotrzyk
    <rsmotrzyk@mikroplan.com.pl>.  Many thanks to him.  He has included many
    other new features, but I got it at the time when I was trying to get this
    version out of beta. Because of that, I'm not incorporating the rest until
    after v3.00 is released as non-beta.  I'll then work his stuff into the next
    version.
  * The owner drawing and column images were originally implemented by Remi
    Sellem (RemiS@chemware.co.uk) and Mike Lindre (no address).  I only
    reworked them a little, integrated them into this component, and made a
    few changes to use the new Delphi 3 collection editor for ColumnsFormat and
    fixed a few bugs.  The original property editor (ExtColEd.pas) for this is
    provided for Delphi 2 users, but is not required at all for Delphi 3 usage.
  * There are some serious limitations that I did not realize when I first
    released the virtual mode feature.  If you are not using virtual mode
    (VirtualMode set to TRUE) then you need not be concerned.  These problems
    only affect virutal mode.  The problem is that since items are not stored
    by the list view, but rather provided as needed by an event handler, the
    Items property does not reflect the actual items in the list.  In fact,
    it is always empty.  Items.Count will return the proper number of items,
    but anything trying to use Items[x] will never get any valid data.  This
    affects several things, such as automatic drag and drop (DragMode =
    dmAutomatic), the Selected property and more.  This is because the
    implementation of TListView uses the Items property extensively.  I have
    tried to provide for this as best I can through methods like
    TExtListView.ELV_GetNextItem that can be used in place of critical functions
    that no longer work because they rely on the Items property.  I suggest that
    you NOT use virtual mode unless you completely understand all of the issues
    that may arise from using it.


Known Issues:
  * Default owner drawing will not work when running on a NT 3.51 system.  I
    use DrawTextEx() to do the drawing, and that function is only a stub in
    NT 3.51.  I use DrawTextEx because I need the DT_END_ELLIPSIS flag.  My
    best suggestion at this point is to not use default drawing if your app
    needs to run on an NT 3.51 machine, i.e. draw it yourself in OnDrawItem or
    OnDrawSubItem.
  * Default owner drawing will not work with virtual mode.  By definition, data
    is not stored in the control when virtual mode is enabled.  So, there is no
    way the control can know what to paint for you in owner draw mode.  Owner
    drawing will work correctly, but you have to do the drawing via the
    OnDrawItem and/or OnDrawSubItem events.
  * If you have both an OnDrawItem and an OnDrawSubItem event handler when in
    VirtualMode, you will have to set DefaultDrawing to TRUE in the OnDrawItem
    handler to get the OnDrawSubItem event to fire.
  * Changing column information (ColumnsFormat property) screws up the header
    image stuff.  For example, if you have set up the ColumnsFormat such that
    you have images appearing in your column headers and then you change the
    alignment of one of the TListColumns (an item of the Columns property), the
    header image will  disappear.  I could catch this if Borland would have been
    a little more liberal with their virtual/dynamic declarations, but the one
    I need isn't declared that way, so I can't override it.  Instead, you will
    just have to be aware of the situation and manually refresh it yourself.
    Example:

      // Change column 3's text alignment.
      ExtListView.Columns[2].Alignment := taRightJustify;
      // Screwed up header image, refresh it
      ExtListView.UpdateColumnImage(2);

    If you need to refresh all of the column images, just use
    UpdateColumnsImages.
  * Changing order of a list item when lvxCheckboxes style is set causes
    incorrect painting and/or loss of the check state.  This appears to be a
    problem in either the COMCTL32.DLL implementation or the handling of moving
    items around in the TListView implementation, or both.  Either way, there's
    not much I can do about it.
  * Setting a subitem image (lvxSubItemImages ExtendStyle) to -1 does not
    properly clear the image for the subitem.  The current COMCTL32.DLL
    implementation does not seem to store this value and instead it gets a
    random value assigned to it.  The work-around that I have found is to set
    the index to a value that does not exist in the image list.  To make this
    a bit easier, I have declared a constant named ELV_NO_SUBITEM_IMAGE that
    is equal to MaxInt-1 (MaxInt seems to suffer the same problem as -1).  This
    will work fine as long as your image list does not have more than
    2,147,483,646 images in it.  :)
  * OnVMStateChanged event does not fire as documented by Microsoft for virtual
    mode list views.  It appears to only fire when a range of items changes,
    and even that appears sporadic in my informal testing.  Sorry, I didn't
    write COMCTL32.DLL, so I can't fix it.  On the bright side, OnChange still
    fires.  On the dark side, it passes a TListItem which is always NIL in
    virtual mode.
  * lvxCheckboxes extended style does not work with virtual mode.  Seems to be
    a limitation of virtual mode as implemented by Microsoft in COMCTL32.DLL.
  * Adding a column to a TExtListView component at run-time seems to cause
    an EAccessViolation if you do it in the owning form's OnCreate event handler
    sometimes.  I have found that this can be worked around by moving the code
    that creates the column into the OnShow handler.  Your mileage may vary.
  * The new multiple work areas and region stuff introduced in the 4.71.xxx
    version of COMCTL32.DLL is not supported yet.
  * The new info tip stuff introduced in the 4.71.xxx version of COMCTL32.DLL
    is not supported yet because I can't get it to do a damn thing...
  * NMITEMACTIVATE structure introduced in the IE 4 version of COMCTL32.DLL
    is not supported yet.
  * I tried adding stuff for the background image, but it doesn't seem to work.
    If you want to fool with it, enable the DFS_TRY_BACKGROUND_IMAGE define at
    the top of ExtListView.pas.  Let me know if you have any luck.


Revision History:
3.15:  + Smart sorting would incorrectly flag negative numbers as dates in
         regions where a "-" is used as the date seperator.  Changed so that
         two sperator characters must be found before it is considered a date.
3.14:  + Column sizes were not saved if the user double clicked on the header
         dividers to resize them.
3.13:  + FullDrag property was incorrectly published under D4.  This property is
         the equivalent of lvxHeaderDragDrop in the TExtListView ExtendedStyles
         property.  That should be used instead, and it should not exist at all
         in TEnhListView since it requires the updated ComCtl32.DLL.
       + Added TCustomExtListView class for TExtListView to descend from.  Same
         reasoning as TCustomEnhListView class, and I should have done this one
         when I did that one.  Lazy programmer...
       + Cleaned up the demos some.  Some of the component had changed over
         time, and they had to be tweaked a bit before they stopped complaining.
         Note that TestVM only works with Delphi 3 and up because it uses
         TSplitter.  You can probably remove these and get it to work in D2 
         since they aren't critical to the demo.
3.12:  + Published new properties for Delphi 4 component where it made sense.
         For example, the new Anchors, Constraints, and DragKind properties
         are now available (under D4), but Checkboxes and OwnerDraw are not
         since they are implemented another way already in my component.
       + Added note about default owner drawing and virtual mode to the Known
         Issues section above.
       + HoverTime property has been changed back to a Longint type (was DWORD).
         Delphi 4 has some problems here, apparently.  First, it seems that
         the Object Inspector will allow only a longint range to be entered for
         a double word type (Longword, Cardinal or DWORD).  Worse, the very
         popular RX Lib freeware component package installs a property editor
         for the cardinal type (which also gets the DWORD type) that won't let
         you enter values in D4; it just keeps giving an error message about
         the value needing to be between -1 and 0.  For these reasons, I have
         switched the type of HoverTime back to a Longint.
       + Two new methods added; ReadSettings and WriteSettings.  Several people
         asked for a way to store and load settings that was independant of the
         current SaveSettings.AutoSave value.  StoreSettings and LoadSettings
         only worked if AutoSave was TRUE.  Now these methods simply test
         AutoSave and then call ReadSettings/WriteSettings.  If you want to
         read or write the stuff yourself independant of AutoSave, you can call
         ReadSettings/WriteSettings.
       + Under some odd circumstances, you could get the component to call
         RecreateWnd while it was inside of CreateWnd.  If you know much about
         the VCL, you know that this is a very Bad Thing (tm).  It would cause
         nasty exceptions.  I believe I have worked around it, but if you notice
         any odd behavior please let me know immediately.
       + OnDrawSubItem event never fired for lvxOwnerDrawFixed Style listviews
         that were in VirtualMode.  Fixed.
3.11:  + If column sizes were saved but some column widths were missing, the
         missing column sizes would be rediculously small.  They now default
         to the design-time size.
3.10:  + The CheckDLLVersion function in the ExtListView.pas unit had a nasty
         bug in it.  This would cause false EELVOldComCtl exceptions to be
         raised when a TExtListView's RequireComCtlUpdate property was set.
         Many thanks to Igor Lookin <Lookin_I@Usa.Net> for catching this one.
3.09:  + Cleaned up some compiler hints under Delphi 4 that I missed last time.
       + Fixed some default owner-drawing bugs that didn't look quite like a
         normal list view.  Mostly had to do with small image list.  Many
         thanks to Norbert Adamko <norris@frdsa.utc.sk> for fixing these.
       + LastColumnClicked was published in TExtListView, but should have only
         been made public.  Fixed.
       + SaveSettings property has new sub-property, SaveCurrentSort.  This will
         save the current sorted column index and direction and restore it on
         next execution.
3.08:  + Change OnMeasureItem event to use UINT type parameter, and underlying
         methods as well (MeasureItem) for Delphi 4 compatibility.  This will
         break your existing OnMeasureItem event handlers.  Just copy all the
         event handler code to the clipboard, remove the handler from the
         component entirely, re-add the handler, paste your code back into it.
       + Other changes for Delphi 4 compatitibility that should affect nothing
         externally to the component.
       + New public array property, CurrentColumnWidth.  Under everything but
         Delphi 4, this evaluates to ActualColumn[Index].Width.  Under Delphi 4,
         column widths are not updated during a header resize, so it broke a lot
         of code.  This is used to fix it.  It bypasses the TListColumn.Width
         call and goes directly to the API, which does know about new widths
         during header resize.
3.07:  + Fixed stupid bug that caused sort arrows to show up in all columns
         of TExtListView's that I introduced in v3.06.  Note to self: Check
         EVERYTHING, no matter how trivial the change seems.....
3.06:  + Sort arrows did not work well when sorting was done by OnSortItems
         event instead of AutoColumnSort property.
       + Resort call would not work inside BeginUpdate/EndUpdate unless
         AutoResort were TRUE.  Thanks to  Norbert ADAMKO <norris@frdsa.utc.sk>
         for fixing this.
       + If an ExtListView had items in it and you switched to virtual mode and
         then back out, you would get AV's.  Fixed.
3.05:  + Sort arrows did not respond to system color changes, so they were
         really ugly if you change the 3D Objects system color.
3.04:  + Sort arrows always showed up if ShowSortArrows was TRUE.  This was a
         bug if AutoColumnSort was set to acsNoSort.  Fixed.
       + Added new ResizeColumns public method.
       + Added note about COMMCTRL unit usage in "Notes & Credits" section (see
         above).
3.03:  + Added Version property.
       + There were still a bunch of property write methods that assumed the
         component had a valid window handle (or tried to create one if it did
         not).  That wasn't really causing any problems when using the
         component, but it was causing fits for people who were trying to
         create a descendant from it under certain circumstances.
3.02:  + Fixed problem where TExtListView stayed in the change list of
         SmallImages property when value changed.  Thanks to CWard
         (CWard@lombardrisk.com) for finding and fixing it.
3.01:  + TEnhLVSaveSettings constructor was not calling its inherited
         constructor.  That's probably why I had some many fits with AutoSaving
         during the 3.00 beta cycle.... Duh.
       + Help file!
3.00:  + The changes from v2.04 are too numerous to mention.
2.04:  + TLVColumnEx record had two members declared in the wrong order.  Thanks
         to Remi Sellem for catching this.
       + The COMCTL32.H did not include a macro for setting an item's checked
         state, only for getting it.  I have figured one out, and now the
         IsChecked property is read/write not read-only.
2.03:  + Reworked the sorting routines to work with bigger numbers and to make
         it a little smarter at detecting valid numbers.  Thanks for much of
         this to Rod Cullison (RCullis@worldnet.att.net).  Also added basic date
         sorting capabilities.
2.02:  + Changed property AutoColumnSort to have three different states
         (acsNoSort, acsSort, acsSortToggle). New one toggles sort order between
         ascending and descending order.   By Christian Holzner
         <cholzner@ping.at>.
2.01:  + Added two new properties, AutoColumnSort and AutoSortAscending, that
         allow the list view columns to be automatically sorted when the user
         clicks on them.  Thanks to Peter Thvrnqvist
         (NMA96PTH@lustudat.student.lu.se) for writing the sorting code that I
         never seemed to get to.
       + There are some serious limitations to virtual mode.  See discussion in
         the "Notes" section above.
2.00:  + Added SaveSettings property.  Allows automatic saving and restoring of
         column order and sizes.
       + Now covers all new additions in the latest ActiveX SDK release.
         Briefly, here's most of what's new:
           Properties for Virtual Mode, subitem info, hot item, hot cursor, work
           area and item checked.
           Methods for item spacing, get sub item at give coords, getting and
           setting column order.
           New events for MarqueeBegin (bounding box selection), ItemActivate,
           and owner data ("Virtual Mode") events.
       + Now includes COMCTL32.DLL and API documentation ("Chapter 11.doc").
       + Now includes far less comments than usual because I have no time.  If
         you see something that looks wrong or doesn't make sense, email me.
1.00:  + Initial release.

