home *** CD-ROM | disk | FTP | other *** search
/ Freelog 11 / Freelog011.iso / BestOf / PhoenixMail / Source / comps / EnhListView.pas < prev    next >
Pascal/Delphi Source File  |  1999-01-06  |  55KB  |  1,815 lines

  1. {*****************************************************************************
  2.  *
  3.  *  Parts of this code were changed by Michael Haller
  4.  *  E-mail:     michael@discountdrive.com
  5.  *  Homepage:   http://www.discountdrive.com/sunrise/
  6.  *
  7.  *  The copyright has the original author of this code.
  8.  *
  9.  *****************************************************************************}
  10.  
  11.  
  12.  
  13. {$I DFS.INC}  { Standard defines for all Delphi Free Stuff components }
  14.  
  15. // Delphi 2 and C++B 1 have incorrectly declared InsertItem as private.
  16. {$IFDEF DFS_COMPILER_3_UP}
  17.   {$DEFINE DFS_FIXED_LIST_VIEW}
  18. {$ENDIF}
  19.  
  20. {.$DEFINE DFS_DEBUG}
  21.  
  22.  
  23. {------------------------------------------------------------------------------}
  24. { TEnhListView v3.10                                                           }
  25. {------------------------------------------------------------------------------}
  26. { A list view control that provides enhanced functionality beyond the          }
  27. { standard list view.  For example, automatic sorting of simple data types,    }
  28. { owner draw event for vsReport mode, and more.  This does NOT require any     }
  29. { special version of COMCTL32.DLL.                                             }
  30. { Copyright 1998, Brad Stowers.  All Rights Reserved.                          }
  31. { This component can be freely used and distributed in commercial and private  }
  32. { environments, provied this notice is not modified in any way.                }
  33. {------------------------------------------------------------------------------}
  34. { Feel free to contact me if you have any questions, comments or suggestions   }
  35. { at bstowers@pobox.com.                                                       }
  36. { The lateset version will always be available on the web at:                  }
  37. {   http://www.pobox.com/~bstowers/delphi/                                     }
  38. { See ELV.txt for notes, known issues, and revision history.                   }
  39. {------------------------------------------------------------------------------}
  40. { Date last modified:  July 22, 1998                                           }
  41. {------------------------------------------------------------------------------}
  42.  
  43.  
  44. // C++Builder 3 requires this if you use run-time packages.
  45. {$IFDEF DFS_CPPB_3_UP}
  46.   {$ObjExportAll On}
  47. {$ENDIF}
  48.  
  49. unit EnhListView;
  50.  
  51. interface
  52.  
  53. {$IFNDEF DFS_WIN32}
  54.   ERROR!  This unit only available for Delphi 2.0 or higher!!!
  55. {$ENDIF}
  56.  
  57. uses
  58.   Windows, Messages, Classes, Controls, ComCtrls, CommCtrl, SysUtils, Graphics,
  59.   StdCtrls, Menus, Dialogs, DFSAbout;
  60.  
  61.  
  62. const
  63.   { This shuts up C++Builder 3 about the redefiniton being different. There
  64.     seems to be no equivalent in C1.  Sorry. }
  65.   {$IFDEF DFS_CPPB_3_UP}
  66.   {$EXTERNALSYM DFS_COMPONENT_VERSION}
  67.   {$ENDIF}
  68.   DFS_COMPONENT_VERSION = 'TEnhListView v3.10';
  69.  
  70.   DRAWTEXTEX_FLAGS = DT_NOPREFIX or DT_SINGLELINE or DT_VCENTER or
  71.      DT_END_ELLIPSIS;
  72.   DRAWTEXTEX_ALIGNMENT: array[TAlignment] of UINT = (DT_LEFT, DT_RIGHT,
  73.      DT_CENTER);
  74.   WM_OWNERDRAWCOLUMNS = WM_USER + 143;
  75.  
  76. type
  77.   TIntArray = array[0..(MaxInt div SizeOf(Integer)-1)] of Integer;
  78.   PIntArray = ^TIntArray;
  79.  
  80.   TResizeMethod = (rmFitText, rmFitHeader);
  81.   TAutoColumnSort = (acsNoSort, acsSort, acsSortToggle);
  82.   TAutoSortStyle = (assSmart, assDefault);
  83.   TLVStyle = (lvStandard, lvOwnerDrawFixed);
  84.   TLVHDrawItemEvent = procedure(Control: TWinControl; var ACanvas: TCanvas;
  85.      Index: Integer; var ARect: TRect; Selected: boolean;
  86.      var DefaultDrawing: boolean) of object;
  87.   TLVMeasureItemEvent = procedure(Control: TWinControl;
  88.      var AHeight: UINT) of object;
  89.   TLVDrawItemEvent = procedure(Control: TWinControl; var ACanvas: TCanvas;
  90.      Index: Integer; ARect: TRect; State: TOwnerDrawState;
  91.      var DefaultDrawing, FullRowSelect: boolean) of object;
  92.   TLVDrawSubItemEvent = procedure(Control: TWinControl; var ACanvas: TCanvas;
  93.      Index, SubItem: Integer; ARect: TRect; State: TOwnerDrawState;
  94.      var DefaultDrawing: boolean) of object;
  95.   TLVAfterDrawItemEvent = procedure(Control: TWinControl; var ACanvas: TCanvas;
  96.      Index: Integer; ARect: TRect; State: TOwnerDrawState) of object;
  97.   TLVSortItemsEvent = procedure(Sender: TObject; Item1, Item2: TListItem;
  98.      SortColumn: integer; var CompResult: integer) of object;
  99.   TLVSortStatusEvent = procedure(Sender: TObject; SortColumn: integer;
  100.      Ascending: boolean) of object;
  101.   TLVEditCanceled = procedure(Sender: TObject; Item: TListItem) of object;
  102.  
  103.   // Class for saved settings
  104.   TEnhLVSaveSettings = class(TPersistent)
  105.   private
  106.     FAutoSave: boolean;
  107.     FRegistryKey: string;
  108.     FSaveColumnSizes: boolean;
  109.     FSaveCurrentSort: boolean;
  110.   public
  111.     constructor Create; virtual;
  112.     procedure StoreColumnSizes(ColCount: integer;
  113.        const IntArray: array of integer);
  114.     procedure ReadColumnSizes(ColCount: integer;
  115.        var IntArray: array of integer);
  116.     procedure StoreCurrentSort(Ascending: boolean; SortCol: integer);
  117.     procedure ReadCurrentSort(var Ascending: boolean; var SortCol: integer);
  118.   published
  119.     property AutoSave: boolean read FAutoSave write FAutoSave default FALSE;
  120.     property RegistryKey: string read FRegistryKey write FRegistryKey;
  121.     property SaveColumnSizes: boolean
  122.        read FSaveColumnSizes
  123.        write FSaveColumnSizes
  124.        default TRUE;
  125.     property SaveCurrentSort: boolean
  126.        read FSaveCurrentSort
  127.        write FSaveCurrentSort
  128.        default TRUE;
  129.   end;
  130.  
  131.  
  132.   { The new class }
  133.   TCustomEnhListView = class(TCustomListView)
  134.   private
  135.     FSortDirty: boolean;
  136.     FUpdateCount: integer;
  137.     FStyle: TLVStyle;
  138.     FAutoColumnSort: TAutoColumnSort;
  139.     FAutoSortStyle: TAutoSortStyle;
  140.     FAutoResort: boolean;
  141.     FAutoSortAscending: boolean;
  142.     FTmpAutoSortAscending: boolean;
  143.     FLastColumnClicked: Integer;
  144.     FSaveSettings: TEnhLVSaveSettings;
  145.     FShowSortArrows: boolean;
  146.     FReverseSortArrows: boolean;
  147.     FSortUpBmp,
  148.     FSortDownBmp: TBitmap;
  149.  
  150.     FOnSortBegin: TLVSortStatusEvent;
  151.     FOnSortFinished: TLVSortStatusEvent;
  152.     FOnMeasureItem: TLVMeasureItemEvent;
  153.     FOnDrawItem: TLVDrawItemEvent;
  154.     FOnDrawSubItem: TLVDrawSubItemEvent;
  155.     FOnAfterDefaultDrawItem: TLVAfterDrawItemEvent;
  156.     FOnDrawHeader: TLVHDrawItemEvent;
  157.     FOnSortItems: TLVSortItemsEvent;
  158.     FOnEditCanceled: TLVEditCanceled;
  159.  
  160.     { Message handlers }
  161.     procedure CMSysColorChange(var Message: TWMSysColorChange);
  162.        message CM_SYSCOLORCHANGE;
  163.     procedure CNMeasureItem(var Message: TWMMeasureItem); message CN_MEASUREITEM;
  164.     procedure CNDrawItem(var Message: TWMDrawItem); message CN_DRAWITEM;
  165.     procedure CNNotify(var Message: TWMNotify); message CN_NOTIFY;
  166.     procedure WMDestroy(var Message: TWMDestroy); message WM_DESTROY;
  167.     procedure WMDrawHeader(var Message: TWMDrawItem); message WM_DRAWITEM;
  168.     procedure WMNotify(var Message: TWMNotify); message WM_NOTIFY;
  169.     procedure WMOwnerDrawColumns(var Message: TMessage);
  170.        message WM_OWNERDRAWCOLUMNS;
  171.   protected
  172.     { USE WITH CARE.  This can be NIL }
  173.     FCanvas: TCanvas;
  174.     FHeaderHandle: HWND;
  175.     procedure InvalidateColumnHeader(Index: integer); virtual;
  176.     procedure DoSort(ColumnIndex:integer; Descending: boolean); virtual;
  177.     procedure SortBegin(ColumnIndex: integer; Ascending: boolean); virtual;
  178.     procedure SortFinished(ColumnIndex: integer; Ascending: boolean); virtual;
  179.     procedure SortItems(const Item1, Item2: TListItem; SortColumn: integer;
  180.        var CompResult: integer); virtual;
  181.     procedure MeasureItem(var Height: UINT); virtual;
  182.     procedure DefaultDrawItem(Index: Integer; Rect: TRect;
  183.        State: TOwnerDrawState; FullRowSelect: boolean); virtual;
  184.     procedure DefaultDrawSubItem(Index, SubItem: integer; Rect: TRect;
  185.        State: TOwnerDrawState); virtual;
  186.     procedure ProcessDrawItemMsg(Index: Integer;
  187.        Rect: TRect; State: TOwnerDrawState; var DefaultDrawing,
  188.        FullRowSelect: boolean); virtual;
  189.     function ActualColumnIndex(Index: integer): integer; virtual;
  190.     function GetActualColumn(Index: integer): TListColumn; virtual;
  191.     function GetSubItemText(Index, SubItem: integer): string; virtual;
  192.     procedure DrawSubItem(Index, SubItem: Integer; Rect: TRect;
  193.        State: TOwnerDrawState; var DefaultDrawing: boolean); virtual;
  194.     procedure DrawItem(var Canvas: TCanvas; Index: Integer; Rect: TRect;
  195.        State: TOwnerDrawState; var DefaultDrawing,
  196.        FullRowSelect: boolean);
  197.        {$IFDEF DFS_COMPILER_4_UP} reintroduce; overload; {$ENDIF} virtual;
  198.     procedure AfterDrawItem(var Canvas: TCanvas; Index: Integer;
  199.        Rect: TRect; State: TOwnerDrawState); virtual;
  200.     procedure Edit(const Item: TLVItem); override;
  201.     procedure EditCanceled(const Item: TLVItem); virtual;
  202.     { Overriden ancestor methods }
  203.     procedure ColClick(Column: TListColumn); override;
  204. {$IFDEF DFS_FIXED_LIST_VIEW}
  205.     procedure InsertItem(Item: TListItem); override;
  206. {$ENDIF}
  207.     procedure CreateWnd; override;
  208.     procedure DestroyWnd; override;
  209.     procedure ProcessDrawHeaderMsg(Index: Integer; Rect: TRect;
  210.        State: TOwnerDrawState; var DefaultDrawing: boolean); virtual;
  211.     procedure DrawHeader(var Canvas: TCanvas; Index: Integer; var Rect: TRect;
  212.        Selected: boolean; var DefaultDrawing: boolean); virtual;
  213.     procedure DefaultDrawHeader(var Canvas: TCanvas; Index: Integer;
  214.        var Rect: TRect; Selected: boolean); virtual;
  215.     procedure SetOnDrawHeader(Value: TLVHDrawItemEvent); virtual;
  216.     procedure SetColumnsOwnerDrawFlag(OwnerDrawn: boolean); virtual;
  217.     procedure CreateSortBmps(var UpBmp, DownBmp: TBitmap); virtual;
  218.  
  219.     { Property methods }
  220.     procedure SetAutoColumnSort(Value: TAutoColumnSort);
  221.     procedure SetAutoSortStyle(Value: TAutoSortStyle);
  222.     procedure SetCurrentSortAscending(Value: boolean);
  223.     procedure SetAutoSortAscending(Value: boolean);
  224.     procedure SetStyle(Value: TLVStyle);
  225.     procedure SetShowSortArrows(Value: boolean);
  226.     procedure SetReverseSortArrows(Value: boolean);
  227.     procedure SetLastColumnClicked(Value: integer);
  228.     procedure SetAutoResort(Value: boolean);
  229.     function GetVersion: TDFSVersion; virtual;
  230.     procedure SetVersion(const Val: TDFSVersion);
  231.     function GetCurrentColumnWidth(Index: integer): integer;
  232.  
  233.     procedure CreateParams(var Params: TCreateParams); override;
  234.     procedure Loaded; override;
  235.  
  236.     { Should probably remain protected }
  237.     property SortUpBmp: TBitmap
  238.       read FSortUpBmp;
  239.     property SortDownBmp: TBitmap
  240.       read FSortDownBmp;
  241.  
  242.     { Should be made public by descendants as needed }
  243.     property LastColumnClicked: Integer
  244.       read FLastColumnClicked
  245.       write SetLastColumnClicked;
  246.  
  247.     { Should be published by descendants as needed }
  248.     property HeaderHandle: HWnd
  249.        read FHeaderHandle;
  250.     property AutoColumnSort: TAutoColumnSort
  251.        read FAutoColumnSort
  252.        write SetAutoColumnSort
  253.        default acsNoSort;
  254.     property AutoSortStyle: TAutoSortStyle
  255.        read FAutoSortStyle
  256.        write SetAutoSortStyle
  257.        default assSmart;
  258.     property AutoResort: boolean
  259.        read FAutoResort
  260.        write SetAutoResort
  261.        default TRUE;
  262.     property AutoSortAscending: boolean
  263.        read FAutoSortAscending
  264.        write SetAutoSortAscending
  265.        default TRUE;
  266.     property ShowSortArrows: boolean
  267.        read FShowSortArrows
  268.        write SetShowSortArrows
  269.        default FALSE;
  270.     property ReverseSortArrows: boolean
  271.        read FReverseSortArrows
  272.        write SetReverseSortArrows
  273.        default FALSE; 
  274.     property CurrentSortAscending: boolean
  275.        read FTmpAutoSortAscending
  276.        write SetCurrentSortAscending;
  277.     property SaveSettings: TEnhLVSaveSettings
  278.        read FSaveSettings
  279.        write FSaveSettings;
  280.     property Style: TLVStyle
  281.        read FStyle
  282.        write SetStyle
  283.        default lvStandard;
  284.     property CurrentColumnWidth[Index: integer]: integer
  285.        read GetCurrentColumnWidth;
  286.  
  287.     { Events }
  288.     property OnDrawHeader: TLVHDrawItemEvent
  289.        read FOnDrawHeader
  290.        write SetOnDrawHeader;
  291.     property OnMeasureItem: TLVMeasureItemEvent
  292.        read FOnMeasureItem
  293.        write FOnMeasureItem;
  294.     property OnDrawItem: TLVDrawItemEvent
  295.        read FOnDrawItem
  296.        write FOnDrawItem;
  297.     property OnDrawSubItem: TLVDrawSubItemEvent
  298.        read FOnDrawSubItem
  299.        write FOnDrawSubItem;
  300.     property OnAfterDefaultDrawItem: TLVAfterDrawItemEvent
  301.        read FOnAfterDefaultDrawItem
  302.        write FOnAfterDefaultDrawItem;
  303.     property OnSortItems: TLVSortItemsEvent
  304.        read FOnSortItems
  305.        write FOnSortItems;
  306.     property OnSortBegin: TLVSortStatusEvent
  307.        read FOnSortBegin
  308.        write FOnSortBegin;
  309.     property OnSortFinished: TLVSortStatusEvent
  310.        read FOnSortFinished
  311.        write FOnSortFinished;
  312.     property OnEditCanceled: TLVEditCanceled
  313.        read FOnEditCanceled
  314.        write FOnEditCanceled;
  315.   public
  316.     constructor Create(AOwner: TComponent); override;
  317.     destructor Destroy; override;
  318.  
  319.     function StoreSettings: boolean; virtual;
  320.     function LoadSettings: boolean; virtual;
  321.     procedure DefaultSort(ColumnIndex:integer; Descending: boolean); virtual;
  322.     procedure Resort; virtual;
  323.     // Use these as replacements for Items.BeginUpdate and EndUpdate.  They
  324.     // call those methods, but they also inhibit autosorting until after the
  325.     // last EndUpdate.
  326.     procedure BeginUpdate; virtual;
  327.     procedure EndUpdate; virtual;
  328.  
  329.     // Resize all columns.
  330.     procedure ResizeColumns(ResizeMethod: TResizeMethod); virtual;
  331.  
  332.     // Accounts for re-ordered columns
  333.     property ActualColumn[Index: integer]: TListColumn
  334.        read GetActualColumn;
  335.   published
  336.     property Version: TDFSVersion
  337.        read GetVersion
  338.        write SetVersion
  339.        stored FALSE;
  340.   end;
  341.  
  342.  
  343.   TEnhListView = class(TCustomEnhListView)
  344.   public
  345.     property HeaderHandle;
  346.     property CurrentSortAscending;
  347.     property LastColumnClicked;
  348.     property CurrentColumnWidth;
  349.   published
  350.     property AutoColumnSort;
  351.     property AutoSortStyle;
  352.     property AutoResort;
  353.     property AutoSortAscending;
  354.     property ReverseSortArrows;
  355.     property ShowSortArrows;
  356.     property SaveSettings;
  357.     property Style;
  358.  
  359.     property OnMeasureItem;
  360.     property OnDrawItem;
  361.     property OnDrawSubItem;
  362.     property OnAfterDefaultDrawItem;
  363.     property OnDrawHeader;
  364.     property OnSortItems;
  365.     property OnSortBegin;
  366.     property OnSortFinished;
  367.     property OnEditCanceled;
  368.  
  369.     { Publish TCustomListView inherited protected properties }
  370.     property Align;
  371.     property BorderStyle;
  372.     property Color;
  373.     property ColumnClick;
  374.     property OnClick;
  375.     property OnDblClick;
  376.     property Columns;
  377.     property Ctl3D;
  378.     property DragMode;
  379.     property ReadOnly
  380.        default False;
  381.     property Enabled;
  382.     property Font;
  383.     property HideSelection;
  384.     property IconOptions;
  385.     property Items;
  386.     property AllocBy;
  387.     property MultiSelect;
  388.     property OnChange;
  389.     property OnChanging;
  390.     property OnColumnClick;
  391.     property OnDeletion;
  392.     property OnEdited;
  393.     property OnEditing;
  394.     property OnEnter;
  395.     property OnExit;
  396.     property OnInsert;
  397.     property OnDragDrop;
  398.     property OnDragOver;
  399.     property DragCursor;
  400.     property OnStartDrag;
  401.     property OnEndDrag;
  402.     property OnMouseDown;
  403.     property OnMouseMove;
  404.     property OnMouseUp;
  405.     property ParentColor
  406.        default False;
  407.     property ParentFont;
  408.     property ParentShowHint;
  409.     property ShowHint;
  410.     property PopupMenu;
  411.     property ShowColumnHeaders;
  412.     property TabOrder;
  413.     property TabStop
  414.        default True;
  415.     property ViewStyle;
  416.     property Visible;
  417.     property OnKeyDown;
  418.     property OnKeyPress;
  419.     property OnKeyUp;
  420.     property LargeImages;
  421.     property SmallImages;
  422.     property StateImages;
  423.   end;
  424.  
  425. var
  426.   { Default drawing variables }
  427.   DefDraw_TextOffset: integer; // Offset for the text -- 5
  428.   DefDraw_ImageOffset: integer; // Offset for image -- 2
  429.  
  430.  
  431. implementation
  432.  
  433. uses
  434.   {$IFDEF DFS_COMPILER_4_UP} ImgList, {$ENDIF} Registry;
  435.  
  436.  
  437. var
  438.   FDirection,
  439.   FSortColNum: integer;
  440.  
  441. function __CustomSortProc1__(Item1, Item2: TListItem; Data: integer): integer;
  442.    stdcall;
  443.  
  444.   function IsValidNumber(const S: string; var V: extended): boolean;
  445.   var
  446.     NumCode: integer;
  447.   begin
  448.     Val(S, V, NumCode);
  449.     Result := (NumCode = 0);
  450.   end;
  451.  
  452.   // date conversion will fail if using long format, e.g. '1 January 1994'
  453.   function IsValidDateTime(const S: string; var D: TDateTime): boolean;
  454.   var
  455.     HasDate: boolean;
  456.     HasTime: boolean;
  457.   begin
  458.     HasDate := Pos(DateSeparator, S) > 0;
  459.     HasTime := Pos(TimeSeparator, S) > 0;
  460.     Result := HasDate or HasTime;
  461.     if Result then
  462.     begin
  463.       try
  464.         if HasDate and HasTime then
  465.           D := StrToDateTime(S)
  466.         else if HasDate then
  467.           D := StrToDate(S)
  468.         else if HasTime then
  469.           D := StrToTime(S);
  470.       except
  471.         // Something failed to convert...
  472.         D := 0;
  473.         Result := FALSE;
  474.       end;
  475.     end;
  476.   end; { IsValidDateTime }
  477.  
  478. var
  479.   Str1, Str2: string;
  480.   Val1, Val2: extended;
  481.   Date1, Date2: TDateTime;
  482.   Diff: TDateTime;
  483. begin
  484.   if (Item1 = NIL) or (Item2 = NIL) then
  485.   begin
  486.     // something bad happening, I'm outta here
  487.     Result := 0;
  488.     exit;
  489.   end;
  490.  
  491.   try
  492.     if FSortColNum = -1 then
  493.     begin
  494.       //Str1 := Item1.Caption;
  495.       //Str2 := Item2.Caption;
  496.       { Changed by Michael Haller }
  497.       if Item1.StateIndex = -1 then begin
  498.         Str1 := IntToStr(Item1.ImageIndex);
  499.         Str2 := IntToStr(Item2.ImageIndex);
  500.       end else begin
  501.         Str1 := IntToStr(Item1.StateIndex);
  502.         Str2 := IntToStr(Item2.StateIndex);
  503.       end;
  504.     end else begin
  505.       if FSortColNum < Item1.SubItems.Count then
  506.         Str1 := Item1.SubItems[FSortColNum]
  507.       else
  508.         Str1 := '';
  509.       if FSortColNum < Item2.SubItems.Count then
  510.         Str2 := Item2.SubItems[FSortColNum]
  511.       else
  512.         Str2 := '';
  513.     end;
  514.  
  515.     if TCustomEnhListView(Data).AutoSortStyle = assSmart then
  516.     begin
  517.       if IsValidDateTime(Str1, Date1) and IsValidDateTime(Str2, Date2) then
  518.       begin
  519.         Diff := Date1 - Date2;
  520.         if Diff < 0.0 then Result := -1
  521.         else if Diff > 0.0 then Result := 1
  522.         else Result := 0
  523.       end else if IsValidNumber(Str1, Val1) and IsValidNumber(Str2, Val2) then
  524.       begin
  525.         if Val1 < Val2 then Result := -1
  526.         else if Val1 > Val2 then Result := 1
  527.         else Result := 0
  528.       end else
  529.         Result := AnsiCompareStr(Str1, Str2);
  530.     end else
  531.       Result := AnsiCompareStr(Str1, Str2);
  532.  
  533.     Result := FDirection * Result; // Set direction flag.
  534.   except
  535.     Result := 0;  // Something went bad in the comparison.  Say they are equal.
  536.   end;
  537. end;
  538.  
  539. function __CustomSortProc2__(Item1, Item2: TListItem; Data: integer): integer;
  540.    stdcall;
  541. var
  542.   EvRes: integer;
  543. begin
  544.   EvRes := 0;
  545.   TCustomEnhListView(Data).SortItems(Item1, Item2, FSortColNum, EvRes);
  546.   Result := EvRes * FDirection;
  547. end;
  548.  
  549. constructor TEnhLVSaveSettings.Create;
  550. begin
  551.   inherited Create;
  552.  
  553.   FAutoSave := FALSE;
  554.   FRegistryKey := '';
  555.   FSaveColumnSizes := TRUE;
  556.   SaveCurrentSort := TRUE;
  557. end;
  558.  
  559. procedure TEnhLVSaveSettings.StoreColumnSizes(ColCount: integer;
  560.    const IntArray: array of integer);
  561. var
  562.   Reg: TRegIniFile;
  563.   x: integer;
  564.   s: string;
  565. begin
  566.   if ColCount < 1 then exit;
  567.   s := '';
  568.   { Changed by Michael Haller }
  569.   s := '20,';
  570.   for x := 1 to ColCount-1 do
  571.     s := s + IntToStr(IntArray[x]) + ',';
  572.   SetLength(s, Length(s)-1);
  573.   Reg := TRegIniFile.Create(FRegistryKey);
  574.   try
  575.     Reg.WriteString('Columns', 'Sizes', s);
  576.   finally
  577.     Reg.Free;
  578.   end;
  579. end;
  580.  
  581. procedure TEnhLVSaveSettings.ReadColumnSizes(ColCount: integer;
  582.    var IntArray: array of integer);
  583. var
  584.   Reg: TRegIniFile;
  585.   x,y: integer;
  586.   s: string;
  587. begin
  588.   if ColCount < 1 then exit;
  589.   s := '';
  590.   Reg := TRegIniFile.Create(FRegistryKey);
  591.   try
  592.     s := Reg.ReadString('Columns', 'Sizes', '');
  593.   finally
  594.     Reg.Free;
  595.   end;
  596.   if s = '' then
  597.   begin
  598.     IntArray[0] := -1;
  599.     exit;
  600.   end;
  601.   y := 0;
  602.   for x := 0 to ColCount-1 do
  603.   begin
  604.     try
  605.       y := Pos(',', s);
  606.       if y = 0 then
  607.         y := Length(s)+1;
  608.       IntArray[x] := StrToInt(Copy(s, 1, y-1));
  609.     except
  610.       IntArray[x] := 0;
  611.     end;
  612.     s := copy(s, y+1, length(s));
  613.     if s = '' then break;
  614.   end;
  615. end;
  616.  
  617. procedure TEnhLVSaveSettings.StoreCurrentSort(Ascending: boolean;
  618.    SortCol: integer);
  619. var
  620.   Reg: TRegIniFile;
  621. begin
  622.   Reg := TRegIniFile.Create(FRegistryKey);
  623.   try
  624.     //Reg.WriteBool('Sort', 'Ascending', Ascending);
  625.     { Changed by Michael Haller }
  626.     if Ascending then
  627.       Reg.WriteString('Sort', 'Ascending', '1')
  628.     else
  629.       Reg.WriteString('Sort', 'Ascending', '0');
  630.     Reg.WriteInteger('Sort', 'SortCol', SortCol);
  631.   finally
  632.     Reg.Free;
  633.   end;
  634. end;
  635.  
  636. procedure TEnhLVSaveSettings.ReadCurrentSort(var Ascending: boolean;
  637.    var SortCol: integer);
  638. var
  639.   Reg: TRegIniFile;
  640. begin
  641.   Reg := TRegIniFile.Create(FRegistryKey);
  642.   try
  643.     Ascending := Reg.ReadBool('Sort', 'Ascending', TRUE);
  644.     SortCol := Reg.ReadInteger('Sort', 'SortCol', 0);
  645.   finally
  646.     Reg.Free;
  647.   end;
  648. end;
  649.  
  650.  
  651. // Override constructor to "zero out" our internal variable.
  652. constructor TCustomEnhListView.Create(AOwner: TComponent);
  653. begin
  654.   inherited Create(AOwner);
  655.  
  656.   FHeaderHandle := 0;
  657.   FSortDirty := FALSE;
  658.   FUpdateCount := 1; // inhibit sorting until finished creating.
  659.   FSaveSettings := TEnhLVSaveSettings.Create;
  660.   FAutoColumnSort := acsNoSort;
  661.   FAutoResort := TRUE;
  662.   FAutoSortStyle := assSmart;
  663.   FAutoSortAscending := TRUE;
  664.   FTmpAutoSortAscending := FAutoSortAscending;
  665.   FLastColumnClicked := -1;
  666.   FCanvas := NIL;
  667.   FStyle  := lvStandard;
  668.   FSortUpBmp := NIL;
  669.   FSortDownBmp := NIL;
  670.   FShowSortArrows := FALSE;
  671.   FReverseSortArrows := FALSE;
  672. end;
  673.  
  674. destructor TCustomEnhListView.Destroy;
  675. begin
  676.   FSortUpBmp.Free;
  677.   FSortDownBmp.Free;
  678.   FCanvas.Free;
  679.  
  680.   inherited Destroy;
  681.  
  682.   FSaveSettings.Free;
  683. end;
  684.  
  685. procedure TCustomEnhListView.CreateParams(var Params: TCreateParams);
  686. begin
  687.   inherited CreateParams(Params);
  688.  
  689.   if (FStyle = lvOwnerDrawFixed) then
  690.   begin
  691.     Params.Style := Params.Style or LVS_OWNERDRAWFIXED;
  692.     if FCanvas = NIL then
  693.       FCanvas := TCanvas.Create;
  694.   end else
  695.   begin
  696.     if (not assigned(FOnDrawHeader)) and (not FShowSortArrows) then
  697.     begin
  698.       FCanvas.Free;
  699.       FCanvas := NIL;
  700.     end;
  701.   end;
  702. end;
  703.  
  704. procedure TCustomEnhListView.CreateWnd;
  705. begin
  706.   inherited CreateWnd;
  707.   // If we are loading object from stream (form file), we have to wait until
  708.   // everything is loaded before populating the list.  If we are not loading,
  709.   // i.e. the component was created dynamically or was just dropped on a form,
  710.   // we need to reset the flag now.
  711.   if not (csLoading in ComponentState) then
  712.     FUpdateCount := 0;
  713. end;
  714.  
  715. procedure TCustomEnhListView.Loaded;
  716. begin
  717.   inherited Loaded;
  718.  
  719.   HandleNeeded;
  720.   FUpdateCount := 0;
  721.  
  722.   if (not LoadSettings) or (not SaveSettings.SaveCurrentSort) then
  723.   begin
  724.     if Columns.Count > 0 then
  725.       FLastColumnClicked := 0;
  726.     Resort;
  727.   end;
  728.  
  729.   // Something flaky going on.  Hard to explain, but this clears it up.
  730.   PostMessage(Handle, WM_OWNERDRAWCOLUMNS, 0, 0);
  731. end;
  732.  
  733. procedure TCustomEnhListView.WMDestroy(var Message: TWMDestroy);
  734. begin
  735.   StoreSettings;
  736.  
  737.   inherited;
  738. end;
  739.  
  740.  
  741. function TCustomEnhListView.StoreSettings: boolean;
  742. var
  743.   ColCount: integer;
  744.   ColArray: PIntArray;
  745.   x: integer;
  746. begin
  747.   if FSaveSettings.AutoSave and
  748.      (([csDesigning, csLoading, csReading] * ComponentState) = []) then
  749.   begin
  750.     Result := TRUE;
  751.     ColCount := Columns.Count;
  752.     if ColCount > 0 then
  753.     begin
  754.       GetMem(ColArray, SizeOf(Integer)*ColCount);
  755.       try
  756.         if FSaveSettings.SaveColumnSizes then
  757.         begin
  758.           for x := 0 to ColCount-1 do
  759.             ColArray[x] := ActualColumn[x].Width;
  760.           FSaveSettings.StoreColumnSizes(ColCount, ColArray^);
  761.         end;
  762.         if FSaveSettings.SaveCurrentSort then
  763.           FSaveSettings.StoreCurrentSort(CurrentSortAscending, LastColumnClicked);
  764.       finally
  765.         FreeMem(ColArray);
  766.       end;
  767.     end;
  768.   end else
  769.     Result := FALSE;
  770. end;
  771.  
  772. function TCustomEnhListView.LoadSettings: boolean;
  773. var
  774.   ColCount: integer;
  775.   ColArray: PIntArray;
  776.   x: integer;
  777.   SortCol: integer;
  778.   SortAscending: boolean;
  779. begin
  780.   if FSaveSettings.AutoSave and (not(csDesigning in ComponentState)) then
  781.   begin
  782.     Result := TRUE;
  783.     ColCount := Columns.Count;
  784.     if ColCount > 0 then
  785.     begin
  786.       GetMem(ColArray, SizeOf(Integer)*ColCount);
  787.       try
  788.         if FSaveSettings.SaveColumnSizes then
  789.         begin
  790.           FSaveSettings.ReadColumnSizes(ColCount, ColArray^);
  791.           if ColArray[0] <> -1 then
  792.             for x := 0 to ColCount-1 do
  793.               ActualColumn[x].Width := ColArray[x];
  794.         end;
  795.       finally
  796.         FreeMem(ColArray);
  797.       end;
  798.     end;
  799.  
  800.     if FSaveSettings.SaveCurrentSort then
  801.     begin
  802.       FSaveSettings.ReadCurrentSort(SortAscending, SortCol);
  803.       if SortCol >= Columns.Count then
  804.         SortCol := Columns.Count-1;
  805.       if SortCol < 0 then
  806.         SortCol := 0;
  807.       BeginUpdate;
  808.       try
  809.         CurrentSortAscending := SortAscending;
  810.         LastColumnClicked := SortCol;
  811.         Resort;
  812.       finally
  813.         EndUpdate;
  814.       end;
  815.     end;
  816.   end else
  817.     Result := FALSE;
  818. end;
  819.  
  820.  
  821. procedure TCustomEnhListView.DoSort(ColumnIndex:integer; Descending: boolean);
  822. begin
  823.   FSortDirty := FALSE;
  824.   LastColumnClicked := ColumnIndex;
  825.   SortBegin(ColumnIndex, not Descending);
  826.   if Descending then
  827.     FDirection := 1
  828.   else
  829.     FDirection := -1;
  830.   FSortColNum := ColumnIndex - 1;
  831.   if assigned(FOnSortItems) then
  832.     CustomSort(@__CustomSortProc2__, integer(Self))
  833.   else
  834.     CustomSort(@__CustomSortProc1__, integer(Self));
  835.   SortFinished(ColumnIndex, not Descending);
  836. end;
  837.  
  838. procedure TCustomEnhListView.DefaultSort(ColumnIndex: integer;
  839.    Descending: boolean);
  840. begin
  841.   // Check if the sort order should be toggled
  842.   if FAutoColumnSort = acsSortToggle then
  843.     if LastColumnClicked = ColumnIndex then
  844.       FTmpAutoSortAscending := not Descending
  845.     else
  846.       FTmpAutoSortAscending := Descending;
  847.  
  848.   InvalidateColumnHeader(ColumnIndex);
  849.   DoSort(ColumnIndex, Descending);
  850. end;
  851.  
  852. procedure TCustomEnhListView.SortItems(const Item1, Item2: TListItem;
  853.    SortColumn: integer; var CompResult: integer);
  854. begin
  855.   // The only way to get in here is if FOnSortItems is assigned, so don't bother
  856.   //  checking for NIL
  857.   FonSortItems(Self, Item1, Item2, SortColumn, CompResult);
  858. end;
  859.  
  860. procedure TCustomEnhListView.SortBegin(ColumnIndex: integer;
  861.    Ascending: boolean);
  862. begin
  863.   if assigned(FOnSortBegin) then
  864.     FOnSortBegin(Self, ColumnIndex, Ascending);
  865. end;
  866.  
  867. procedure TCustomEnhListView.SortFinished(ColumnIndex: integer;
  868.    Ascending: boolean);
  869. begin
  870.   if assigned(FOnSortFinished) then
  871.     FOnSortFinished(Self, ColumnIndex, Ascending);
  872. end;
  873.  
  874. procedure TCustomEnhListView.ColClick(Column: TListColumn);
  875. begin
  876.   // Check if the sort order should be toggled
  877.   if FAutoColumnSort = acsSortToggle then
  878.     if LastColumnClicked = Column.Index then
  879.       FTmpAutoSortAscending := not FTmpAutoSortAscending
  880.     else
  881.       FTmpAutoSortAscending := FAutoSortAscending;
  882.  
  883.   inherited ColClick(Column);
  884.  
  885.   if (FAutoColumnSort <> acsNoSort) and (Column.Index < Columns.Count) then
  886.     DoSort(Column.Index, FTmpAutoSortAscending);
  887.  
  888.   LastColumnClicked := Column.Index;
  889. end;
  890.  
  891. {$IFDEF DFS_FIXED_LIST_VIEW}
  892. procedure TCustomEnhListView.InsertItem(Item: TListItem);
  893. begin
  894.   inherited InsertItem(Item);
  895.   if FAutoResort then
  896.     Resort;
  897. end;
  898. {$ENDIF}
  899.  
  900.  
  901. procedure TCustomEnhListView.Edit(const Item: TLVItem);
  902. begin
  903.   inherited Edit(Item);
  904.   if FAutoResort then
  905.     Resort;
  906. end;
  907.  
  908. type
  909.   THackListItems = class(TListItems)
  910.   end;
  911.  
  912. procedure TCustomEnhListView.EditCanceled(const Item: TLVItem);
  913. begin
  914.   if assigned(FOnEditCanceled) then
  915.     with Item do
  916.       FOnEditCanceled(Self, THackListItems(Items).GetItem(iItem));
  917. end;
  918.  
  919. procedure TCustomEnhListView.CNNotify(var Message: TWMNotify);
  920. begin
  921.   inherited;
  922.  
  923.   with Message.NMHdr^ do
  924.     case code of
  925. {$IFNDEF DFS_FIXED_LIST_VIEW}
  926.       LVN_INSERTITEM:
  927.         if FAutoResort then
  928.           Resort;
  929. {$ENDIF}
  930.       LVN_ENDLABELEDIT:
  931.         with PLVDispInfo(Pointer(Message.NMHdr))^ do
  932.           if (item.pszText = NIL) and (item.IItem <> -1) then
  933.             EditCanceled(item);
  934.     end;
  935. end;
  936.  
  937. procedure TCustomEnhListView.SetAutoColumnSort(Value: TAutoColumnSort);
  938. begin
  939.   if FAutoColumnSort <> Value then
  940.   begin
  941.     FAutoColumnSort := Value;
  942.     if FAutoColumnSort <> acsNoSort then
  943.       Resort;
  944.   end;
  945. end;
  946.  
  947. procedure TCustomEnhListView.SetAutoSortStyle(Value: TAutoSortStyle);
  948. begin
  949.   if FAutoSortStyle <> Value then
  950.   begin
  951.     FAutoSortStyle := Value;
  952.     Resort;
  953.   end;
  954. end;
  955.  
  956. procedure TCustomEnhListView.SetAutoResort(Value: boolean);
  957. begin
  958.   if FAutoResort <> Value then
  959.     FAutoResort := Value;
  960. end;
  961.  
  962. procedure TCustomEnhListView.SetCurrentSortAscending(Value: boolean);
  963. begin
  964.   if FTmpAutoSortAscending <> Value then
  965.   begin
  966.     FTmpAutoSortAscending := Value;
  967.     InvalidateColumnHeader(FLastColumnClicked);
  968.   end;
  969. end;
  970.  
  971. procedure TCustomEnhListView.SetAutoSortAscending(Value: Boolean);
  972. begin
  973.   if FAutoSortAscending <> Value then
  974.   begin
  975.     FAutoSortAscending := Value;
  976.     FTmpAutoSortAscending := Value;
  977.   end;
  978. end;
  979.  
  980. procedure TCustomEnhListView.Resort;
  981. begin
  982.   FSortDirty := TRUE;
  983.   if ((FAutoColumnSort <> acsNoSort) and (LastColumnClicked >= 0) and
  984.      (LastColumnClicked < Columns.Count)) or (assigned(FOnSortItems)) then
  985.   begin
  986.     if FUpdateCount < 1 then
  987.       DoSort(LastColumnClicked, FTmpAutoSortAscending);
  988.   end;
  989. end;
  990.  
  991. procedure TCustomEnhListView.BeginUpdate;
  992. begin
  993.   Items.BeginUpdate;
  994.   inc(FUpdateCount);
  995. end;
  996.  
  997.  
  998. procedure TCustomEnhListView.EndUpdate;
  999. begin
  1000.   dec(FUpdateCount);
  1001.   if FUpdateCount < 0 then
  1002.     FUpdateCount := 0; // In case someone gets overly happy with EndUpdate calls
  1003.   if FUpdateCount = 0 then
  1004.   begin
  1005.     // Need to resort?
  1006.     if FSortDirty then
  1007.       Resort;
  1008.   end;
  1009.  
  1010.   // Call this last so resort happens before screen redraw is re-enabled.
  1011.   Items.EndUpdate;
  1012. end;
  1013.  
  1014.  
  1015. procedure TCustomEnhListView.DrawItem(var Canvas: TCanvas; Index: Integer;
  1016.    Rect: TRect; State: TOwnerDrawState; var DefaultDrawing,
  1017.    FullRowSelect: boolean);
  1018. begin
  1019.   DefaultDrawing := not assigned(FOnDrawItem);
  1020.   if assigned(FOnDrawItem) then
  1021.     FOnDrawItem(Self, Canvas, Index, Rect, State, DefaultDrawing,FullRowSelect);
  1022. end;
  1023.  
  1024. procedure TCustomEnhListView.AfterDrawItem(var Canvas: TCanvas; Index: Integer;
  1025.    Rect: TRect; State: TOwnerDrawState);
  1026. begin
  1027.   if assigned(FOnAfterDefaultDrawItem) then
  1028.     FOnAfterDefaultDrawItem(Self, Canvas, Index, Rect, State);
  1029. end;
  1030.  
  1031. procedure TCustomEnhListView.CMSysColorChange(var Message: TWMSysColorChange);
  1032. begin
  1033.   // Need to recreate the sort arrow bmps to use the new system colors
  1034.   if ShowSortArrows then
  1035.     CreateSortBmps(FSortUpBmp, FSortDownBmp);
  1036.   inherited;
  1037. end;
  1038.  
  1039. procedure TCustomEnhListView.CNMeasureItem(var Message: TWMMeasureItem);
  1040. begin
  1041.   inherited;
  1042.   MeasureItem(Message.MeasureItemStruct.itemHeight);
  1043.   Message.Result := 1;
  1044. end;
  1045.  
  1046. procedure TCustomEnhListView.MeasureItem(var Height: UINT);
  1047. begin
  1048.   if assigned(FOnMeasureItem) then
  1049.     FOnMeasureItem(Self, Height);
  1050. end;
  1051.  
  1052.  
  1053. procedure TCustomEnhListView.CNDrawItem(var Message: TWMDrawItem);
  1054. var
  1055.   State: TOwnerDrawState;
  1056.   DoDefaultDrawing: boolean;
  1057.   FullRowSelect: boolean;
  1058.   SavedDC: integer;
  1059. begin { CNDrawItem }
  1060.   If FCanvas = NIL then exit;
  1061.  
  1062.   with Message.DrawItemStruct^ do
  1063.   begin
  1064.     State := TOwnerDrawState(WordRec(LongRec(itemState).Lo).Lo);
  1065.     SavedDC := SaveDC(hDC);
  1066.     FCanvas.Handle := hDC;
  1067.     try
  1068.       FCanvas.Font := Font;
  1069.       FCanvas.Brush := Brush;
  1070.       DoDefaultDrawing := FALSE;
  1071.       FullRowSelect := FALSE;
  1072.       ProcessDrawItemMsg(itemID, rcItem, State, DoDefaultDrawing, FullRowSelect);
  1073.     finally
  1074.       FCanvas.Handle := 0;
  1075.       RestoreDC(hDC, SavedDC);
  1076.     end;
  1077.   end;
  1078.  
  1079.   Message.Result := 1;
  1080. end;
  1081.  
  1082. function TCustomEnhListView.GetActualColumn(Index: integer): TListColumn;
  1083. begin
  1084.   // Delphi 2 and C++B 1 have a bug in TListColumn.GetWidth.  It returns zero
  1085.   // for the width if the handle hasn't been allocated yet instead of returning
  1086.   // the value of the internal storage variable like Delphi 3 does.  I've also
  1087.   // had some problems similar under Delphi 3, so I'm just always requiring the
  1088.   // handle to be valid.
  1089.   HandleNeeded;
  1090.  
  1091.   if Index >= Columns.Count then
  1092.     Result := NIL
  1093.   else
  1094.     Result := Columns[Index];
  1095. end;
  1096.  
  1097. function TCustomEnhListView.GetSubItemText(Index, SubItem: integer): string;
  1098. begin
  1099.   if SubItem < 0 then
  1100.     Result := Items[Index].Caption
  1101.   else
  1102.     Result := Items[Index].SubItems[SubItem];
  1103. end;
  1104.  
  1105. // SubItem is -1 for Caption item
  1106. procedure TCustomEnhListView.DrawSubItem(Index, SubItem: Integer; Rect: TRect;
  1107.    State: TOwnerDrawState; var DefaultDrawing: boolean);
  1108. begin
  1109.   DefaultDrawing := not assigned(FOnDrawSubItem);
  1110.   if assigned(FOnDrawSubItem) then
  1111.     FOnDrawSubItem(Self, FCanvas, Index, SubItem, Rect, State, DefaultDrawing);
  1112. end;
  1113.  
  1114. procedure TCustomEnhListView.DefaultDrawSubItem(Index, SubItem: Integer;
  1115.    Rect: TRect; State: TOwnerDrawState);
  1116. var
  1117.   DoDefaultDrawing: boolean;
  1118.   SavedDC: integer;
  1119. begin
  1120.   DoDefaultDrawing := csDesigning in ComponentState;
  1121.   SavedDC := SaveDC(FCanvas.Handle);
  1122.   try
  1123.     if not (csDesigning in ComponentState) then
  1124.       DrawSubItem(Index, SubItem, Rect, State, DoDefaultDrawing);
  1125.  
  1126.     if DoDefaultDrawing then
  1127.       DrawTextEx(FCanvas.Handle, PChar(GetSubItemText(Index, SubItem)), -1, Rect,
  1128.          DRAWTEXTEX_FLAGS or
  1129.          DRAWTEXTEX_ALIGNMENT[ActualColumn[SubItem+1].Alignment], NIL);
  1130.   finally
  1131.     RestoreDC(FCanvas.Handle, SavedDC);
  1132.   end;
  1133. end;
  1134.  
  1135. {$IFDEF DFS_COMPILER_4_UP}
  1136. type
  1137.   THackImageList = class(TCustomImageList);
  1138. {$ENDIF}
  1139.  
  1140. procedure TCustomEnhListView.DefaultDrawItem(Index: Integer; Rect: TRect;
  1141.    State: TOwnerDrawState; FullRowSelect: boolean);
  1142. {$IFDEF DFS_COMPILER_4_UP}
  1143. const
  1144.   DrawingStyles: array[TDrawingStyle] of Longint = (ILD_FOCUS, ILD_SELECTED,
  1145.     ILD_NORMAL, ILD_TRANSPARENT);
  1146.   Images: array[TImageType] of Longint = (0, ILD_MASK);
  1147. {$ENDIF}
  1148. var
  1149. {$IFDEF DFS_COMPILER_4_UP}
  1150.   DS: TDrawingStyle;
  1151. {$ELSE}
  1152.   OldStyle: TDrawingStyle;
  1153. {$ENDIF}
  1154.   OldBlend: TColor;
  1155.   Count: Integer;
  1156.   SubRect: TRect;
  1157. begin
  1158.   if Items[Index] = NIL then
  1159.     // something bad happening, I'm outta here
  1160.     exit;
  1161.  
  1162.   if Columns.Count > 0 then
  1163.   begin
  1164.     if (odSelected in State) then
  1165.     begin
  1166.       if Focused then
  1167.       begin
  1168.         FCanvas.Brush.Color := clHighlight;
  1169.         FCanvas.Font.Color := clHighlightText;
  1170.       end else begin
  1171.         if not HideSelection then
  1172.         begin
  1173.           FCanvas.Brush.Color := clBtnFace;
  1174.           FCanvas.Font.Color := clBtnText;
  1175.         end;
  1176.       end;
  1177.     end;
  1178.     SubRect := Rect;
  1179.     SubRect.Right := Rect.Left + CurrentColumnWidth[0] - 2;
  1180.  
  1181.     if assigned(SmallImages) then
  1182.     begin
  1183.       OldBlend := SmallImages.BlendColor;
  1184.       SmallImages.BlendColor := clHighlight;
  1185.       {$IFDEF DFS_COMPILER_4_UP}
  1186.       { Changing DrawStyle causes an invalidate, which is very nasty since we
  1187.         are in the process of repainting here.  Continuous flickering.... }
  1188.       if (odSelected in State) and Focused then
  1189.         DS := dsSelected
  1190.       else
  1191.         DS := dsTransparent;
  1192.       THackImageList(SmallImages).DoDraw(Items[Index].ImageIndex, FCanvas,
  1193.          Rect.Left + DefDraw_ImageOffSet, Rect.Top,
  1194.          DrawingStyles[DS] or Images[SmallImages.ImageType], Enabled);
  1195.       {$ELSE}
  1196.       OldStyle := SmallImages.DrawingStyle;
  1197.       if (odSelected in State) and Focused then
  1198.         SmallImages.DrawingStyle := dsSelected
  1199.       else
  1200.         SmallImages.DrawingStyle := dsTransparent;
  1201.  
  1202.       SmallImages.Draw(FCanvas, Rect.Left + DefDraw_ImageOffSet, Rect.Top,
  1203.          Items[Index].ImageIndex);
  1204.       SmallImages.DrawingStyle := OldStyle;
  1205.       {$ENDIF}
  1206.       SmallImages.BlendColor := OldBlend;
  1207.       if ActualColumn[0].Alignment = taLeftJustify then
  1208.         Inc(SubRect.Left, DefDraw_TextOffset + SmallImages.Width);
  1209.     end else begin
  1210.       if ActualColumn[0].Alignment = taLeftJustify then
  1211.         Inc(SubRect.Left, DefDraw_TextOffset);
  1212.     end;
  1213.  
  1214.     DefaultDrawSubItem(Index, -1, SubRect, State);
  1215.  
  1216.     // Already done column 0, start at 1.
  1217.     for Count := 1 to Columns.Count-1 do
  1218.     begin
  1219.       { Restore this through each iteration since they may screw with it in
  1220.         the OnDrawSubItem event. }
  1221.       if not FullRowSelect then
  1222.       begin
  1223.         FCanvas.Brush.Color := clWindow;
  1224.         FCanvas.Font.Color := clWindowText;
  1225.       end;
  1226.  
  1227.       if Count > Items[Index].SubItems.Count then
  1228.         continue; // Hidden item
  1229.       if ActualColumn[Count].Alignment = taLeftJustify then
  1230.       begin
  1231.         SubRect.Left := SubRect.Right;
  1232.         SubRect.Right := SubRect.Left + CurrentColumnWidth[Count];
  1233.         Inc(SubRect.Left, DefDraw_TextOffset)
  1234.       end else begin
  1235.         SubRect.Left := SubRect.Right + DefDraw_TextOffset;
  1236.         SubRect.Right := SubRect.Left + CurrentColumnWidth[Count];
  1237.         Dec(SubRect.Right, DefDraw_TextOffset);
  1238.       end;
  1239.       DefaultDrawSubItem(Index, Count-1, SubRect, State);
  1240.     end;
  1241.   end;
  1242. end;
  1243.  
  1244.  
  1245. procedure TCustomEnhListView.ProcessDrawItemMsg(Index: Integer; Rect: TRect;
  1246.    State: TOwnerDrawState; var DefaultDrawing, FullRowSelect: boolean);
  1247. var
  1248.   SubRect: TRect;
  1249. begin
  1250.   DefaultDrawing := csDesigning in ComponentState;
  1251.   if not (csDesigning in ComponentState) then
  1252.     DrawItem(FCanvas, Index, Rect, State, DefaultDrawing, FullRowSelect);
  1253.  
  1254.   if DefaultDrawing then
  1255.   begin
  1256.     FCanvas.FillRect(Rect);
  1257.  
  1258.     if (Index >= 0) then
  1259.     begin
  1260.       if (odSelected in State) then
  1261.       begin
  1262.         if (not HideSelection) or Focused then
  1263.         begin
  1264.           if Focused then
  1265.             FCanvas.Brush.Color := clHighlight
  1266.           else
  1267.             FCanvas.Brush.Color := clBtnFace;
  1268.           SubRect := Rect;
  1269.           Inc(SubRect.Left, DefDraw_TextOffset - 2);
  1270.           if (not FullRowSelect) then
  1271.           begin
  1272.             if assigned(Items[Index]) then
  1273.               SubRect.Right := SubRect.Left +
  1274.                  FCanvas.TextWidth(Items[Index].Caption) + 8;
  1275.             if assigned(SmallImages) then
  1276.               OffsetRect(SubRect, SmallImages.Width, 0);
  1277.             // Don't let it go past first column width
  1278.             if (Columns.Count > 0) and
  1279.                (CurrentColumnWidth[0] < SubRect.Right) then
  1280.               SubRect.Right := CurrentColumnWidth[0];
  1281.           end else
  1282.             if assigned(SmallImages) then
  1283.               Inc(SubRect.Left, SmallImages.Width);
  1284.           FCanvas.FillRect(SubRect);
  1285.         end;
  1286.       end;
  1287.       DefaultDrawItem(Index, Rect, State, FullRowSelect);
  1288.       if (odFocused in State) and Focused then
  1289.       begin
  1290.         SubRect := Rect;
  1291.         Inc(SubRect.Left, DefDraw_TextOffset - 2);
  1292.         if (not FullRowSelect) then
  1293.         begin
  1294.           if assigned(Items[Index]) then
  1295.             SubRect.Right := SubRect.Left +
  1296.                FCanvas.TextWidth(Items[Index].Caption) + 8;
  1297.             if assigned(SmallImages) then
  1298.               OffsetRect(SubRect, SmallImages.Width, 0);
  1299.             // Don't let it go past first column width
  1300.             if (Columns.Count > 0) and
  1301.                (CurrentColumnWidth[0] < SubRect.Right) then
  1302.               SubRect.Right := CurrentColumnWidth[0];
  1303.         end else
  1304.           if assigned(SmallImages) then
  1305.             Inc(SubRect.Left, SmallImages.Width);
  1306.         FCanvas.DrawFocusRect(SubRect);
  1307.       end;
  1308.     end else
  1309.       FCanvas.FillRect(Rect);
  1310.  
  1311.     if (not (csDesigning in ComponentState)) then
  1312.       AfterDrawItem(FCanvas, Index, Rect, State);
  1313.   end;
  1314. end;
  1315.  
  1316.  
  1317. procedure TCustomEnhListView.SetStyle(Value: TLVStyle);
  1318. begin
  1319.   if FStyle <> Value then
  1320.   begin
  1321.     FStyle := Value;
  1322.     if HandleAllocated then
  1323.       RecreateWnd;
  1324.   end;
  1325. end;
  1326.  
  1327. procedure TCustomEnhListView.SetReverseSortArrows(Value: boolean);
  1328. begin
  1329.   if Value <> FReverseSortArrows then
  1330.   begin
  1331.     FReverseSortArrows := Value;
  1332.     if ShowSortArrows then
  1333.     begin
  1334.       CreateSortBmps(FSortUpBmp, FSortDownBmp);
  1335.       InvalidateColumnHeader(FLastColumnClicked);
  1336.     end;
  1337.   end;
  1338. end;
  1339.  
  1340. procedure TCustomEnhListView.SetShowSortArrows(Value: boolean);
  1341. begin
  1342.   if Value <> FShowSortArrows then
  1343.     FShowSortArrows := Value;
  1344.   FSortUpBmp.Free;
  1345.   FSortDownBmp.Free;
  1346.   if FShowSortArrows then
  1347.   begin
  1348.     FSortUpBmp := TBitmap.Create;
  1349.     FSortDownBmp := TBitmap.Create;
  1350.     CreateSortBmps(FSortUpBmp, FSortDownBmp);
  1351.     if not (csReading in ComponentState) then
  1352.       SetColumnsOwnerDrawFlag(TRUE);
  1353.   end else begin
  1354.     FSortUpBmp := NIL;
  1355.     FSortDownBmp := NIL;
  1356.  
  1357.     if not (csReading in ComponentState) then
  1358.       SetColumnsOwnerDrawFlag(assigned(FOnDrawHeader))
  1359.   end;
  1360.   if HandleAllocated then
  1361.     Invalidate;
  1362. end;
  1363.  
  1364. procedure TCustomEnhListView.CreateSortBmps(var UpBmp, DownBmp: TBitmap);
  1365. var
  1366.   HeaderHeight: integer;
  1367.   MidPoint: integer;
  1368.   Bmp: TBitmap;
  1369. begin
  1370.   if UpBmp = NIL then
  1371.     UpBmp := TBitmap.Create;
  1372.   if DownBmp = NIL then
  1373.     DownBmp := TBitmap.Create;
  1374.  
  1375.   UpBmp.Canvas.Font.Assign(Font);
  1376.   HeaderHeight := UpBmp.Canvas.TextHeight('Wy') - 6;
  1377.   if HeaderHeight > 0 then
  1378.   begin
  1379.     if Odd(HeaderHeight) then
  1380.       Inc(HeaderHeight);
  1381.     UpBmp.Width := HeaderHeight;
  1382.     UpBmp.Height := HeaderHeight;
  1383.     DownBmp.Width := HeaderHeight;
  1384.     DownBmp.Height := HeaderHeight;
  1385.     MidPoint := HeaderHeight div 2;
  1386.  
  1387.     { Don't ask about the drawing.  I just fooled around until I got
  1388.       something I liked. }
  1389.     if FReverseSortArrows then
  1390.       Bmp := UpBmp
  1391.     else
  1392.       Bmp := DownBmp;
  1393.     with Bmp.Canvas do
  1394.     begin
  1395.       {changed by Michael Haller}
  1396.       Brush.Color := clBtnFace;
  1397.       FillRect(Rect(0, 0, HeaderHeight, HeaderHeight));
  1398.       Pen.Color := clBtnHighlight;
  1399.       MoveTo(MidPoint, HeaderHeight-2);
  1400.       LineTo(HeaderHeight-1, 0);
  1401.       Pixels[HeaderHeight-1, 0] := Pen.Color;
  1402.       Pen.Color := clBtnShadow;
  1403.       MoveTo(HeaderHeight-2, 0);
  1404.       LineTo(0, 0);
  1405.       LineTo(MidPoint-1, HeaderHeight-2);
  1406.       Pixels[MidPoint-1, HeaderHeight-2] := Pen.Color;
  1407.     end;
  1408.  
  1409.     if FReverseSortArrows then
  1410.       Bmp := DownBmp
  1411.     else
  1412.       Bmp := UpBmp;
  1413.     with Bmp.Canvas do
  1414.     begin
  1415.       Brush.Color := clBtnFace;
  1416.       FillRect(Rect(0, 0, HeaderHeight, HeaderHeight));
  1417.       Pen.Color := clBtnShadow;
  1418.       MoveTo(0, HeaderHeight-1);
  1419.       LineTo(MidPoint-1, 0);
  1420.       Pen.Color := clBtnHighlight;
  1421.       MoveTo(MidPoint, 0);
  1422.       LineTo(HeaderHeight-1, HeaderHeight-1);
  1423.       LineTo(-1, HeaderHeight-1);
  1424.       Pixels[MidPoint, 0] := clBtnFace;
  1425.     end;
  1426.   end;
  1427. end;
  1428.  
  1429. procedure TCustomEnhListView.DestroyWnd;
  1430. begin
  1431.   inherited DestroyWnd;
  1432.  
  1433.   FHeaderHandle := 0;
  1434. end;
  1435.  
  1436. procedure TCustomEnhListView.DrawHeader(var Canvas: TCanvas; Index: Integer;
  1437.    var Rect: TRect; Selected: boolean; var DefaultDrawing: boolean);
  1438. begin
  1439.   DefaultDrawing := not assigned(FOnDrawHeader);
  1440.   if assigned(FOnDrawHeader) then
  1441.     FOnDrawHeader(Self, Canvas, Index, Rect, Selected, DefaultDrawing);
  1442. end;
  1443.  
  1444. procedure TCustomEnhListView.WMNotify(var Message: TWMNotify);
  1445. const
  1446.   RECURSE_FLAG: boolean = FALSE;
  1447. begin
  1448.   inherited;
  1449.  
  1450.   // Best way that I can find to snag the real header handle.  Kludgy at best,
  1451.   // but what else are you gonna do?
  1452.   // No, the if comparisons are NOT backwards, HDN_xxx values are negative.
  1453.   if (Message.NMHdr.code < HDN_FIRST) and (Message.NMHdr.code > HDN_LAST) then
  1454.     if Message.NMHdr.hwndFrom <> FHeaderHandle then
  1455.       FHeaderHandle := Message.NMHdr.hwndFrom;
  1456.  
  1457.   // Note the recursion flag.  This is needed since the SetColumnsOwnerDrawFlag
  1458.   // call below will cause some HDN_xxx notification messages.
  1459.   if RECURSE_FLAG then exit;
  1460.  
  1461.   // For some reason, the SECOND time you drag a header width, it toasts the
  1462.   // column index in the draw item message.  Also seems to reset owner draw
  1463.   // info at times, too.  Anyway, the best fix I could come up with was to
  1464.   // always watch for a change in the header handle, and always reset the owner
  1465.   // draw flag.
  1466.   case Message.NMHdr.code of
  1467.     HDN_BEGINTRACK, HDN_ITEMCHANGED:
  1468.       begin
  1469.         RECURSE_FLAG := TRUE;
  1470.         try
  1471.           SetColumnsOwnerDrawFlag(assigned(FOnDrawHeader) or FShowSortArrows);
  1472.         finally
  1473.           RECURSE_FLAG := FALSE;
  1474.         end;
  1475.       end;
  1476.   end;
  1477.  
  1478. (*  old way.  had some performance problems when used in conjunction with
  1479.     TToolbar97 component.  No idea why that would cause it, though.
  1480.   // For some reason, the SECOND time you drag a header width, it toasts the
  1481.   // column index in the draw item message.  Also seems to reset owner draw
  1482.   // info at times, too.  Anyway, the best fix I could come up with was to
  1483.   // always watch for a change in the header handle, and always reset the owner
  1484.   // draw flag.  Note the recursion flag.  This is needed since the
  1485.   // SetColumnsOwnerDrawFlag will cause some HDN_xxx notification messages.
  1486.  
  1487.   // Best way that I can find to snag the real header handle.  Kludgy at best,
  1488.   // but what else are you gonna do?
  1489.   case Message.NMHdr.code of
  1490.     HDN_LAST..HDN_FIRST:
  1491.       begin
  1492.         if Message.NMHdr.hwndFrom <> FHeaderHandle then
  1493.           FHeaderHandle := Message.NMHdr^.hwndFrom;
  1494.  
  1495.         if RECURSE_FLAG or (FUpdateCount > 0) then exit;
  1496.  
  1497.         RECURSE_FLAG := TRUE;
  1498.         try
  1499.           SetColumnsOwnerDrawFlag(assigned(FOnDrawHeader) or FShowSortArrows);
  1500.         finally
  1501.           RECURSE_FLAG := FALSE;
  1502.         end;
  1503.       end;
  1504.   end;
  1505. *)
  1506. end;
  1507.  
  1508. procedure TCustomEnhListView.WMDrawHeader(var Message: TWMDrawItem);
  1509. var
  1510.   State: TOwnerDrawState;
  1511.   DoDefaultDrawing: boolean;
  1512.   SavedDC: integer;
  1513. begin { CNDrawItem }
  1514.   if FCanvas = NIL then exit;
  1515.  
  1516.   with Message.DrawItemStruct^ do
  1517.   begin
  1518.     Message.Result := 1;
  1519.     State := TOwnerDrawState(WordRec(LongRec(itemState).Lo).Lo);
  1520.     SavedDC := SaveDC(hDC);
  1521.     FCanvas.Handle := hDC;
  1522.     try
  1523.       FCanvas.Font := Font;
  1524.       FCanvas.Brush := Brush;
  1525.       DoDefaultDrawing := FALSE;
  1526.       ProcessDrawHeaderMsg(itemID, rcItem, State, DoDefaultDrawing);
  1527.     finally
  1528.       FCanvas.Handle := 0;
  1529.       RestoreDC(hDC, SavedDC);
  1530.     end;
  1531.   end;
  1532. end;
  1533.  
  1534. procedure TCustomEnhListView.ProcessDrawHeaderMsg(Index: Integer; Rect: TRect;
  1535.    State: TOwnerDrawState; var DefaultDrawing: boolean);
  1536. begin
  1537.   FCanvas.Font.Assign(Font);
  1538.   FCanvas.Brush.Assign(Brush);
  1539.   FCanvas.Brush.Style := bsClear;
  1540.   FCanvas.Brush.Color := clBtnFace;
  1541.  
  1542.   DefaultDrawing := csDesigning in ComponentState;
  1543.   if not (csDesigning in ComponentState) then
  1544.     DrawHeader(FCanvas, Index, Rect, odSelected in State, DefaultDrawing);
  1545.  
  1546.   if DefaultDrawing then
  1547.     DefaultDrawHeader(FCanvas, Index, Rect, odSelected in State);
  1548. end;
  1549.  
  1550. procedure TCustomEnhListView.DefaultDrawHeader(var Canvas: TCanvas;
  1551.    Index: Integer; var Rect: TRect; Selected: boolean);
  1552. var
  1553.   TheColumn: TListColumn;
  1554.   Offset: integer;
  1555.   R, CR: TRect;
  1556.   Bmp: TBitmap;
  1557. begin
  1558.  
  1559. (******************************************************************************)
  1560. (* NOTE:  This method is overriden and replaced in TExtListView.  That means  *)
  1561. (*   that if changes are made here, they will also need to be made in         *)
  1562. (*   ExtListView.pas' DefaultDrawHeader method.                               *)
  1563. (******************************************************************************)
  1564.  
  1565.   if not Selected then
  1566.     InflateRect(Rect, -2, -2);
  1567.   Canvas.FillRect(Rect);
  1568.   if Selected then
  1569.     InflateRect(Rect, -2, -2);
  1570.  
  1571.   if (Index >= 0) and (Index < Columns.Count) then
  1572.   begin
  1573.     // Don't use ActualColumn[] here!  That's for SubItem foolery, not header.
  1574.     TheColumn := Columns[Index];
  1575.  
  1576.     if Selected then
  1577.     begin
  1578.       inc(Rect.Top);
  1579.       inc(Rect.Left);
  1580.     end;
  1581.  
  1582.     R := Rect;
  1583.  
  1584.     case TheColumn.Alignment of
  1585.       taRightJustify:
  1586.         Dec(R.Right, 4);
  1587.       taLeftJustify:
  1588.         Inc(R.Left, 4);
  1589.       // taCenter needs no modification
  1590.     end;
  1591.  
  1592.     if FShowSortArrows and (LastColumnClicked = Index) and
  1593.        (AutoColumnSort <> acsNoSort) then
  1594.     begin
  1595.       if CurrentSortAscending then
  1596.         Bmp := FSortUpBmp
  1597.       else
  1598.         Bmp := FSortDownBmp;
  1599.  
  1600.       if TheColumn.Alignment = taRightJustify then
  1601.         Inc(R.Left, Bmp.Width + 8)
  1602.       else
  1603.         Dec(R.Right, Bmp.Width + 8);
  1604.  
  1605.       { How big of a rectangle do we have to work with for the text? }
  1606.       CR := R;
  1607.       DrawTextEx(FCanvas.Handle, PChar(TheColumn.Caption), -1, CR,
  1608.          DRAWTEXTEX_FLAGS or DT_CALCRECT or
  1609.          DRAWTEXTEX_ALIGNMENT[TheColumn.Alignment], NIL);
  1610.       { Note that DT_CALCRECT does not adjust for alignment. We must do that }
  1611.       case TheColumn.Alignment of
  1612.         taRightJustify:
  1613.           R.Left := R.Right - (CR.Right - CR.Left);
  1614.         taCenter:
  1615.           begin
  1616.             R.Left := R.Left + (((R.Right - R.Left) - (CR.Right - CR.Left)) div
  1617.                2);
  1618.             R.Right := R.Left + (CR.Right - CR.Left);
  1619.           end;
  1620.       else // taLeftJustify: doesn't matter, that is what DT_CALCRECT returns
  1621.         R := CR;
  1622.       end;
  1623.       if R.Left < Rect.Left then
  1624.         R.Left := Rect.Left;
  1625.       if R.Right > Rect.Right then
  1626.         R.Right := Rect.Right;
  1627.  
  1628.       if Selected then
  1629.         OffsetRect(R, 1, 1);
  1630.       // Draw the caption in the rect available
  1631.       DrawTextEx(FCanvas.Handle, PChar(TheColumn.Caption), -1, R,
  1632.          DRAWTEXTEX_FLAGS or DRAWTEXTEX_ALIGNMENT[TheColumn.Alignment], NIL);
  1633.  
  1634.       // Draw the sort arrow bitmap
  1635.       Offset := (Rect.Bottom - Rect.Top - Bmp.Height) div 2;
  1636.       case TheColumn.Alignment of
  1637.         taRightJustify:
  1638.           // Only draw if we have enough room
  1639.           if (R.Left - Bmp.Width - 8) >= Rect.Left then
  1640.             Canvas.Draw(R.Left - Bmp.Width - 8, R.Top + Offset, Bmp);
  1641.       else // taLeftJustify, taCenter
  1642.         // Only draw if we have enough room
  1643.         if (R.Right + Bmp.Width + 8) <= Rect.Right then
  1644.           Canvas.Draw(R.Right + 8, R.Top + Offset, Bmp);
  1645.       end;
  1646.     end else begin
  1647.       if Selected then
  1648.         OffsetRect(R, 1, 1);
  1649.       DrawTextEx(FCanvas.Handle, PChar(TheColumn.Caption), -1, R,
  1650.          DRAWTEXTEX_FLAGS or DRAWTEXTEX_ALIGNMENT[TheColumn.Alignment], NIL);
  1651.     end;
  1652.   end;
  1653. end;
  1654.  
  1655. procedure TCustomEnhListView.SetOnDrawHeader(Value: TLVHDrawItemEvent);
  1656. begin
  1657.   FOnDrawHeader := Value;
  1658.   SetColumnsOwnerDrawFlag(assigned(FOnDrawHeader) or FShowSortArrows);
  1659. end;
  1660.  
  1661. procedure TCustomEnhListView.SetColumnsOwnerDrawFlag(OwnerDrawn: boolean);
  1662. var
  1663.   Item: THDItem;
  1664.   x: integer;
  1665. begin
  1666.   if not HandleAllocated then exit;
  1667.  
  1668.   for x := 0 to Columns.Count-1 do
  1669.   begin
  1670.     Item.Mask := HDI_FORMAT;
  1671.     if Header_GetItem(HeaderHandle, x, Item) then
  1672.     begin
  1673.       if OwnerDrawn then
  1674.         Item.Fmt := Item.Fmt or HDF_OWNERDRAW
  1675.       else
  1676.         Item.Fmt := Item.Fmt and not HDF_OWNERDRAW;
  1677.       Header_SetItem(HeaderHandle, x, Item);
  1678.     end;
  1679.   end;
  1680.  
  1681.   if OwnerDrawn then
  1682.   begin
  1683.     if (FCanvas = NIL) then
  1684.       FCanvas := TCanvas.Create;
  1685.   end else begin
  1686.     if (Style = lvStandard) and (FCanvas <> NIL) then
  1687.     begin
  1688.       FCanvas.Free;
  1689.       FCanvas := NIL;
  1690.     end;
  1691.   end;
  1692. end;
  1693.  
  1694. procedure TCustomEnhListView.SetLastColumnClicked(Value: integer);
  1695. var
  1696.   OldValue: integer;
  1697. begin
  1698.   if Value <> FLastColumnClicked then
  1699.   begin
  1700.     OldValue := FLastColumnClicked;
  1701.     FLastColumnClicked := Value;
  1702.     // If showing arrows and clicked column changes, we have to get rid of the
  1703.     // old sorting arrow by causing the header to be repainted.
  1704.     if FShowSortArrows then
  1705.       // Can't do this above because FLastColumnClicked is used to paint the
  1706.       // arrow
  1707.       InvalidateColumnHeader(OldValue);
  1708.   end;
  1709. end;
  1710.  
  1711. function TCustomEnhListView.ActualColumnIndex(Index: integer): integer;
  1712. begin
  1713.   Result := Index;
  1714. end;
  1715.  
  1716. procedure TCustomEnhListView.InvalidateColumnHeader(Index: integer);
  1717.   function RealColWidth(i: integer): integer;
  1718.   {$IFDEF DFS_COMPILER_4_UP}
  1719.   var
  1720.     Column: TLVColumn;
  1721.   {$ENDIF}
  1722.   begin
  1723.     {$IFDEF DFS_COMPILER_4_UP}
  1724.     Column.mask := LVCF_WIDTH;
  1725.     ListView_GetColumn(Handle, i, Column);
  1726.     Result := Column.cx;
  1727.     {$ELSE}
  1728.     Result := Columns[i].Width;
  1729.     {$ENDIF}
  1730.   end;
  1731. var
  1732.   R: TRect;
  1733.   x: integer;
  1734.   w: integer;
  1735. begin
  1736.   if (Index < 0) or (Index >= Columns.Count) or (HeaderHandle = 0) then
  1737.     exit;
  1738.  
  1739.   w := RealColWidth(Index);
  1740.   // We have to turn this into the actual column index if drag-drop headers have
  1741.   // re-arranged stuff in the TExtListView descendant component.
  1742.   Index := ActualColumnIndex(Index);
  1743.  
  1744.   Windows.GetClientRect(HeaderHandle, R);
  1745.   for x := 0 to Columns.Count - 1 do
  1746.     if ActualColumnIndex(x) < Index then
  1747.       inc(R.Left, RealColWidth(x));
  1748.   R.Right := R.Left + w;
  1749.  
  1750.   // Adjust for shadow
  1751.   InflateRect(R, -2, -2);
  1752.   InvalidateRect(HeaderHandle, @R, FALSE);
  1753. end;
  1754.  
  1755. procedure TCustomEnhListView.WMOwnerDrawColumns(var Message: TMessage);
  1756. begin
  1757.   SetColumnsOwnerDrawFlag(assigned(FOnDrawHeader) or FShowSortArrows);
  1758.   Update;
  1759. end;
  1760.  
  1761. function TCustomEnhListView.GetVersion: TDFSVersion;
  1762. begin
  1763.   Result := DFS_COMPONENT_VERSION;
  1764. end;
  1765.  
  1766. procedure TCustomEnhListView.SetVersion(const Val: TDFSVersion);
  1767. begin
  1768.   { empty write method, just needed to get it to show up in Object Inspector }
  1769. end;
  1770.  
  1771. procedure TCustomEnhListView.ResizeColumns(ResizeMethod: TResizeMethod);
  1772. var
  1773.   i: integer;
  1774. begin
  1775.   BeginUpdate;
  1776.   Columns.BeginUpdate;
  1777.   try
  1778.     for i := 0 to Columns.Count - 1 do
  1779.       if ResizeMethod = rmFitText then
  1780.         Columns[i].Width := -1
  1781.       else
  1782.         Columns[i].Width := -2;
  1783.   finally
  1784.     EndUpdate;
  1785.     Columns.EndUpdate;
  1786.   end;
  1787. end;
  1788.  
  1789.  
  1790. function TCustomEnhListView.GetCurrentColumnWidth(Index: integer): integer;
  1791. {$IFDEF DFS_COMPILER_4_UP}
  1792. var
  1793.   Column: TLVColumn;
  1794. {$ENDIF}
  1795. begin
  1796. {$IFDEF DFS_COMPILER_4_UP}
  1797.   if HandleAllocated then
  1798.   begin
  1799.     Column.mask := LVCF_WIDTH;
  1800.     ListView_GetColumn(Handle, ActualColumnIndex(Index), Column);
  1801.     Result := Column.cx;
  1802.   end else
  1803.     Result := ActualColumn[Index].Width;
  1804. {$ELSE}
  1805.   Result := ActualColumn[Index].Width;
  1806. {$ENDIF}
  1807. end;
  1808.  
  1809.  
  1810. initialization
  1811.   DefDraw_TextOffset := 4;
  1812.   DefDraw_ImageOffset := 2;
  1813. end.
  1814.  
  1815.