unit IEListView; {================================================================== Component TCustomIEListView / Version 1.0, September 1999 ================================================================== Description: ============ Basic component for TDirView. Author: ======= (c) Ingo Eckel 1999 Sodener Weg 38 65812 Bad Soden Germany (c) Martin Prikryl 2001 - 2003 For detailed documentation see the documentation of TDirView. ==================================================================} {Required compiler options for TCustomIEListView:} {$A+,B-,X+,H+,P+} interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, ActiveX, CommCtrl, Extctrls, ImgList, ComCtrls, NortonLikeListView, ListViewColProperties; type TIEListViewColProperties = class(TCustomListViewColProperties) protected function GetSortAscending: Boolean; procedure SetSortColumn(Value: Integer); function GetSortColumn: Integer; function GetSortStr: string; virtual; procedure SetSortAscending(Value: Boolean); procedure SetSortStr(Value: string); virtual; function GetParamsStr: string; override; procedure SetParamsStr(Value: string); override; public constructor Create(ListView: TCustomListView; ColCount: Integer); property SortAscending: Boolean read GetSortAscending write SetSortAscending default True; property SortColumn: Integer read GetSortColumn write SetSortColumn; property SortStr: string read GetSortStr write SetSortStr stored False; end; type TCustomIEListView = class; TListViewSecondaryColumnHeaderEvent = procedure(Sender: TCustomIEListView; Index: Integer; var SecondaryColumn: Integer) of object; TCustomIEListView = class(TCustomNortonLikeListView) private FSortColumn: Integer; FSortAscending: Boolean; FShowColumnIcon: Boolean; FParentForm: TCustomForm; FOnHeaderEndDrag: TNotifyEvent; FOnHeaderEndTrack: TNotifyEvent; FOnRecreate: TNotifyEvent; FOnSecondaryColumnHeader: TListViewSecondaryColumnHeaderEvent; FDragImageList: TDragImageList; protected procedure ColPropertiesChange(Sender: TObject); virtual; procedure SetShowColumnIcon(Value: Boolean); virtual; procedure SetSortColumn(Value: Integer); virtual; procedure SetSortAscending(Value: Boolean); virtual; procedure SortItems; virtual; procedure SetViewStyle(Value: TViewStyle); override; // CLEAN virtual procedure HeaderEndDrag(Sender: TObject); virtual; function SecondaryColumnHeader(Index: Integer): Integer; function NewColProperties: TCustomListViewColProperties; override; function SortAscendingByDefault(Index: Integer): Boolean; virtual; procedure CreateWnd; override; procedure ColClick(Column: TListColumn); override; procedure SetSort(Column: Integer; Ascending: Boolean); procedure WMNotify(var Msg: TWMNotify); message WM_NOTIFY; procedure CMRecreateWnd(var Message: TMessage); message CM_RECREATEWND; public constructor Create(AOwner: TComponent); override; destructor Destroy; override; procedure SetColumnImages; virtual; procedure SortBy(Column: Integer); property DragImageList: TDragImageList read FDragImageList; property ParentForm: TCustomForm read FParentForm; {Set the sort column of the listview} property SortColumn: Integer read FSortColumn write SetSortColumn; {Show the sorting symbol in the listview's header:} property ShowColumnIcon: Boolean read FShowColumnIcon write SetShowColumnIcon default True; {Sortorder of actual sort column} property SortAscending: Boolean read FSortAscending write SetSortAscending default True; property OnSecondaryColumnHeader: TListViewSecondaryColumnHeaderEvent read FOnSecondaryColumnHeader write FOnSecondaryColumnHeader; published property OnHeaderEndDrag: TNotifyEvent read FOnHeaderEndDrag write FOnHeaderEndDrag; property OnHeaderEndTrack: TNotifyEvent read FOnHeaderEndTrack write FOnHeaderEndTrack; property OnRecreate: TNotifyEvent read FOnRecreate write FOnRecreate; property Align; property AllocBy; property Anchors; property BiDiMode; property BorderStyle; property BorderWidth; property Checkboxes; property Color; property ColumnClick default True; property Constraints; property Ctl3D; property DoubleBuffered; property Enabled; property Font; property FlatScrollBars; property FullDrag; property GridLines; property HideSelection; property HotTrack; property HotTrackStyles; property IconOptions; property ReadOnly default False; property RowSelect; property ParentBiDiMode; property ParentColor default False; property ParentDoubleBuffered; property ParentFont; property ParentShowHint; property PopupMenu; property ShowColumnHeaders; property ShowHint; property TabOrder; property TabStop default True; property Visible; property OnChange; property OnChanging; property OnClick; property OnColumnClick; property OnColumnRightClick; property OnCustomDraw; property OwnerDraw; {Used for internal purposes:} property OnCustomDrawItem; property OnCustomDrawSubItem; property OnDblClick; property OnDeletion; property OnDrawItem; property OnEdited; property OnEditing; property OnEndDock; property OnEnter; property OnExit; property OnInsert; property OnKeyDown; property OnKeyPress; property OnKeyUp; property OnMouseDown; property OnMouseMove; property OnMouseUp; property OnResize; property OnStartDock; property NortonLike; end; {Type TCustomIEListView} type TIEListView = class(TCustomIEListView) published // copy from TListView, except for marked items property Action; property Align; property AllocBy; property Anchors; property BevelEdges; property BevelInner; property BevelOuter; property BevelKind default bkNone; property BevelWidth; property BiDiMode; property BorderStyle; property BorderWidth; property Checkboxes; property Color; property Columns; property ColumnClick; property Constraints; property Ctl3D; property DragCursor; property DragKind; property DragMode; property Enabled; property Font; property FlatScrollBars; property FullDrag; property GridLines; property HideSelection; property HotTrack; property HotTrackStyles; property HoverTime; property IconOptions; property Items; property LargeImages; property MultiSelect; property OwnerData; property OwnerDraw; property ReadOnly default False; property RowSelect; property ParentBiDiMode; property ParentColor default False; property ParentFont; property ParentShowHint; property PopupMenu; property ShowColumnHeaders; property ShowWorkAreas; property ShowHint; property SmallImages; property SortType; property StateImages; property TabOrder; property TabStop default True; property ViewStyle; property Visible; property OnAdvancedCustomDraw; property OnAdvancedCustomDrawItem; property OnAdvancedCustomDrawSubItem; property OnChange; property OnChanging; property OnClick; property OnColumnClick; property OnColumnDragged; property OnColumnRightClick; property OnCompare; property OnContextPopup; property OnCustomDraw; property OnCustomDrawItem; property OnCustomDrawSubItem; property OnData; property OnDataFind; property OnDataHint; property OnDataStateChange; property OnDblClick; property OnDeletion; property OnDrawItem; property OnEdited; property OnEditing; property OnEndDock; property OnEndDrag; property OnEnter; property OnExit; property OnGetImageIndex; property OnGetSubItemImage; property OnDragDrop; property OnDragOver; property OnInfoTip; property OnInsert; property OnKeyDown; property OnKeyPress; property OnKeyUp; property OnMouseDown; property OnMouseMove; property OnMouseUp; property OnResize; property OnSelectItem; property OnStartDock; property OnStartDrag; property OnSecondaryColumnHeader; // TCustomIEListView end; var GlobalDragImageList: TDragImageList; procedure Register; implementation uses PasTools, Types; procedure Register; begin RegisterComponents('Martin', [TIEListView]); end; { TIEListViewColProperties } constructor TIEListViewColProperties.Create(ListView: TCustomListView; ColCount: Integer); begin inherited; end; procedure TIEListViewColProperties.SetParamsStr(Value: string); begin SortStr := CutToChar(Value, '|', True); inherited SetParamsStr(Value); end; procedure TIEListViewColProperties.SetSortAscending(Value: Boolean); begin TCustomIEListView(FListView).SortAscending := Value; end; procedure TIEListViewColProperties.SetSortColumn(Value: Integer); begin if SortColumn <> Value then begin TCustomIEListView(FListView).SortColumn := Value; Changed; end; end; function TIEListViewColProperties.GetParamsStr: string; begin Result := Format('%s|%s', [SortStr, inherited GetParamsStr]); end; function TIEListViewColProperties.GetSortAscending: Boolean; begin Result := TCustomIEListView(FListView).SortAscending; end; function TIEListViewColProperties.GetSortColumn: Integer; begin Result := TCustomIEListView(FListView).SortColumn; end; procedure TIEListViewColProperties.SetSortStr(Value: string); var ASortColumn: Integer; begin ASortColumn := StrToIntDef(CutToChar(Value, ';', True), SortColumn); if ASortColumn < Count then SortColumn := ASortColumn; SortAscending := Boolean(StrToIntDef(CutToChar(Value, ';', True), Integer(SortAscending))); end; function TIEListViewColProperties.GetSortStr: string; begin Result := Format('%d;%d', [SortColumn, Integer(SortAscending)]); end; { TCustomIEListView } constructor TCustomIEListView.Create(AOwner: TComponent); begin inherited; ColProperties.OnChange := ColPropertiesChange; FShowColumnIcon := True; FSortColumn := 0; FSortAscending := True; end; {Create} procedure TCustomIEListView.SetSort(Column: Integer; Ascending: Boolean); begin if (SortColumn <> Column) or (SortAscending <> Ascending) then begin FSortColumn := Column; FSortAscending := Ascending; if Items.Count > 0 then SortItems; SetColumnImages; end; end; procedure TCustomIEListView.SortBy(Column: Integer); begin if Column = SortColumn then SetSort(SortColumn, not SortAscending) else SetSort(Column, SortAscendingByDefault(Column)); end; procedure TCustomIEListView.SetSortColumn(Value: Integer); begin SetSort(Value, True); end; {SetSortColumn} procedure TCustomIEListView.SetViewStyle(Value: TViewStyle); begin if Value <> ViewStyle then begin inherited SetViewStyle(Value); if ViewStyle = vsReport then SetColumnImages; end; end; {SetViewStyle} procedure TCustomIEListView.SetSortAscending(Value: Boolean); begin SetSort(SortColumn, Value); end; {SetSortAscending} procedure TCustomIEListView.SetColumnImages; var HdItem: THdItem; Index: Integer; SecondaryColumn: Integer; ShowImage: Boolean; NewFmt: Integer; begin if ShowColumnHeaders and HandleAllocated then begin for Index := 0 to Columns.Count-1 do begin HdItem.Mask := HDI_FORMAT; Header_GetItem(FHeaderHandle, Index, HdItem); SecondaryColumn := SecondaryColumnHeader(Index); ShowImage := False; if FShowColumnIcon then begin if (Index = SortColumn) or ((SecondaryColumn >= 0) and (SecondaryColumn = SortColumn)) then begin ShowImage := True; end; end; // for hidden columns, do not show the icon // as on some systems it is still drawn, but on neighboring columns if ShowImage and (Columns[Index].Width > 0) then begin if SortAscending then begin NewFmt := (Hditem.fmt or HDF_SORTUP) and (not HDF_SORTDOWN); end else begin NewFmt := (Hditem.fmt or HDF_SORTDOWN) and (not HDF_SORTUP); end; end else begin NewFmt := HdItem.fmt and (not (HDF_SORTUP or HDF_SORTDOWN)); end; if NewFmt <> HdItem.fmt then begin HdItem.Mask := HDI_FORMAT; HdItem.fmt := NewFmt; Header_SetItem(FHeaderHandle, Index, HDItem); end; end; end; end; {SetColumnImage} procedure TCustomIEListView.SetShowColumnIcon(Value: Boolean); begin if Value <> ShowColumnIcon then begin FShowColumnIcon := Value; SetColumnImages; end; end; {SetShowColumnIcon} function TCustomIEListView.SecondaryColumnHeader(Index: Integer): Integer; begin if Assigned(OnSecondaryColumnHeader) then begin OnSecondaryColumnHeader(Self, Index, Result); end else begin Result := -1; end; end; function TCustomIEListView.NewColProperties: TCustomListViewColProperties; begin Result := TIEListViewColProperties.Create(Self, 0); end; function TCustomIEListView.SortAscendingByDefault(Index: Integer): Boolean; begin Result := True; end; procedure TCustomIEListView.ColClick(Column: TListColumn); begin SortBy(Column.Index); inherited; end; {ColClick} procedure TCustomIEListView.WMNotify(var Msg: TWMNotify); begin if (FHeaderHandle <> 0) and (Msg.NMHdr^.hWndFrom = FHeaderHandle) then case Msg.NMHdr.code of HDN_BEGINDRAG: begin // We probably do not need to eat this message anymore, // we let's keep it in sync with HDN_ENDDRAG (see comment there) end; HDN_ENDDRAG: begin // Originally the code to eat this message was here to // workaround bug in D4 (until Update Pack 3). // But when we pass the message to VCL, it reorders // columns in Columns collection, what our code does not handle. // See also comment in TCustomListViewColProperties.UpdateListViewOrder HeaderEndDrag(Self); Invalidate; Exit; end; HDN_ENDTRACKA, HDN_ENDTRACKW: begin SetColumnImages; Invalidate; inherited; if Assigned(FOnHeaderEndTrack) then FOnHeaderEndTrack(Self); Exit; end; HDN_DIVIDERDBLCLICKA, HDN_DIVIDERDBLCLICKW: begin inherited; if Assigned(FOnHeaderEndTrack) then FOnHeaderEndTrack(Self); SetColumnImages; end; end; inherited; end; { TCustomIEListView.WMNotify } // Might not be always called, see comment in TDriveView.DestroyWnd procedure TCustomIEListView.CMRecreateWnd(var Message: TMessage); begin inherited; if Assigned(OnRecreate) then OnRecreate(Self); end; procedure TCustomIEListView.HeaderEndDrag(Sender : TObject); begin if Assigned(FOnHeaderEndDrag) then FOnHeaderEndDrag(Self); end; {HeaderEndDrag} procedure TCustomIEListView.ColPropertiesChange(Sender: TObject); begin SetColumnImages; end; procedure TCustomIEListView.CreateWnd; begin inherited; FParentForm := GetParentForm(Self); if not (csDesigning in ComponentState) then FDragImageList := TDragImageList.Create(Self); if not Assigned(GlobalDragImageList) then GlobalDragImageList := DragImageList; SetColumnImages; end; {CreateWnd} destructor TCustomIEListView.Destroy; begin if Assigned(FDragImageList) then begin if GlobalDragImageList = FDragImageList then GlobalDragImageList := nil; FDragImageList.Free; end; inherited; end; {Destroy} procedure TCustomIEListView.SortItems; begin AlphaSort; ItemsReordered; end; end.