fctreeview.pas
上传用户:hylc_2004
上传日期:2014-01-23
资源大小:46800k
文件大小:166k
源码类别:

Delphi控件源码

开发平台:

Delphi

  1. unit fcTreeView;
  2. {
  3. //
  4. // Components : TfcTreeView
  5. //
  6. // Copyright (c) 1999 by Woll2Woll Software
  7. // 3/3/99 - (RSW) Remove tvoUnderscoreAllowed Option
  8. // 5/21/99 - Complete editing
  9. // 6/14/99 - Fix disappearing tree when going into edit mode
  10. // 6/23/99 - Fire OnDblClick event even when ExpandOnDblClick is False
  11. // 7/3/99 - Only call Invalidate if not in expanding/collapsing
  12. // 7/6/99 - Support streaming of TfcTreeView Items to TfcTreecombo's tree
  13. // 11/12/99 - If right mouse button, then exit so multi-selected records are
  14. //          not unselected
  15. // 1/5/2000 - Fix TFrame duplicate streaming problem
  16. // 2/3/2000 - Optimize imagelist usage so that resources are better
  17. //            managed with regards to bitmaps
  18. //
  19. // 2/28/2000 - Always increment refcount so that treeview does not incorrectly
  20. //             free temp image list.
  21. // 5/16/2000 - PYW - Fix Memory leak from code left over from Delphi 3
  22. // 6/9/2000 - PYW - Prevent default button handling for treeview
  23. // 12/13/2001 - Don't use temp canvas for XP Themes. TreeView not painted in some cases otherwise
  24. // 1/31/2002 - In WMPaint call inherited if nodes are in beginupdate/endupdate.
  25. // 1/31/2002 - PYW - Added new property to respect expanded node settings.
  26. // 5/10/2002 - Use DrawText to calculate font based on current canvas settings from OnCalcNodeAttributes event.
  27. }
  28. interface
  29. {$i fcIfdef.pas}
  30. {$R-}
  31. uses
  32.   Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  33.   CommCtrl, ComStrs, consts, comctrls, fccustomdraw, fccanvas, extctrls, fccommon,
  34. {$ifdef fcdelphi6Up}
  35. variants,
  36. {$endif}
  37. {$ifdef fcdelphi7Up}
  38.   themes,
  39. {$endif}
  40.   {$ifdef ThemeManager}
  41.   thememgr, themesrv, uxtheme,
  42.   {$endif}
  43.   shellapi
  44.   {$ifdef fcDelphi4Up}, ImgList{$endif};
  45. type
  46.   TfcCustomTreeView = class;
  47.   TfcTreeNode = class;
  48.   TfcItemState = (fcisSelected, fcisGrayed, fcisDisabled, fcisChecked,
  49.     fcisFocused, fcisDefault, fcisHot, fcisMarked, fcisIndeterminate);
  50.   TfcItemStates = set of TfcItemState;
  51.   TfcTVDrawTextEvent = procedure (TreeView: TfcCustomTreeview;
  52.     Node: TfcTreeNode; ARect: TRect; AItemState: TfcItemStates;
  53.     var DefaultDrawing: boolean) of object;
  54.   TfcTreeMouseMoveEvent = procedure(TreeView: TfcCustomTreeView;
  55.       Node: TfcTreeNode;
  56.       Shift: TShiftState; X, Y: Integer)of object;
  57.   TfcTreeMouseEvent = procedure(TreeView: TfcCustomTreeView;
  58.       Node: TfcTreeNode;
  59.       Button: TMouseButton; Shift: TShiftState; X, Y: Integer) of object;
  60.   TfcTreeNodes = class;
  61.   TfcNodeState = (fcnsCut, fcnsDropHilited, fcnsFocused, fcnsSelected,
  62.                   fcnsExpanded);
  63.   TfcNodeAttachMode = (fcnaAdd, fcnaAddFirst, fcnaAddChild, fcnaAddChildFirst,
  64.                        fcnaInsert, fcnaInsertAfter);
  65.   TfcAddMode = (fctaAddFirst, fctaAdd, fctaInsert);
  66.   TfcTreeViewCheckboxType = (tvctNone, tvctCheckbox, tvctRadioGroup);
  67.   TfcTreeViewOption = (tvoExpandOnDblClk, tvoExpandButtons3D,
  68.      tvoFlatCheckBoxes, tvoHideSelection,
  69.      tvoRowSelect, tvoShowButtons,
  70.      tvoShowLines, tvoShowRoot,
  71.      {tvoUnderscoreAllowed,} tvoHotTrack, tvoAutoURL, tvoToolTips,
  72.      tvoEditText, tvo3StateCheckbox);
  73.   TfcTreeViewOptions = set of TfcTreeViewOption;
  74.   PfcNodeInfo = ^TfcNodeInfo;
  75.   TfcNodeInfo = packed record
  76.     ImageIndex: Integer;
  77.     SelectedIndex: Integer;
  78.     StateIndex: Integer;
  79.     OverlayIndex: Integer;
  80.     CheckboxType: TfcTreeViewCheckboxType;
  81.     Checked: byte;
  82.     Expanded: boolean;
  83.     DummyPad: packed array[1..3] of char;  { Allow Future growth }
  84.     Data: Pointer;
  85.     StringDataSize1: integer;
  86.     StringDataSize2: integer;
  87.     Count: Integer;
  88.     Text: string[255];
  89.     { Future growth so that old executables can still run with newer tree view formats }
  90. //    Dummy1: integer;
  91. //    Dummy2: integer;
  92. //    Dummy3: integer;
  93. //    Dummy4: integer;
  94.   end;
  95.   TfcTreeNode = class(TPersistent)
  96.   private
  97.     FMultiSelected: boolean;
  98.     FCheckboxType: TfcTreeViewCheckboxType;
  99.     FChecked: boolean;
  100.     FOwner: TfcTreeNodes;
  101.     FText: string;
  102.     FStringData1, FStringData2: String;
  103.     FData: Pointer;
  104.     FItemId: HTreeItem;
  105.     FImageIndex: Integer;
  106.     FSelectedIndex: Integer;
  107.     FOverlayIndex: Integer;
  108.     FStateIndex: Integer;
  109.     FDeleting: Boolean;
  110.     FInTree: Boolean;
  111.     FGrayed: boolean;
  112.     procedure SetCheckboxType(val: TfcTreeViewCheckboxType);
  113.     function CompareCount(CompareMe: Integer): Boolean;
  114.     function DoCanExpand(Expand: Boolean): Boolean;
  115.     procedure DoExpand(Expand: Boolean);
  116.     procedure ExpandItem(Expand: Boolean; Recurse: Boolean);
  117.     function GetAbsoluteIndex: Integer;
  118.     function GetExpanded: Boolean;
  119.     function GetLevel: Integer;
  120.     function GetParent: TfcTreeNode;
  121.     function GetChildren: Boolean;
  122.     function GetCut: Boolean;
  123.     function GetDropTarget: Boolean;
  124.     function GetFocused: Boolean;
  125.     function GetIndex: Integer;
  126.     function GetItem(Index: Integer): TfcTreeNode;
  127.     function GetSelected: Boolean;
  128.     function GetState(NodeState: TfcNodeState): Boolean;
  129.     function GetCount: Integer;
  130.     function GetTreeView: TfcCustomTreeView;
  131.     procedure InternalMove(ParentNode, Node: TfcTreeNode; HItem: HTreeItem;
  132.       AddMode: TfcAddMode);
  133. //    function IsEqual(Node: TfcTreeNode): Boolean;
  134.     function IsNodeVisible: Boolean;
  135.     procedure SetChildren(Value: Boolean);
  136.     procedure SetCut(Value: Boolean);
  137.     procedure SetData(Value: Pointer);
  138.     procedure SetDropTarget(Value: Boolean);
  139.     procedure SetItem(Index: Integer; Value: TfcTreeNode);
  140.     procedure SetExpanded(Value: Boolean);
  141.     procedure SetFocused(Value: Boolean);
  142.     procedure SetImageIndex(Value: Integer);
  143.     procedure SetOverlayIndex(Value: Integer);
  144.     procedure SetSelectedIndex(Value: Integer);
  145.     procedure SetSelected(Value: Boolean);
  146.     procedure SetStateIndex(Value: Integer);
  147.     procedure SetText(const S: string);
  148.     function GetMultiSelected: Boolean;
  149.     procedure SetMultiSelected(Value: Boolean);
  150.     procedure SetChecked(val: boolean);
  151.     procedure SetGrayed(val: boolean);
  152.   protected
  153. //    function ShowBlankImage: boolean; virtual;
  154.     {$ifdef fcDelphi4Up}
  155.     ReadDataSize: integer;
  156.     {$endif}
  157.     procedure Invalidate; virtual;
  158.     Function GetSizeOfNodeInfo: integer; virtual;
  159.     procedure ReadData(Stream: TStream; Info: PfcNodeInfo); virtual;
  160.     procedure WriteData(Stream: TStream; Info: PfcNodeInfo); virtual;
  161.   public
  162.     Patch: Variant;
  163.     function GetStateIndex: integer;
  164.     Function IsRadioGroup: boolean;
  165.     function GetSortText: string; virtual;
  166.     constructor Create(AOwner: TfcTreeNodes); virtual;
  167.     destructor Destroy; override;
  168.     function AlphaSort: Boolean;
  169.     procedure Assign(Source: TPersistent); override;
  170.     procedure Collapse(Recurse: Boolean);
  171.     function CustomSort(SortProc: TTVCompare; Data: Longint): Boolean;
  172.     procedure Delete;
  173.     procedure DeleteChildren;
  174.     function DisplayRect(TextOnly: Boolean): TRect;
  175.     function EditText: Boolean;
  176.     procedure EndEdit(Cancel: Boolean);
  177.     procedure Expand(Recurse: Boolean);
  178.     function GetFirstChild: TfcTreeNode;
  179.     function GetHandle: HWND;
  180.     function GetLastChild: TfcTreeNode;
  181.     function GetNext: TfcTreeNode;
  182.     function GetNextChild(Value: TfcTreeNode): TfcTreeNode;
  183.     function GetNextSibling: TfcTreeNode;
  184.     function GetNextVisible: TfcTreeNode;
  185.     function GetPrev: TfcTreeNode;
  186.     function GetPrevChild(Value: TfcTreeNode): TfcTreeNode;
  187.     function GetPrevSibling: TfcTreeNode;
  188.     function GetPrevVisible: TfcTreeNode;
  189.     function HasAsParent(Value: TfcTreeNode): Boolean;
  190.     function IndexOf(Value: TfcTreeNode): Integer;
  191.     procedure MakeVisible;
  192.     procedure MoveTo(Destination: TfcTreeNode; Mode: TfcNodeAttachMode); virtual;
  193.     property AbsoluteIndex: Integer read GetAbsoluteIndex;
  194.     property Count: Integer read GetCount;
  195.     property Cut: Boolean read GetCut write SetCut;
  196.     property Data: Pointer read FData write SetData;
  197.     property Deleting: Boolean read FDeleting;
  198.     property Focused: Boolean read GetFocused write SetFocused;
  199.     property DropTarget: Boolean read GetDropTarget write SetDropTarget;
  200.     property Selected: Boolean read GetSelected write SetSelected;
  201.     property Expanded: Boolean read GetExpanded write SetExpanded;
  202.     property Handle: HWND read GetHandle;
  203.     property HasChildren: Boolean read GetChildren write SetChildren;
  204.     property ImageIndex: Integer read FImageIndex write SetImageIndex;
  205.     property Index: Integer read GetIndex;
  206.     property IsVisible: Boolean read IsNodeVisible;
  207.     property Item[Index: Integer]: TfcTreeNode read GetItem write SetItem; default;
  208.     property ItemId: HTreeItem read FItemId;
  209.     property Level: Integer read GetLevel;
  210.     property OverlayIndex: Integer read FOverlayIndex write SetOverlayIndex;
  211.     property Owner: TfcTreeNodes read FOwner;
  212.     property Parent: TfcTreeNode read GetParent;
  213.     property SelectedIndex: Integer read FSelectedIndex write SetSelectedIndex;
  214.     property StateIndex: Integer read FStateIndex write SetStateIndex;
  215.     property Text: string read FText write SetText;
  216.     property StringData: string read FStringData1 write FStringData1;
  217.     property StringData2: string read FStringData2 write FStringData2;
  218.     property TreeView: TfcCustomTreeView read GetTreeView;
  219.     property Checked: boolean read FChecked write SetChecked;
  220.     property Grayed: boolean read FGRayed write SetGrayed;
  221.     property CheckboxType: TfcTreeViewCheckboxType read FCheckboxType write SetCheckboxType;
  222.     property MultiSelected: Boolean read GetMultiSelected write SetMultiSelected;
  223.   end;
  224. { TfcTreeNodes }
  225.   PfcNodeCache = ^TfcNodeCache;
  226.   TfcNodeCache = record
  227.     CacheNode: TfcTreeNode;
  228.     CacheIndex: Integer;
  229.   end;
  230.   TwwStoreData = (sdStoreText, sdStoreData1, sdStoreData2);
  231.   TfcTreeNodes = class(TPersistent)
  232.   private
  233.     FOwner: TfcCustomTreeView;
  234.     FUpdateCount: Integer;
  235.     FNodeCache: TfcNodeCache;
  236.     InDestroy: boolean;
  237.     procedure AddedNode(Value: TfcTreeNode);
  238.     function GetHandle: HWND;
  239.     function GetNodeFromIndex(Index: Integer): TfcTreeNode;
  240.     procedure ReadData(Stream: TStream);
  241.     procedure Repaint(Node: TfcTreeNode);
  242.     procedure WriteData(Stream: TStream);
  243.     procedure ClearCache;
  244.     procedure ReadStreamVersion(Reader: TReader);
  245.     procedure WriteStreamVersion(Writer: TWriter);
  246.   protected
  247.     function AddItem(Parent, Target: HTreeItem; const Item: TTVItem;
  248.       AddMode: TfcAddMode): HTreeItem;
  249.     function InternalAddObject(Node: TfcTreeNode; const S: string;
  250.       Ptr: Pointer; AddMode: TfcAddMode): TfcTreeNode;
  251.     procedure DefineProperties(Filer: TFiler); override;
  252.     function CreateItem(Node: TfcTreeNode): TTVItem;
  253.     function GetCount: Integer;
  254.     procedure SetItem(Index: Integer; Value: TfcTreeNode);
  255.     procedure SetUpdateState(Updating: Boolean);
  256.   public
  257.     constructor Create(AOwner: TfcCustomTreeView);
  258.     destructor Destroy; override;
  259.     function AddChildFirst(Node: TfcTreeNode; const S: string): TfcTreeNode;
  260.     function AddChild(Node: TfcTreeNode; const S: string): TfcTreeNode;
  261.     function AddChildObjectFirst(Node: TfcTreeNode; const S: string;
  262.       Ptr: Pointer): TfcTreeNode;
  263.     function AddChildObject(Node: TfcTreeNode; const S: string;
  264.       Ptr: Pointer): TfcTreeNode;
  265.     function AddFirst(Node: TfcTreeNode; const S: string): TfcTreeNode;
  266.     function Add(Node: TfcTreeNode; const S: string): TfcTreeNode;
  267.     function AddObjectFirst(Node: TfcTreeNode; const S: string;
  268.       Ptr: Pointer): TfcTreeNode;
  269.     function AddObject(Node: TfcTreeNode; const S: string;
  270.       Ptr: Pointer): TfcTreeNode;
  271.     procedure Assign(Source: TPersistent); override;
  272.     procedure BeginUpdate;
  273.     procedure Clear;
  274.     procedure Delete(Node: TfcTreeNode);
  275.     procedure EndUpdate;
  276.     function GetFirstNode: TfcTreeNode;
  277.     function GetNode(ItemId: HTreeItem): TfcTreeNode;
  278.     function Insert(Node: TfcTreeNode; const S: string): TfcTreeNode;
  279.     function InsertObject(Node: TfcTreeNode; const S: string;
  280.       Ptr: Pointer): TfcTreeNode;
  281.     function FindNode(SearchText: string; VisibleOnly: Boolean): TfcTreeNode;
  282.     function FindNodeInfo(SearchText: string; VisibleOnly: Boolean;
  283.        StoreDataUsing: TwwStoreData = sdStoreText): TfcTreeNode;
  284.     property Count: Integer read GetCount;
  285.     property Handle: HWND read GetHandle;
  286.     property Item[Index: Integer]: TfcTreeNode read GetNodeFromIndex; default;
  287.     property Owner: TfcCustomTreeView read FOwner;
  288.   end;
  289. { TfcCustomTreeView }
  290.   TfcTVMultiSelectAttributes = class(TPersistent)
  291.   private
  292.      FEnabled: Boolean;
  293.      FAutoUnselect: boolean;
  294. //     FAlwaysIncludeSelectedItem: Boolean;
  295.      FMultiSelectLevel: integer;
  296.      FMultiSelectCheckbox: boolean;
  297.      TreeView: TfcCustomTreeView;
  298.      procedure SetEnabled(val: boolean);
  299.      procedure SetMultiSelectLevel(val: integer);
  300.      procedure SetMultiSelectCheckBox(val: boolean);
  301.   public
  302.      constructor Create(Owner: TComponent);
  303.      procedure Assign(Source: TPersistent); override;
  304.   published
  305.      property AutoUnselect : boolean read FAutoUnselect write FAutoUnselect default True;
  306. //     property AlwaysIncludeSelectedItem: Boolean read FAlwaysIncludeSelectedItem write FAlwaysIncludeSelectedItem default False;
  307.      property Enabled: boolean read FEnabled write SetEnabled default False;
  308.      property MultiSelectLevel: integer read FMultiSelectLevel write SetMultiSelectLevel default 0;
  309.      property MultiSelectCheckbox: boolean read FMultiSelectCheckbox write SetMultiSelectCheckbox default True;
  310.   end;
  311.   TfcHitTest = (fchtAbove, fchtBelow, fchtNowhere, fchtOnItem, fchtOnButton, fchtOnIcon,
  312.     fchtOnIndent, fchtOnLabel, fchtOnRight, fchtOnStateIcon, fchtToLeft, fchtToRight);
  313.   TfcHitTests = set of TfcHitTest;
  314.   TfcSortType = (fcstNone, fcstData, fcstText, fcstBoth);
  315.   EfcTreeViewError = class(Exception);
  316.   TfcTVChangingEvent = procedure(TreeView: TfcCustomTreeView; Node: TfcTreeNode;
  317.     var AllowChange: Boolean) of object;
  318.   TfcTVChangedEvent = procedure(TreeView: TfcCustomTreeView; Node: TfcTreeNode) of object;
  319.   TfcTVEditingEvent = procedure(TreeView: TfcCustomTreeView; Node: TfcTreeNode;
  320.     var AllowEdit: Boolean) of object;
  321.   TfcTVEditedEvent = procedure(TreeView: TfcCustomTreeView; Node: TfcTreeNode; var S: string) of object;
  322.   TfcTVExpandingEvent = procedure(TreeView: TfcCustomTreeView; Node: TfcTreeNode;
  323.     var AllowExpansion: Boolean) of object;
  324.   TfcTVCollapsingEvent = procedure(TreeView: TfcCustomTreeView; Node: TfcTreeNode;
  325.     var AllowCollapse: Boolean) of object;
  326.   TfcTVExpandedEvent = procedure(TreeView: TfcCustomTreeView; Node: TfcTreeNode) of object;
  327.   TfcTVCompareEvent = procedure(TreeView: TfcCustomTreeView; Node1, Node2: TfcTreeNode;
  328.     Data: Integer; var Compare: Integer) of object;
  329.   TfcTVCustomDrawEvent = procedure(TreeView: TfcCustomTreeView; const ARect: TRect;
  330.     var DefaultDraw: Boolean) of object;
  331.   TfcCalcNodeAttributesEvent = procedure(TreeView: TfcCustomTreeView;
  332.           Node: TfcTreeNode; State: TfcItemStates) of object;
  333.   TfcItemChangeAction = (icaAdd, icaDelete, icaText, icaImageIndex);
  334.   TfcItemChangeEvent = procedure(TreeView: TfcCustomTreeView; Node: TfcTreeNode;
  335.     Action: TfcItemChangeAction; NewValue: Variant) of object;
  336.   TfcToggleCheckboxEvent = procedure(TreeView: TfcCustomTreeView; Node: TfcTreeNode) of object;
  337.   TfcTreeNodeClass = class of TfcTreeNode;
  338.   TfcCustomTreeView = class(TWinControl)
  339.   private
  340.     FOnItemChange: TfcItemChangeEvent;
  341. //    FOnItemChanging: TfcItemChangeEvent;
  342.     FAutoExpand: Boolean;
  343.     FBorderStyle: TBorderStyle;
  344.     FCanvas: TfcCanvas;
  345.     FPaintCanvas: TfcCanvas;
  346.     FCanvasChanged: Boolean;
  347.     FDefEditProc: Pointer;
  348.     FDragged: Boolean;
  349.     FDragImage: {$ifdef fcDelphi4Up}TDragImageList{$else}TCustomImageList{$endif};
  350.     FDragNode: TfcTreeNode;
  351.     FEditHandle: HWND;
  352.     FEditInstance: Pointer;
  353.     FImageChangeLink: TChangeLink;
  354.     FImages: TCustomImageList;
  355.     FLastDropTarget: TfcTreeNode;
  356.     FManualNotify: Boolean;
  357.     FMemStream: TMemoryStream;
  358.     FRClickNode: TfcTreeNode;
  359.     FRightClickSelects: Boolean;
  360.     FReadOnly: Boolean;
  361.     FSaveIndex: Integer;
  362.     FSaveIndent: Integer;
  363.     FSaveItems: TStringList;
  364.     FSaveTopIndex: Integer;
  365.     FSortType: TfcSortType;
  366.     FStateChanging: Boolean;
  367.     FStateImages: TCustomImageList;
  368.     FStateChangeLink: TChangeLink;
  369.     FStreamExpandedNode: Boolean;
  370. //    FToolTips: Boolean;
  371.     FTreeNodes: TfcTreeNodes;
  372.     FWideText: WideString;
  373.     FOnEditing: TfcTVEditingEvent;
  374.     FOnEdited: TfcTVEditedEvent;
  375.     FOnExpanded: TfcTVExpandedEvent;
  376.     FOnExpanding: TfcTVExpandingEvent;
  377.     FOnCollapsed: TfcTVExpandedEvent;
  378.     FOnCollapsing: TfcTVCollapsingEvent;
  379.     FOnChanging: TfcTVChangingEvent;
  380.     FOnChange: TfcTVChangedEvent;
  381.     FOnCompare: TfcTVCompareEvent;
  382.     FOnDeletion: TfcTVExpandedEvent;
  383.     FOnGetImageIndex: TfcTVExpandedEvent;
  384.     FOnGetSelectedIndex: TfcTVExpandedEvent;
  385.     FLineColor: TColor;
  386.     FInactiveFocusColor: TColor;
  387.     FOnMouseDown, FOnMouseUp, FOnDblClick: TfcTreeMouseEvent;
  388.     FOnMouseMove: TfcTreeMouseMoveEvent;
  389.     FOnToggleCheckbox: TfcToggleCheckboxEvent;
  390.     FNodeClass: TfcTreeNodeClass;
  391.     FMultiSelectAttributes: TfcTVMultiSelectAttributes;
  392.     FOnCalcNodeAttributes: TfcCalcNodeAttributesEvent;
  393.     FBorderWidth: Integer;
  394.     FOnDrawText: TfcTVDrawTextEvent;
  395. //    FFixBugImageList: TImageList;
  396.     FOptions: TfcTreeViewOptions;
  397.     FDisableThemes: boolean;
  398.     FPaintBitmap: TBitmap;
  399.     FIndent: Integer;
  400.     LastSelectedNode: TfcTreeNode;
  401.     MouseNode: TfcTreeNode;
  402.     LastMouseMoveNode: TfcTreeNode;  // For themes with checkboxes and radiobuttons invalidation
  403.     LastMouseHitTest: TfcHitTests;
  404.     ClickedNode: TfcTreeNode;
  405.     Down: boolean;
  406.     EditNode, BeforeMouseDownNode: TfcTreeNode;
  407.     FStreamVersion: integer;
  408.     FUsePaintBuffering: boolean;
  409. //    FEditControl: TWinControl;
  410.     procedure CanvasChanged(Sender: TObject);
  411.     procedure CMColorChanged(var Message: TMessage); message CM_COLORCHANGED;
  412.     procedure CMCtl3DChanged(var Message: TMessage); message CM_CTL3DCHANGED;
  413.     procedure CMFontChanged(var Message: TMessage); message CM_FONTCHANGED;
  414.     procedure CMDrag(var Message: TCMDrag); message CM_DRAG;
  415.     procedure CNNotify(var Message: TWMNotify); message CN_NOTIFY;
  416.     procedure WMNCHitTest(var Message: TWMNCHitTest); message WM_NCHITTEST;
  417.     procedure EditWndProc(var Message: TMessage);
  418.     procedure DoDragOver(Source: TDragObject; X, Y: Integer; CanDrop: Boolean);
  419.     function GetChangeDelay: Integer;
  420.     function GetDropTarget: TfcTreeNode;
  421.     function GetIndent: Integer;
  422.     function GetNodeFromItem(const Item: TTVItem): TfcTreeNode;
  423.     function GetSelection: TfcTreeNode;
  424.     function GetTopItem: TfcTreeNode;
  425.     procedure ImageListChange(Sender: TObject);
  426.     procedure SetAutoExpand(Value: Boolean);
  427.     procedure SetBorderStyle(Value: TBorderStyle);
  428.     procedure SetChangeDelay(Value: Integer);
  429.     procedure SetDropTarget(Value: TfcTreeNode);
  430.     procedure SetImageList(Value: HImageList; Flags: Integer);
  431.     procedure SetIndent(Value: Integer);
  432.     procedure SetImages(Value: TCustomImageList);
  433.     procedure SetReadOnly(Value: Boolean);
  434.     procedure SetSelection(Value: TfcTreeNode);
  435.     procedure SetSortType(Value: TfcSortType);
  436.     procedure SetStateImages(Value: TCustomImageList);
  437. //    procedure SetToolTips(Value: Boolean);
  438.     procedure SeTfcTreeNodes(Value: TfcTreeNodes);
  439.     procedure SetTopItem(Value: TfcTreeNode);
  440.     procedure OnChangeTimer(Sender: TObject);
  441.     procedure WMLButtonDown(var Message: TWMLButtonDown); message WM_LBUTTONDOWN;
  442.     procedure WMRButtonDown(var Message: TWMRButtonDown); message WM_RBUTTONDOWN;
  443.     procedure WMRButtonUp(var Message: TWMRButtonUp); message WM_RBUTTONUP;
  444.     procedure WMLButtonDblClk(var Message: TWMLButtonDblClk); message WM_LBUTTONDBLCLK;
  445.     procedure WMNotify(var Message: TWMNotify); message WM_NOTIFY;
  446.     procedure CMSysColorChange(var Message: TMessage); message CM_SYSCOLORCHANGE;
  447.     procedure WMPaint(var Message: TWMPaint); message WM_PAINT;
  448.     procedure WMEraseBkgnd(var Message: TWmEraseBkgnd); message WM_ERASEBkgnd;
  449.     procedure CMExit(var Message: TMessage); message CM_EXIT;
  450.     procedure CMDesignHitTest(var Message: TCMDesignHitTest); message CM_DESIGNHITTEST;
  451.     procedure WMDestroy(var Message: TWMDestroy); message WM_DESTROY;
  452.     function ValidMultiSelectLevel(ALevel: Integer): Boolean;
  453.     Function CheckboxNeeded(Node: TfcTreeNode): boolean;
  454.     Function GetCenterPoint(ARect: TRect): TPoint;
  455.     procedure SetOptions(Value: TfcTreeViewOptions);
  456.     procedure SetLineColor(Value: TColor);
  457.     procedure SetInactiveFocusColor(Value: TColor);
  458.     function GetItemHeight: ShortInt;
  459.     procedure SetItemHeight(Value: ShortInt);
  460.     function GetScrollTime: Integer;
  461.     procedure SetScrollTime(Value: Integer);
  462.     function GetMultiSelectListCount: integer;
  463.     function GetMultiSelectItem(Index: integer): TfcTreeNode;
  464.     procedure HintTimerEvent(Sender: TObject);
  465.     function GetPaintCanvas: TfcCanvas;
  466.   protected
  467.     FMultiSelectList: TList;
  468.     SkipErase: boolean;
  469.     SkipChangeMessages: boolean;  { Notify method skips processing of change notifications }
  470.     InLoading: boolean; { During expansion of Reference tree,
  471.                           do not recursively expand item's children.
  472.                           Calling MoveTo expands parent so we prevent this}
  473.     FChangeTimer: TTimer;
  474.     DisplayedItems: integer;
  475.     FMouseInControl : boolean;
  476.     { Implement hint handling }
  477.     HintWindow: THintWindow;
  478.     HintTimer: TTimer;
  479.     HintTimerCount: integer;
  480.     LastHintNode: TfcTreeNode;
  481.     function CanEdit(Node: TfcTreeNode): Boolean; dynamic;
  482.     function CanChange(Node: TfcTreeNode): Boolean; dynamic;
  483.     function CanCollapse(Node: TfcTreeNode): Boolean; dynamic;
  484.     function CanExpand(Node: TfcTreeNode): Boolean; dynamic;
  485.     procedure Change(Node: TfcTreeNode); dynamic;
  486.     procedure Collapse(Node: TfcTreeNode); dynamic;
  487.     function CreateNode: TfcTreeNode; virtual;
  488.     procedure CreateParams(var Params: TCreateParams); override;
  489.     procedure CreateWnd; override;
  490.     procedure Delete(Node: TfcTreeNode); dynamic;
  491.     procedure DestroyWnd; override;
  492.     procedure DoEndDrag(Target: TObject; X, Y: Integer); override;
  493.     procedure DoStartDrag(var DragObject: TDragObject); override;
  494.     procedure Edit(const Item: TTVItem); dynamic;
  495.     procedure Expand(Node: TfcTreeNode); dynamic;
  496.     function GetDragImages: {$ifdef fcDelphi4Up}TDragImageList{$else}TCustomImageList{$endif}; override;
  497.     procedure GetImageIndex(Node: TfcTreeNode); virtual;
  498.     procedure GetSelectedIndex(Node: TfcTreeNode); virtual;
  499.     procedure Loaded; override;
  500.     procedure KeyPress(var Key: Char); override;
  501.     procedure KeyDown(var Key: Word; Shift: TShiftState); override;
  502.     procedure Notification(AComponent: TComponent;
  503.       Operation: TOperation); override;
  504.     procedure SetDragMode(Value: TDragMode); override;
  505.     procedure WndProc(var Message: TMessage); override;
  506.     property AutoExpand: Boolean read FAutoExpand write SetAutoExpand default False;
  507.     property BorderStyle: TBorderStyle read FBorderStyle write SetBorderStyle default bsSingle;
  508.     property ChangeDelay: Integer read GetChangeDelay write SetChangeDelay default 0;
  509.     property Images: TCustomImageList read FImages write SetImages;
  510.     property Indent: Integer read GetIndent write SetIndent;
  511.     property ReadOnly: Boolean read FReadOnly write SetReadOnly default False;
  512.     property RightClickSelects: Boolean read FRightClickSelects write FRightClickSelects default False;
  513.     property SortType: TfcSortType read FSortType write SetSortType default fcstNone;
  514.     property StateImages: TCustomImageList read FStateImages write SetStateImages;
  515.     property StreamExpandedNode: Boolean read FStreamExpandedNode write FStreamExpandedNode default False;
  516. //    property ToolTips: Boolean read FToolTips write SetToolTips default False;
  517.     property OnEditing: TfcTVEditingEvent read FOnEditing write FOnEditing;
  518.     property OnEdited: TfcTVEditedEvent read FOnEdited write FOnEdited;
  519.     property OnExpanding: TfcTVExpandingEvent read FOnExpanding write FOnExpanding;
  520.     property OnExpanded: TfcTVExpandedEvent read FOnExpanded write FOnExpanded;
  521.     property OnCollapsing: TfcTVCollapsingEvent read FOnCollapsing write FOnCollapsing;
  522.     property OnCollapsed: TfcTVExpandedEvent read FOnCollapsed write FOnCollapsed;
  523.     property OnChanging: TfcTVChangingEvent read FOnChanging write FOnChanging;
  524.     property OnChange: TfcTVChangedEvent read FOnChange write FOnChange;
  525.     property OnCompare: TfcTVCompareEvent read FOnCompare write FOnCompare;
  526.     property OnDeletion: TfcTVExpandedEvent read FOnDeletion write FOnDeletion;
  527.     property OnGetImageIndex: TfcTVExpandedEvent read FOnGetImageIndex write FOnGetImageIndex;
  528.     property OnGetSelectedIndex: TfcTVExpandedEvent read FOnGetSelectedIndex write FOnGetSelectedIndex;
  529.     procedure MultiSelectNode(Node: TfcTreeNode; Select: boolean; redraw: boolean); virtual;
  530.     function IsVisible(Node: TfcTreeNode; PartialOK: Boolean): Boolean; virtual;
  531.     function ItemRect(Node: TfcTreeNode; LabelOnly: Boolean): TRect;
  532.     procedure PaintButton(Node: TfcTreeNode; pt: TPoint; size: integer);
  533.     procedure PaintLines(Node: TfcTreeNode);
  534.     procedure PaintImage(Node: TfcTreeNode; State: TfcItemStates);
  535.     function LevelRect(ANode: TfcTreeNode): TRect;
  536.     procedure DoDrawText(TreeView: TfcCustomTreeView;
  537.          Node: TfcTreeNode; ARect: TRect; AItemState: TfcItemStates;
  538.          var DefaultDrawing: boolean); virtual;
  539.     procedure Compare(Node1, Node2: TfcTreeNode; lParam: integer; var Result: integer); virtual;
  540.     procedure CalcNodeAttributes(Node: TfcTreeNode; AItemState: TfcItemStates); virtual;
  541.     function GetDisplayText(Node: TfcTreeNode): string; virtual;
  542.     procedure LoadCanvasDefaults(Node: TfcTreeNode; AItemState: TfcItemStates);
  543.     function ProcessKeyPress(Key: char; shift: TShiftState): boolean; virtual;
  544.     function IsRowSelect: boolean; virtual;
  545.     procedure MouseLoop(X, Y: Integer); virtual;
  546.     procedure MouseDown(Button: TMouseButton; Shift: TShiftState;
  547.                  X, Y: Integer); override;
  548.     function UseImages(Node: TfcTreeNode): Boolean;
  549.     function UseStateImages(Node: TfcTreeNode): Boolean;
  550.     procedure BeginPainting; virtual;
  551.     procedure EndPainting; virtual;
  552.     procedure BeginItemPainting(Node: TfcTreeNode; ARect: TRect; AItemState: TfcItemStates); virtual;
  553.     procedure EndItemPainting(Node: TfcTreeNode; ARect: TRect; AItemState: TfcItemStates); virtual;
  554.     procedure PaintItem(Node: TfcTreeNode); virtual;
  555.     procedure ClearStateImageIndexes;
  556.     procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
  557.     procedure MouseUp(Button: TMouseButton; Shift: TShiftState;
  558.       X, Y: Integer); override;
  559.     procedure DoToggleCheckbox(Node: TfcTreeNode); virtual;
  560.     procedure FreeHintWindow; virtual;
  561.     Function CreateHintWindow(Node: TfcTreeNode): THintWindow; virtual;
  562.     Procedure UnselectAllNodes(IgnoreNode: TfcTreeNode);
  563.     procedure InvalidateNoErase;
  564.     property ItemHeight: ShortInt read GetItemHeight write SetItemHeight;
  565.     property OnCalcNodeAttributes: TfcCalcNodeAttributesEvent read FOnCalcNodeAttributes write FOnCalcNodeAttributes;
  566.     property ScrollTime: Integer read GetScrollTime write SetScrollTime;
  567.     property NodeClass: TfcTreeNodeClass read FNodeClass write FNodeClass;
  568.   public
  569.     Patch: Variant;
  570.     procedure ResetStateImages;
  571.     property StreamVersion: integer read FStreamVersion;
  572.     Function GetFirstSibling(Node: TfcTreeNode): TfcTreeNode;
  573.     Procedure InvalidateNode(Node: TfcTreeNode);
  574.     Function MultiSelectCheckboxNeeded(Node: TfcTreeNode): boolean;
  575.     Procedure UnselectAll;
  576.     constructor Create(AOwner: TComponent); override;
  577.     destructor Destroy; override;
  578.     function AlphaSort: Boolean;
  579.     function CustomSort(SortProc: TTVCompare; Data: Longint): Boolean;
  580.     procedure FullCollapse;
  581.     procedure FullExpand;
  582.     function GetHitTestInfoAt(X, Y: Integer): TfcHitTests;
  583.     function GetNodeAt(X, Y: Integer): TfcTreeNode;
  584.     function IsEditing: Boolean;
  585.     procedure LoadFromFile(const FileName: string);
  586.     procedure LoadFromStream(Stream: TStream);
  587.     procedure SaveToFile(const FileName: string);
  588.     procedure SaveToStream(Stream: TStream);
  589.     property Canvas: TfcCanvas read GetPaintCanvas;
  590.     property DropTarget: TfcTreeNode read GetDropTarget write SetDropTarget;
  591.     property Selected: TfcTreeNode read GetSelection write SetSelection;
  592.     property TopItem: TfcTreeNode read GetTopItem write SetTopItem;
  593.     property RightClickNode: TfcTreeNode read FRClickNode;
  594.     property Options: TfcTreeViewOptions read FOptions write SetOptions default
  595.         [tvoExpandOnDblClk, tvoShowButtons, tvoShowRoot, tvoShowLines, tvoHideSelection, tvoToolTips];
  596.     property Items: TfcTreeNodes read FTreeNodes write SeTfcTreeNodes;
  597.     property MultiSelectAttributes: TfcTVMultiSelectAttributes
  598.         read FMultiSelectAttributes write FMultiSelectAttributes;
  599.     property OnDrawText: TfcTVDrawTextEvent read FOnDrawText write FOnDrawText;
  600.     property OnItemChange: TfcItemChangeEvent read FOnItemChange write FOnItemChange;
  601.     property MultiSelectList[Index: Integer]: TfcTreeNode read GetMultiSelectItem;
  602.     property MultiSelectListCount : integer read GetMultiSelectListCount;
  603.     property LineColor: TColor read FLineColor write SetLineColor default clBtnShadow;
  604.     property InactiveFocusColor: TColor read FInactiveFocusColor write SetInactiveFocusColor default clBtnFace;
  605.     property OnMouseMove: TfcTreeMouseMoveEvent read FOnMouseMove write FOnMouseMove;
  606.     property OnMouseDown: TfcTreeMouseEvent read FOnMouseDown write FOnMouseDown;
  607.     property OnMouseUp: TfcTreeMouseEvent read FOnMouseUp write FOnMouseUp;
  608.     property OnDblClick: TfcTreeMouseEvent read FOnDblClick write FOnDblClick;
  609.     property OnToggleCheckbox: TfcToggleCheckboxEvent read FOnToggleCheckbox write FOnToggleCheckbox;
  610.     property UsePaintBuffering: boolean read FUsePaintBuffering write FUsePaintBuffering default False;
  611.     property DisableThemes : boolean read FDisableThemes write FDisableThemes default False;
  612.   end;
  613.   TfcTreeView = class(TfcCustomTreeView)
  614.   published
  615.     property DisableThemes;
  616.     property Align;
  617.     {$ifdef fcDelphi4Up}
  618.     property Anchors;
  619.     {$endif}
  620.     property AutoExpand;
  621.     {$ifdef fcDelphi4Up}
  622.     property BiDiMode;
  623.     {$endif}
  624.     property BorderStyle;
  625. //    property BorderWidth;
  626.     property ChangeDelay;
  627.     property Color;
  628.     property LineColor;
  629.     property InactiveFocusColor;
  630.     property Ctl3D;
  631.     {$ifdef fcDelphi4Up}
  632.     property Constraints;
  633.     property DragKind;
  634.     {$endIf}
  635.     property DragCursor;
  636.     property DragMode;
  637.     property Enabled;
  638.     property Font;
  639.     property Images;
  640.     property Indent;
  641.     property MultiSelectAttributes;
  642.     property Options;
  643.     property Items;
  644.     {$ifdef fcDelphi4Up}
  645.     property ParentBiDiMode;
  646.     {$endif}
  647.     property ParentColor default False;
  648.     property ParentCtl3D;
  649.     property ParentFont;
  650.     property ParentShowHint;
  651.     property UsePaintBuffering;
  652.     property PopupMenu;
  653.     property ReadOnly;
  654.     property RightClickSelects;
  655.     {$ifdef fcDelphi4Up}
  656.     property ShowHint;
  657.     {$endif}
  658.     property SortType;
  659.     property StateImages;
  660.     property StreamExpandedNode;
  661.     property TabOrder;
  662.     property TabStop default True;
  663. //    property ToolTips;
  664.     property Visible;
  665.     property OnChange;
  666.     property OnChanging;
  667.     property OnClick;
  668.     property OnCollapsing;
  669.     property OnCollapsed;
  670.     property OnCompare;
  671.     property OnDblClick;
  672.     property OnDeletion;
  673.     property OnDragDrop;
  674.     property OnDragOver;
  675.     property OnEdited;
  676.     property OnEditing;
  677.     {$ifdef fcDelphi4Up}
  678.     property OnEndDock;
  679.     {$endif}
  680.     property OnEndDrag;
  681.     property OnEnter;
  682.     property OnExit;
  683.     property OnExpanding;
  684.     property OnExpanded;
  685.     property OnGetImageIndex;
  686.     property OnGetSelectedIndex;
  687.     property OnKeyDown;
  688.     property OnKeyPress;
  689.     property OnKeyUp;
  690.     property OnMouseDown;
  691.     property OnMouseMove;
  692.     property OnMouseUp;
  693.     property OnToggleCheckbox;
  694.     {$ifdef fcDelphi4Up}
  695.     property OnStartDock;
  696.     {$endif}
  697.     property OnStartDrag;
  698.     property OnCalcNodeAttributes;
  699.     property OnDrawText;
  700.   end;
  701.   procedure fcTreeViewError(const Msg: string);
  702. implementation
  703. { TfcTreeNode }
  704. {$ifdef fcDelphi6Up}
  705. uses RTLConsts;
  706. {$endif}
  707. const MaxCheckboxSize = 6;
  708.       FixBugImageListSize = 16;
  709. var FFixBugImageList: TImageList;
  710.     RefCount: integer;
  711. procedure SetComCtlStyle(Ctl: TWinControl; Value: Integer; UseStyle: Boolean);
  712. var
  713.   Style: Integer;
  714. begin
  715.   if Ctl.HandleAllocated then
  716.   begin
  717.     Style := GetWindowLong(Ctl.Handle, GWL_STYLE);
  718.     if not UseStyle then Style := Style and not Value
  719.     else Style := Style or Value;
  720.     SetWindowLong(Ctl.Handle, GWL_STYLE, Style);
  721.   end;
  722. end;
  723. function DefaultTreeViewSort(Node1, Node2: TfcTreeNode; lParam: Integer): Integer; stdcall;
  724. begin
  725. //    Result := lstrcmp(PChar(Node1.Text), PChar(Node2.Text));
  726.    Node1.TreeView.Compare(Node1, Node2, lParam, Result);
  727. end;
  728. {
  729. function DefaultTreeViewSort(Node1, Node2: TfcTreeNode; lParam: Integer): Integer; stdcall;
  730. begin
  731.   with Node1 do
  732.     if Assigned(TreeView.OnCompare) then
  733.       TreeView.OnCompare(TreeView, Node1, Node2, lParam, Result)
  734.     else Result := lstrcmp(PChar(Node1.Text), PChar(Node2.Text));
  735. end;
  736. }
  737. procedure TreeViewError(const Msg: string);
  738. begin
  739.   raise ETreeViewError.Create(Msg);
  740. end;
  741. {procedure TreeViewErrorFmt(const Msg: string; Format: array of const);
  742. begin
  743.   raise ETreeViewError.CreateFmt(Msg, Format);
  744. end;
  745. }
  746. constructor TfcTreeNode.Create(AOwner: TfcTreeNodes);
  747. begin
  748.   inherited Create;
  749.   FOverlayIndex := -1;
  750.   FStateIndex := -1;
  751.   FOwner := AOwner;
  752. end;
  753. destructor TfcTreeNode.Destroy;
  754. var
  755.   Node: TfcTreeNode;
  756.   CheckValue: Integer;
  757.   i: integer;
  758.   MultiSelectList: TList;
  759. begin
  760.    Owner.ClearCache;
  761.    FDeleting := True;
  762.    // 6/30/03 - Clear LastMouseMoveNode
  763.    if fcUseThemes(TreeView) then
  764.    begin
  765.       if TfcCustomTreeView(TreeView).LastMouseMoveNode = Self then
  766.          TfcCustomTreeView(TreeView).LastMouseMoveNode:= nil;
  767.    end;
  768.    if FMultiSelected then begin
  769.       if TfcCustomTreeView(TreeView).LastSelectedNode= self then
  770.          TfcCustomTreeView(TreeView).LastSelectedNode:= nil;
  771.       MultiSelectList:= (TreeView as TfcCustomTreeView).FMultiSelectList;
  772.       for i:= 0 to MultiSelectList.count-1 do begin  { Bad code }
  773.          if self=TfcTreeNode(MultiSelectList[i]) then
  774.          begin
  775.             MultiSelectList.delete(i);
  776.             break;
  777.          end
  778.       end
  779.    end;
  780.    if Owner.Owner.FLastDropTarget = Self then
  781.       Owner.Owner.FLastDropTarget := nil;
  782.    Node := Parent;
  783.    if (Node <> nil) and (not Node.Deleting) then
  784.    begin
  785.       if Node.IndexOf(Self) <> -1 then CheckValue := 1
  786.       else CheckValue := 0;
  787.       if Node.CompareCount(CheckValue) then
  788.       begin
  789.          Expanded := False;
  790.          Node.HasChildren := False;
  791.       end;
  792.    end;
  793.    if ItemId <> nil then TreeView_DeleteItem(Handle, ItemId);
  794.    Data := nil;
  795.    inherited Destroy;
  796. end;
  797. function TfcTreeNode.GetHandle: HWND;
  798. begin
  799.   Result := TreeView.Handle;
  800. end;
  801. function TfcTreeNode.GetTreeView: TfcCustomTreeView;
  802. begin
  803.   Result := Owner.Owner;
  804. end;
  805. function TfcTreeNode.HasAsParent(Value: TfcTreeNode): Boolean;
  806. begin
  807.   if Value <> Nil then
  808.   begin
  809.     if Parent = nil then Result := False
  810.     else if Parent = Value then Result := True
  811.     else Result := Parent.HasAsParent(Value);
  812.   end
  813.   else Result := True;
  814. end;
  815. procedure TfcTreeNode.SetText(const S: string);
  816. var
  817.   Item: TTVItem;
  818.   AVariant: Variant;
  819. begin
  820.   if s = '' then AVariant := NULL else AVariant := s;
  821.   if Assigned(TreeView.OnItemChange) then TreeView.OnItemChange(TreeView, self, icaText, AVariant);
  822.   FText := S;
  823.   with Item do
  824.   begin
  825.     mask := TVIF_TEXT;
  826.     hItem := ItemId;
  827.     pszText := LPSTR_TEXTCALLBACK;
  828.   end;
  829.   TreeView_SetItem(Handle, Item);
  830.   if (TreeView.SortType in [fcstText, fcstBoth]) and FInTree then
  831.   begin
  832.     if (Parent <> nil) then Parent.AlphaSort
  833.     else TreeView.AlphaSort;
  834.   end;
  835. end;
  836. procedure TfcTreeNode.SetData(Value: Pointer);
  837. begin
  838.   FData := Value;
  839.   if (TreeView.SortType in [fcstData, fcstBoth]) and Assigned(TreeView.OnCompare)
  840.     and (not Deleting) and FInTree then
  841.   begin
  842.     if Parent <> nil then Parent.AlphaSort
  843.     else TreeView.AlphaSort;
  844.   end;
  845. end;
  846. function TfcTreeNode.GetState(NodeState: TfcNodeState): Boolean;
  847. var
  848.   Item: TTVItem;
  849. begin
  850.   Result := False;
  851.   with Item do
  852.   begin
  853.     mask := TVIF_STATE;
  854.     hItem := ItemId;
  855.     if TreeView_GetItem(Handle, Item) then
  856.       case NodeState of
  857.         fcnsCut: Result := (state and TVIS_CUT) <> 0;
  858.         fcnsFocused: Result := (state and TVIS_FOCUSED) <> 0;
  859.         fcnsSelected: Result := (state and TVIS_SELECTED) <> 0;
  860.         fcnsExpanded: Result := (state and TVIS_EXPANDED) <> 0;
  861.         fcnsDropHilited: Result := (state and TVIS_DROPHILITED) <> 0;
  862.       end;
  863.   end;
  864. end;
  865. procedure TfcTreeNode.SetImageIndex(Value: Integer);
  866. var
  867.   Item: TTVItem;
  868. begin
  869.   if Assigned(TreeView.OnItemChange) then TreeView.OnItemChange(TreeView, self, icaImageIndex, Value);
  870.   FImageIndex := Value;
  871.   with Item do
  872.   begin
  873.     mask := TVIF_IMAGE or TVIF_HANDLE;
  874.     hItem := ItemId;
  875.     iImage := I_IMAGECALLBACK;
  876.   end;
  877.   TreeView_SetItem(Handle, Item);
  878. end;
  879. procedure TfcTreeNode.SetSelectedIndex(Value: Integer);
  880. var
  881.   Item: TTVItem;
  882. begin
  883.   FSelectedIndex := Value;
  884.   with Item do
  885.   begin
  886.     mask := TVIF_SELECTEDIMAGE or TVIF_HANDLE;
  887.     hItem := ItemId;
  888.     iSelectedImage := I_IMAGECALLBACK;
  889.   end;
  890.   TreeView_SetItem(Handle, Item);
  891. end;
  892. procedure TfcTreeNode.SetOverlayIndex(Value: Integer);
  893. var
  894.   Item: TTVItem;
  895. begin
  896.   FOverlayIndex := Value;
  897.   with Item do
  898.   begin
  899.     mask := TVIF_STATE or TVIF_HANDLE;
  900.     stateMask := TVIS_OVERLAYMASK;
  901.     hItem := ItemId;
  902.     state := IndexToOverlayMask(OverlayIndex + 1);
  903.   end;
  904.   TreeView_SetItem(Handle, Item);
  905. end;
  906. procedure TfcTreeNode.SetStateIndex(Value: Integer);
  907. var
  908.   Item: TTVItem;
  909. begin
  910.   if Value=0 then Value:= -1;  // 11/21/98 - (RSW) Don't allow 0 as state index
  911.   if (CheckboxType = tvctCheckbox) and (Value<>-1) and (Value<>1) then exit; { 3/8/99}
  912.   FStateIndex := Value;
  913.   if Value >= 0 then Dec(Value);
  914.   with Item do
  915.   begin
  916.     mask := TVIF_STATE or TVIF_HANDLE;
  917.     stateMask := TVIS_STATEIMAGEMASK;
  918.     hItem := ItemId;
  919.     state := IndexToStateImageMask(Value + 1);
  920.   end;
  921.   TreeView_SetItem(Handle, Item);
  922. end;
  923. function TfcTreeNode.CompareCount(CompareMe: Integer): Boolean;
  924. var
  925.   Count: integer;
  926.   Node: TfcTreeNode;
  927. Begin
  928.   Count := 0;
  929.   Result := False;
  930.   Node := GetFirstChild;
  931.   while Node <> nil do
  932.   begin
  933.     Inc(Count);
  934.     Node := Node.GetNextChild(Node);
  935.     if Count > CompareMe then Exit;
  936.   end;
  937.   if Count = CompareMe then Result := True;
  938. end;
  939. function TfcTreeNode.DoCanExpand(Expand: Boolean): Boolean;
  940. begin
  941.   Result := False;
  942.   if HasChildren then
  943.   begin
  944.     if Expand then Result := TreeView.CanExpand(Self)
  945.     else Result := TreeView.CanCollapse(Self);
  946.   end;
  947. end;
  948. procedure TfcTreeNode.DoExpand(Expand: Boolean);
  949. begin
  950.   if HasChildren then
  951.   begin
  952.     if Expand then TreeView.Expand(Self)
  953.     else TreeView.Collapse(Self);
  954.   end;
  955. end;
  956. procedure TfcTreeNode.ExpandItem(Expand: Boolean; Recurse: Boolean);
  957. var
  958.   Flag: Integer;
  959.   Node: TfcTreeNode;
  960. begin
  961.   if Recurse then
  962.   begin
  963.     Node := Self;
  964.     repeat
  965.       Node.ExpandItem(Expand, False);
  966.       Node := Node.GetNext;
  967.     until (Node = nil) or (not Node.HasAsParent(Self));
  968.   end
  969.   else begin
  970.     TreeView.FManualNotify := True;
  971.     try
  972.       Flag := 0;
  973.       if Expand then
  974.       begin
  975.         if DoCanExpand(True) then
  976.         begin
  977.           Flag := TVE_EXPAND;
  978.           DoExpand(True);
  979.         end;
  980.       end
  981.       else begin
  982.         if DoCanExpand(False) then
  983.         begin
  984.           Flag := TVE_COLLAPSE;
  985.           DoExpand(False);
  986.         end;
  987.       end;
  988.       if Flag <> 0 then TreeView_Expand(Handle, ItemId, Flag);
  989.     finally
  990.       TreeView.FManualNotify := False;
  991.     end;
  992.   end;
  993. end;
  994. procedure TfcTreeNode.Expand(Recurse: Boolean);
  995. begin
  996.   ExpandItem(True, Recurse);
  997. end;
  998. procedure TfcTreeNode.Collapse(Recurse: Boolean);
  999. begin
  1000.   ExpandItem(False, Recurse);
  1001. end;
  1002. function TfcTreeNode.GetExpanded: Boolean;
  1003. begin
  1004.   Result := GetState(fcnsExpanded);
  1005. end;
  1006. procedure TfcTreeNode.SetExpanded(Value: Boolean);
  1007. begin
  1008.   if Value then Expand(False)
  1009.   else Collapse(False);
  1010. end;
  1011. function TfcTreeNode.GetSelected: Boolean;
  1012. begin
  1013.   Result := GetState(fcnsSelected);
  1014. end;
  1015. procedure TfcTreeNode.SetSelected(Value: Boolean);
  1016. begin
  1017.   if Value then TreeView_SelectItem(Handle, ItemId)
  1018.   else if Selected then TreeView_SelectItem(Handle, nil);
  1019. end;
  1020. function TfcTreeNode.GetCut: Boolean;
  1021. begin
  1022.   Result := GetState(fcnsCut);
  1023. end;
  1024. procedure TfcTreeNode.SetCut(Value: Boolean);
  1025. var
  1026.   Item: TTVItem;
  1027.   Template: DWORD;
  1028. begin
  1029.   if Value then Template := DWORD(-1)
  1030.   else Template := 0;
  1031.   with Item do
  1032.   begin
  1033.     mask := TVIF_STATE;
  1034.     hItem := ItemId;
  1035.     stateMask := TVIS_CUT;
  1036.     state := stateMask and Template;
  1037.   end;
  1038.   TreeView_SetItem(Handle, Item);
  1039. end;
  1040. function TfcTreeNode.GetDropTarget: Boolean;
  1041. begin
  1042.   Result := GetState(fcnsDropHilited);
  1043. end;
  1044. procedure TfcTreeNode.SetDropTarget(Value: Boolean);
  1045. begin
  1046.   if Value then TreeView_SelectDropTarget(Handle, ItemId)
  1047.   else if DropTarget then TreeView_SelectDropTarget(Handle, nil);
  1048. end;
  1049. function TfcTreeNode.GetChildren: Boolean;
  1050. var
  1051.   Item: TTVItem;
  1052. begin
  1053.   Item.mask := TVIF_CHILDREN;
  1054.   Item.hItem := ItemId;
  1055.   if TreeView_GetItem(Handle, Item) then Result := Item.cChildren > 0
  1056.   else Result := False;
  1057. end;
  1058. procedure TfcTreeNode.SetFocused(Value: Boolean);
  1059. var
  1060.   Item: TTVItem;
  1061.   Template: DWORD;
  1062. begin
  1063.   if Value then Template := DWORD(-1)
  1064.   else Template := 0;
  1065.   with Item do
  1066.   begin
  1067.     mask := TVIF_STATE;
  1068.     hItem := ItemId;
  1069.     stateMask := TVIS_FOCUSED;
  1070.     state := stateMask and Template;
  1071.   end;
  1072.   TreeView_SetItem(Handle, Item);
  1073. end;
  1074. function TfcTreeNode.GetFocused: Boolean;
  1075. begin
  1076.   Result := GetState(fcnsFocused);
  1077. end;
  1078. procedure TfcTreeNode.SetChildren(Value: Boolean);
  1079. var
  1080.   Item: TTVItem;
  1081. begin
  1082.   with Item do
  1083.   begin
  1084.     mask := TVIF_CHILDREN;
  1085.     hItem := ItemId;
  1086.     cChildren := Ord(Value);
  1087.   end;
  1088.   TreeView_SetItem(Handle, Item);
  1089. end;
  1090. function TfcTreeNode.GetParent: TfcTreeNode;
  1091. begin
  1092.   with FOwner do
  1093.     Result := GetNode(TreeView_GetParent(Handle, ItemId));
  1094. end;
  1095. function TfcTreeNode.GetNextSibling: TfcTreeNode;
  1096. begin
  1097.   with FOwner do
  1098.     Result := GetNode(TreeView_GetNextSibling(Handle, ItemId));
  1099. end;
  1100. function TfcTreeNode.GetPrevSibling: TfcTreeNode;
  1101. begin
  1102.   with FOwner do
  1103.     Result := GetNode(TreeView_GetPrevSibling(Handle, ItemId));
  1104. end;
  1105. function TfcTreeNode.GetNextVisible: TfcTreeNode;
  1106. begin
  1107.   if IsVisible then
  1108.     with FOwner do
  1109.       Result := GetNode(TreeView_GetNextVisible(Handle, ItemId))
  1110.   else Result := nil;
  1111. end;
  1112. function TfcTreeNode.GetPrevVisible: TfcTreeNode;
  1113. begin
  1114.   with FOwner do
  1115.     Result := GetNode(TreeView_GetPrevVisible(Handle, ItemId));
  1116. end;
  1117. function TfcTreeNode.GetNextChild(Value: TfcTreeNode): TfcTreeNode;
  1118. begin
  1119.   if Value <> nil then Result := Value.GetNextSibling
  1120.   else Result := nil;
  1121. end;
  1122. function TfcTreeNode.GetPrevChild(Value: TfcTreeNode): TfcTreeNode;
  1123. begin
  1124.   if Value <> nil then Result := Value.GetPrevSibling
  1125.   else Result := nil;
  1126. end;
  1127. function TfcTreeNode.GetFirstChild: TfcTreeNode;
  1128. begin
  1129.   with FOwner do
  1130.     Result := GetNode(TreeView_GetChild(Handle, ItemId));
  1131. end;
  1132. function TfcTreeNode.GetLastChild: TfcTreeNode;
  1133. var
  1134.   Node: TfcTreeNode;
  1135. begin
  1136.   Result := GetFirstChild;
  1137.   if Result <> nil then
  1138.   begin
  1139.     Node := Result;
  1140.     repeat
  1141.       Result := Node;
  1142.       Node := Result.GetNextSibling;
  1143.     until Node = nil;
  1144.   end;
  1145. end;
  1146. function TfcTreeNode.GetNext: TfcTreeNode;
  1147. var
  1148.   NodeID, ParentID: HTreeItem;
  1149.   Handle: HWND;
  1150. begin
  1151.   Handle := FOwner.Handle;
  1152.   NodeID := TreeView_GetChild(Handle, ItemId);
  1153.   if NodeID = nil then NodeID := TreeView_GetNextSibling(Handle, ItemId);
  1154.   ParentID := ItemId;
  1155.   while (NodeID = nil) and (ParentID <> nil) do
  1156.   begin
  1157.     ParentID := TreeView_GetParent(Handle, ParentID);
  1158.     NodeID := TreeView_GetNextSibling(Handle, ParentID);
  1159.   end;
  1160.   Result := FOwner.GetNode(NodeID);
  1161. end;
  1162. function TfcTreeNode.GetPrev: TfcTreeNode;
  1163. var
  1164.   Node: TfcTreeNode;
  1165. begin
  1166.   Result := GetPrevSibling;
  1167.   if Result <> nil then
  1168.   begin
  1169.     Node := Result;
  1170.     repeat
  1171.       Result := Node;
  1172.       Node := Result.GetLastChild;
  1173.     until Node = nil;
  1174.   end else
  1175.     Result := Parent;
  1176. end;
  1177. function TfcTreeNode.GetAbsoluteIndex: Integer;
  1178. var
  1179.   Node: TfcTreeNode;
  1180. begin
  1181.   if Owner.FNodeCache.CacheNode = Self then
  1182.     Result := Owner.FNodeCache.CacheIndex
  1183.   else begin
  1184.     Result := -1;
  1185.     Node := Self;
  1186.     while Node <> nil do
  1187.     begin
  1188.       Inc(Result);
  1189.       Node := Node.GetPrev;
  1190.     end;
  1191.   end;
  1192. end;
  1193. function TfcTreeNode.GetIndex: Integer;
  1194. var
  1195.   Node: TfcTreeNode;
  1196. begin
  1197.   Result := -1;
  1198.   Node := Self;
  1199.   while Node <> nil do
  1200.   begin
  1201.     Inc(Result);
  1202.     Node := Node.GetPrevSibling;
  1203.   end;
  1204. end;
  1205. function TfcTreeNode.GetItem(Index: Integer): TfcTreeNode;
  1206. begin
  1207.   Result := GetFirstChild;
  1208.   while (Result <> nil) and (Index > 0) do
  1209.   begin
  1210.     Result := GetNextChild(Result);
  1211.     Dec(Index);
  1212.   end;
  1213.   if Result = nil then TreeViewError(SListIndexError);
  1214. end;
  1215. procedure TfcTreeNode.SetItem(Index: Integer; Value: TfcTreeNode);
  1216. begin
  1217.   item[Index].Assign(Value);
  1218. end;
  1219. function TfcTreeNode.IndexOf(Value: TfcTreeNode): Integer;
  1220. var
  1221.   Node: TfcTreeNode;
  1222. begin
  1223.   Result := -1;
  1224.   Node := GetFirstChild;
  1225.   while (Node <> nil) do
  1226.   begin
  1227.     Inc(Result);
  1228.     if Node = Value then Break;
  1229.     Node := GetNextChild(Node);
  1230.   end;
  1231.   if Node = nil then Result := -1;
  1232. end;
  1233. function TfcTreeNode.GetCount: Integer;
  1234. var
  1235.   Node: TfcTreeNode;
  1236. begin
  1237.   Result := 0;
  1238.   Node := GetFirstChild;
  1239.   while Node <> nil do
  1240.   begin
  1241.     Inc(Result);
  1242.     Node := Node.GetNextChild(Node);
  1243.   end;
  1244. end;
  1245. procedure TfcTreeNode.EndEdit(Cancel: Boolean);
  1246. begin
  1247.   TreeView_EndEditLabelNow(Handle, Cancel);
  1248. end;
  1249. procedure TfcTreeNode.InternalMove(ParentNode, Node: TfcTreeNode;
  1250.   HItem: HTreeItem; AddMode: TfcAddMode);
  1251. var
  1252.   I: Integer;
  1253.   NodeId: HTreeItem;
  1254.   TreeViewItem: TTVItem;
  1255.   Children: Boolean;
  1256.   IsSelected: Boolean;
  1257. begin
  1258.   { if ParentNode = Node then Exit; }
  1259.   Owner.ClearCache;
  1260.   if (AddMode = fctaInsert) and (Node <> nil) then
  1261.     NodeId := Node.ItemId else
  1262.     NodeId := nil;
  1263.   Children := HasChildren;
  1264.   IsSelected := Selected;
  1265.   if (Parent <> nil) and (Parent.CompareCount(1)) then
  1266.   begin
  1267.     Parent.Expanded := False;
  1268.     Parent.HasChildren := False;
  1269.   end;
  1270.   with TreeViewItem do
  1271.   begin
  1272.     mask := TVIF_PARAM;
  1273.     hItem := ItemId;
  1274.     lParam := 0;
  1275.   end;
  1276.   TreeView_SetItem(Handle, TreeViewItem);
  1277.   with Owner do
  1278.     HItem := AddItem(HItem, NodeId, CreateItem(Self), AddMode);
  1279.   if HItem = nil then
  1280.     raise EOutOfResources.Create(sInsertError);
  1281.   for I := Count - 1 downto 0 do
  1282.     Item[I].InternalMove(Self, nil, HItem, fctaAddFirst);
  1283.   TreeView_DeleteItem(Handle, ItemId);
  1284.   FItemId := HItem;
  1285.   Assign(Self);
  1286.   HasChildren := Children;
  1287.   Selected := IsSelected;
  1288. end;
  1289. procedure TfcTreeNode.MoveTo(Destination: TfcTreeNode; Mode: TfcNodeAttachMode);
  1290. var
  1291.   AddMode: TfcAddMode;
  1292.   Node: TfcTreeNode;
  1293.   HItem: HTreeItem;
  1294.   OldOnChanging: TfcTVChangingEvent;
  1295.   OldOnChange: TfcTVChangedEvent;
  1296. begin
  1297.   OldOnChanging := TreeView.OnChanging;
  1298.   OldOnChange := TreeView.OnChange;
  1299.   TreeView.OnChanging := nil;
  1300.   TreeView.OnChange := nil;
  1301.   try
  1302.     if (Destination = nil) or not Destination.HasAsParent(Self) then
  1303.     begin
  1304.       AddMode := fctaAdd;
  1305.       if (Destination <> nil) and not (Mode in [fcnaAddChild, fcnaAddChildFirst]) then
  1306.         Node := Destination.Parent else
  1307.         Node := Destination;
  1308.       case Mode of
  1309.         fcnaAdd,
  1310.         fcnaAddChild: AddMode := fctaAdd;
  1311.         fcnaAddFirst,
  1312.         fcnaAddChildFirst: AddMode := fctaAddFirst;
  1313.         fcnaInsert:
  1314.           begin
  1315.             Destination := Destination.GetPrevSibling;
  1316.             if Destination = Self then exit;
  1317.             if Destination = nil then AddMode := fctaAddFirst
  1318.             else AddMode := fctaInsert;
  1319.           end;
  1320.         fcnaInsertAfter:
  1321.           begin
  1322.             if Destination.GetNextSibling = nil then AddMode := fctaAdd
  1323.             else AddMode := fctaInsert;
  1324.           end;
  1325.       end;
  1326.       if Node <> nil then
  1327.         HItem := Node.ItemId else
  1328.         HItem := nil;
  1329.       InternalMove(Node, Destination, HItem, AddMode);
  1330.       Node := Parent;
  1331.       if Node <> nil then
  1332.       begin
  1333.         Node.HasChildren := True;
  1334.         Node.Expanded := True;
  1335.       end;
  1336.     end;
  1337.   finally
  1338.     TreeView.OnChanging := OldOnChanging;
  1339.     TreeView.OnChange := OldOnChange;
  1340.     Invalidate;
  1341.   end;
  1342. end;
  1343. procedure TfcTreeNode.MakeVisible;
  1344. begin
  1345.   TreeView_EnsureVisible(Handle, ItemId);
  1346. end;
  1347. function TfcTreeNode.GetLevel: Integer;
  1348. var
  1349.   Node: TfcTreeNode;
  1350. begin
  1351.   Result := 0;
  1352.   Node := Parent;
  1353.   while Node <> nil do
  1354.   begin
  1355.     Inc(Result);
  1356.     Node := Node.Parent;
  1357.   end;
  1358. end;
  1359. function TfcTreeNode.IsNodeVisible: Boolean;
  1360. var
  1361.   Rect: TRect;
  1362. begin
  1363.   Result := TreeView_GetItemRect(Handle, ItemId, Rect, True);
  1364. end;
  1365. function TfcTreeNode.EditText: Boolean;
  1366. begin
  1367.   Result := TreeView_EditLabel(Handle, ItemId) <> 0;
  1368. end;
  1369. {function TfcTreeNode.ShowBlankImage: boolean;
  1370. begin
  1371.   result:= not ((TreeView.Images<>nil) and (ImageIndex=-2));
  1372. end;
  1373. }
  1374. function TfcTreeNode.DisplayRect(TextOnly: Boolean): TRect;
  1375. begin
  1376.   FillChar(Result, SizeOf(Result), 0);
  1377.   TreeView_GetItemRect(Handle, ItemId, Result, TextOnly);
  1378.   { Special case of imageindex=-2, do not show blank image }
  1379.   if TextOnly and (TreeView.Images<>nil) and not TreeView.UseImages(self) then
  1380.       result.Left:= result.Left - TImageList(TreeView.Images).Width-1
  1381. end;
  1382. function TfcTreeNode.AlphaSort: Boolean;
  1383. begin
  1384.   Result := CustomSort(nil, 0);
  1385. end;
  1386. function TfcTreeNode.CustomSort(SortProc: TTVCompare; Data: Longint): Boolean;
  1387. var
  1388.   SortCB: TTVSortCB;
  1389. begin
  1390.   Owner.ClearCache;
  1391.   with SortCB do
  1392.   begin
  1393.     if not Assigned(SortProc) then lpfnCompare := @DefaultTreeViewSort
  1394.     else lpfnCompare := SortProc;
  1395.     hParent := ItemId;
  1396.     lParam := Data;
  1397.   end;
  1398.   Result := TreeView_SortChildrenCB(Handle, SortCB, 0);
  1399. end;
  1400. procedure TfcTreeNode.Delete;
  1401. begin
  1402.   if not Deleting then Free;
  1403. end;
  1404. procedure TfcTreeNode.DeleteChildren;
  1405. begin
  1406.   Owner.ClearCache;
  1407.   TreeView_Expand(TreeView.Handle, ItemID, TVE_COLLAPSE or TVE_COLLAPSERESET);
  1408.   HasChildren := False;
  1409. end;
  1410. procedure TfcTreeNode.Assign(Source: TPersistent);
  1411. var
  1412.   Node: TfcTreeNode;
  1413. begin
  1414.   Owner.ClearCache;
  1415.   if Source is TfcTreeNode then
  1416.   begin
  1417.     Node := TfcTreeNode(Source);
  1418.     Text := Node.Text;
  1419.     Data := Node.Data;
  1420.     CheckboxType:= Node.CheckboxType;  { 4/26/99 - Do before assign State Index }
  1421.     StringData:= Node.StringData;
  1422.     StringData2:= Node.StringData2;
  1423.     ImageIndex := Node.ImageIndex;
  1424.     SelectedIndex := Node.SelectedIndex;
  1425.     StateIndex := Node.StateIndex;
  1426.     OverlayIndex := Node.OverlayIndex;
  1427.     Focused := Node.Focused;
  1428.     DropTarget := Node.DropTarget;
  1429.     Cut := Node.Cut;
  1430.     HasChildren := Node.HasChildren;
  1431. //    CheckboxType:= Node.CheckboxType;
  1432.     Checked:= Node.Checked;
  1433.   end
  1434.   else inherited Assign(Source);
  1435. end;
  1436. {function TfcTreeNode.IsEqual(Node: TfcTreeNode): Boolean;
  1437. begin
  1438.   Result := (Text = Node.Text) and (Data = Node.Data);
  1439. end;
  1440. }
  1441. procedure TfcTreeNode.ReadData(Stream: TStream; Info: PfcNodeInfo);
  1442. var
  1443.   I, Size, ItemCount: Integer;
  1444.   StrBuffer: PChar;
  1445.   Temp: Integer;
  1446.   UseExpanded:Boolean;
  1447. begin
  1448.   Owner.ClearCache;
  1449.   Stream.ReadBuffer(Size, SizeOf(Size));
  1450.   { 7/6/99 - Save for fcTreeCombo streaming }
  1451.   {$ifdef fcDelphi4Up}
  1452.   ReadDataSize:= Size;
  1453.   {$endif}
  1454.   { RSW - Advance if somehow size is greater than node size }
  1455.   Stream.ReadBuffer(Info^, fcmin(Size, SizeOf(Info^)));
  1456.   Temp := SizeOf(TfcNodeInfo) - (255 - Length(Info^.Text));
  1457.   { Support StringData property }
  1458.   if Info^.StringDataSize1>0 then
  1459.   begin
  1460.      StrBuffer:= StrAlloc(Info^.StringDataSize1+1);
  1461.      StrBuffer[Info^.StringDataSize1]:= #0;
  1462.      Stream.ReadBuffer(StrBuffer^, Info^.StringDataSize1);
  1463.      StringData:= StrPas(StrBuffer);
  1464.      StrDispose(StrBuffer);
  1465.   end
  1466.   else StringData:= '';
  1467.   { Support StringData property }
  1468.   if Info^.StringDataSize2>0 then
  1469.   begin
  1470.      StrBuffer:= StrAlloc(Info^.StringDataSize2+1);
  1471.      StrBuffer[Info^.StringDataSize2]:= #0;
  1472.      Stream.ReadBuffer(StrBuffer^, Info^.StringDataSize2);
  1473.      StringData2:= StrPas(StrBuffer);
  1474.      StrDispose(StrBuffer);
  1475.   end
  1476.   else StringData2:= '';
  1477.   Text := Info^.Text;
  1478.   ImageIndex := Info^.ImageIndex;
  1479.   SelectedIndex := Info^.SelectedIndex;
  1480.   StateIndex := Info^.StateIndex;
  1481.   OverlayIndex := Info^.OverlayIndex;
  1482.   Data := Info^.Data;
  1483.   ItemCount := Info^.Count;
  1484.   CheckboxType:= Info^.CheckboxType;
  1485.   Checked:= (Info^.Checked and $01)<>0;
  1486.   Grayed:= (Info^.Checked and $02)<>0;
  1487.   UseExpanded:= Info^.Expanded;
  1488.   for I := 0 to ItemCount - 1 do
  1489.     with Owner.AddChild(Self, '') do ReadData(Stream, Info);
  1490.   // 1/31/2002-PYW-Added new property to respect expanded node settings.
  1491.   if (Owner.Owner<>nil) and (Owner.Owner.StreamExpandedNode) then
  1492.      Expanded := UseExpanded;
  1493.   if TreeView.StreamVersion=1 then
  1494.      if Size > Temp then Stream.Position:= Stream.Position + (Size - Temp);
  1495. end;
  1496. Function TfcTreeNode.GetSizeOfNodeInfo: integer;
  1497. begin
  1498.   result:= SizeOf(TfcNodeInfo);
  1499. end;
  1500. procedure TfcTreeNode.WriteData(Stream: TStream; Info: PfcNodeInfo);
  1501. var
  1502.   Size, L, ItemCount: Integer;
  1503.   Node: TfcTreeNode;
  1504. begin
  1505.   L := Length(Text);
  1506.   if L > 255 then L := 255;
  1507.   Size := GetSizeOfNodeInfo + L - 255;
  1508. //  Size := SizeOf(TfcNodeInfo) + L - 255;
  1509.   FillChar(Info^, SizeOf(TfcNodeInfo), 0);
  1510.   Info^.Text := Text;
  1511.   Info^.ImageIndex := ImageIndex;
  1512.   Info^.SelectedIndex := SelectedIndex;
  1513.   Info^.OverlayIndex := OverlayIndex;
  1514.   Info^.StateIndex := StateIndex;
  1515.   Info^.Data := Data;
  1516.   ItemCount := Count;
  1517.   Info^.Count := ItemCount;
  1518.   Info^.CheckboxType:= CheckboxType;
  1519.   Info^.Checked:= ord(Checked) + $02 * Ord(Grayed);
  1520.   Info^.Expanded := Expanded;
  1521.   Info^.StringDataSize1:= length(StringData);
  1522.   Info^.StringDataSize2:= length(StringData2);
  1523.   Stream.WriteBuffer(Size, SizeOf(Size));
  1524.   Stream.WriteBuffer(Info^, Size);
  1525.   { Support StringData properties }
  1526.   if Info^.StringDataSize1>0 then begin
  1527.      Stream.WriteBuffer(PChar(StringData)^, length(StringData));
  1528.   end;
  1529.   if Info^.StringDataSize2>0 then begin
  1530.      Stream.WriteBuffer(PChar(StringData2)^, length(StringData2));
  1531.   end;
  1532.   Node := GetFirstChild;
  1533.   while Node <> nil do
  1534.   begin
  1535.     Node.WriteData(Stream, Info);
  1536.     Node := Node.GetNextSibling;
  1537.   end;
  1538. //  for I := 0 to ItemCount - 1 do Item[I].WriteData(Stream, Info);
  1539. end;
  1540. { TfcTreeNodes }
  1541. constructor TfcTreeNodes.Create(AOwner: TfcCustomTreeView);
  1542. begin
  1543.   inherited Create;
  1544.   FOwner := AOwner;
  1545. end;
  1546. destructor TfcTreeNodes.Destroy;
  1547. begin
  1548.   InDestroy:= True;
  1549.   Clear;
  1550. //  FOwner := nil;
  1551.   inherited Destroy;
  1552. end;
  1553. function TfcTreeNodes.GetCount: Integer;
  1554. begin
  1555.   if Owner.HandleAllocated then Result := TreeView_GetCount(Handle)
  1556.   else Result := 0;
  1557. end;
  1558. function TfcTreeNodes.GetHandle: HWND;
  1559. begin
  1560.   Result := Owner.Handle;
  1561. end;
  1562. procedure TfcTreeNodes.Delete(Node: TfcTreeNode);
  1563. begin
  1564.   if (Node.ItemId = nil) then
  1565.     Owner.Delete(Node);
  1566.   Node.Delete;
  1567. end;
  1568. procedure TfcTreeNodes.Clear;
  1569. var PrevNode, Node: TfcTreeNode;
  1570. begin
  1571.   ClearCache;
  1572.   if { (Owner <> nil) and ksw - prevent problem }Owner.HandleAllocated then
  1573.   begin
  1574.      if count<=0 then exit;
  1575.      Owner.SkipChangeMessages:= True;
  1576.      try
  1577.         BeginUpdate;
  1578.         Owner.Selected:= nil;
  1579.         { Clearing by scanning backwards seems to be significantly faster }
  1580.         { TreeView_DeleteAllItem's current implementation is slower than this
  1581.         { technique. Scanning forwards is also slower. }
  1582.         Node := GetFirstNode;
  1583.         Owner.TopItem:= Node;
  1584.         { Retrieve last node }
  1585.         while Node.GetNextSibling <> nil do Node:= Node.GetNextSibling;
  1586.         while Node.GetNext <> nil do Node:= Node.GetNext;
  1587.         While Node<>Nil do
  1588.         begin
  1589.             PrevNode:= Node;
  1590.             Node := Node.GetPrev;
  1591.             TreeView_DeleteItem(PrevNode.Handle, PrevNode.ItemId);
  1592.         end;
  1593.      finally
  1594.         Owner.SkipChangeMessages:= False;
  1595.         if not inDestroy then EndUpdate;
  1596.      end
  1597.   end
  1598. end;
  1599. {procedure TfcTreeNodes.Clear;
  1600. begin
  1601.   ClearCache;
  1602.   if Owner.HandleAllocated then
  1603.     TreeView_DeleteAllItems(Handle);
  1604. end;}
  1605. function TfcTreeNodes.AddChildFirst(Node: TfcTreeNode; const S: string): TfcTreeNode;
  1606. begin
  1607.   Result := AddChildObjectFirst(Node, S, nil);
  1608. end;
  1609. function TfcTreeNodes.AddChildObjectFirst(Node: TfcTreeNode; const S: string;
  1610.   Ptr: Pointer): TfcTreeNode;
  1611. begin
  1612.   Result := InternalAddObject(Node, S, Ptr, fctaAddFirst);
  1613. end;
  1614. function TfcTreeNodes.AddChild(Node: TfcTreeNode; const S: string): TfcTreeNode;
  1615. begin
  1616.   Result := AddChildObject(Node, S, nil);
  1617. end;
  1618. function TfcTreeNodes.AddChildObject(Node: TfcTreeNode; const S: string;
  1619.   Ptr: Pointer): TfcTreeNode;
  1620. begin
  1621.   Result := InternalAddObject(Node, S, Ptr, fctaAdd);
  1622. end;
  1623. function TfcTreeNodes.AddFirst(Node: TfcTreeNode; const S: string): TfcTreeNode;
  1624. begin
  1625.   Result := AddObjectFirst(Node, S, nil);
  1626. end;
  1627. function TfcTreeNodes.AddObjectFirst(Node: TfcTreeNode; const S: string;
  1628.   Ptr: Pointer): TfcTreeNode;
  1629. begin
  1630.   if Node <> nil then Node := Node.Parent;
  1631.   Result := InternalAddObject(Node, S, Ptr, fctaAddFirst);
  1632. end;
  1633. function TfcTreeNodes.Add(Node: TfcTreeNode; const S: string): TfcTreeNode;
  1634. begin
  1635.   Result := AddObject(Node, S, nil);
  1636. end;
  1637. procedure TfcTreeNodes.Repaint(Node: TfcTreeNode);
  1638. var
  1639.   R: TRect;
  1640. begin
  1641.   if FUpdateCount < 1 then
  1642.   begin
  1643.     while (Node <> nil) and not Node.IsVisible do Node := Node.Parent;
  1644.     if Node <> nil then
  1645.     begin
  1646.       R := Node.DisplayRect(False);
  1647.       InvalidateRect(Owner.Handle, @R, True);
  1648.     end;
  1649.   end;
  1650. end;
  1651. function TfcTreeNodes.AddObject(Node: TfcTreeNode; const S: string;
  1652.   Ptr: Pointer): TfcTreeNode;
  1653. begin
  1654.   if Node <> nil then Node := Node.Parent;
  1655.   Result := InternalAddObject(Node, S, Ptr, fctaAdd);
  1656. end;
  1657. function TfcTreeNodes.Insert(Node: TfcTreeNode; const S: string): TfcTreeNode;
  1658. begin
  1659.   Result := InsertObject(Node, S, nil);
  1660. end;
  1661. procedure TfcTreeNodes.AddedNode(Value: TfcTreeNode);
  1662. begin
  1663.   if Value <> nil then
  1664.   begin
  1665.     Value.HasChildren := True;
  1666.     Repaint(Value);
  1667.   end;
  1668. end;
  1669. function TfcTreeNodes.InsertObject(Node: TfcTreeNode; const S: string;
  1670.   Ptr: Pointer): TfcTreeNode;
  1671. var
  1672.   Item, ItemId: HTreeItem;
  1673.   Parent: TfcTreeNode;
  1674.   AddMode: TfcAddMode;
  1675. begin
  1676.   Result := Owner.CreateNode;
  1677.   try
  1678.     Item := nil;
  1679.     ItemId := nil;
  1680.     Parent := nil;
  1681.     AddMode := fctaInsert;
  1682.     if Node <> nil then
  1683.     begin
  1684.       Parent := Node.Parent;
  1685.       if Parent <> nil then Item := Parent.ItemId;
  1686.       Node := Node.GetPrevSibling;
  1687.       if Node <> nil then ItemId := Node.ItemId
  1688.       else AddMode := fctaAddFirst;
  1689.     end;
  1690.     Result.Data := Ptr;
  1691.     Result.Text := S;
  1692.     Item := AddItem(Item, ItemId, CreateItem(Result), AddMode);
  1693.     if Item = nil then
  1694.       raise EOutOfResources.Create(sInsertError);
  1695.     Result.FItemId := Item;
  1696.     AddedNode(Parent);
  1697.     if not Owner.MultiSelectCheckboxNeeded(Result) then
  1698.        Result.StateIndex:= -1; { 5/15/98 - Required since its not initialized to -1}
  1699.   except
  1700.     Result.Free;
  1701.     raise;
  1702.   end;
  1703. end;
  1704. function TfcTreeNodes.InternalAddObject(Node: TfcTreeNode; const S: string;
  1705.   Ptr: Pointer; AddMode: TfcAddMode): TfcTreeNode;
  1706. var
  1707.   Item: HTreeItem;
  1708. begin
  1709.   Result := Owner.CreateNode;
  1710.   try
  1711.     if Node <> nil then Item := Node.ItemId
  1712.     else Item := nil;
  1713.     Result.Data := Ptr;
  1714.     Result.Text := S;
  1715.     Item := AddItem(Item, nil, CreateItem(Result), AddMode);
  1716.     if Item = nil then
  1717.       raise EOutOfResources.Create(sInsertError);
  1718.     Result.FItemId := Item;
  1719.     AddedNode(Node);
  1720.     if not Owner.MultiSelectCheckboxNeeded(Result) then
  1721.        Result.StateIndex:= -1; { 5/15/98 - Required since its not initialized to -1}
  1722.   except
  1723.     Result.Free;
  1724.     raise;
  1725.   end;
  1726. end;
  1727. function TfcTreeNodes.CreateItem(Node: TfcTreeNode): TTVItem;
  1728. begin
  1729.   Node.FInTree := True;
  1730.   with Result do
  1731.   begin
  1732.     mask := TVIF_TEXT or TVIF_PARAM or TVIF_IMAGE or TVIF_SELECTEDIMAGE;
  1733.     lParam := Longint(Node);
  1734.     pszText := LPSTR_TEXTCALLBACK;
  1735.     iImage := I_IMAGECALLBACK;
  1736.     iSelectedImage := I_IMAGECALLBACK;
  1737.   end;
  1738. end;
  1739. function TfcTreeNodes.AddItem(Parent, Target: HTreeItem;
  1740.   const Item: TTVItem; AddMode: TfcAddMode): HTreeItem;
  1741. var
  1742.   InsertStruct: TTVInsertStruct;
  1743. begin
  1744.   ClearCache;
  1745.   with InsertStruct do
  1746.   begin
  1747.     hParent := Parent;
  1748.     case AddMode of
  1749.       fctaAddFirst:
  1750.         hInsertAfter := TVI_FIRST;
  1751.       fctaAdd:
  1752.         hInsertAfter := TVI_LAST;
  1753.       fctaInsert:
  1754.         hInsertAfter := Target;
  1755.     end;
  1756.   end;
  1757.   InsertStruct.item := Item;
  1758.   FOwner.FChangeTimer.Enabled := False;
  1759.   Result := TreeView_InsertItem(Handle, InsertStruct);
  1760. end;
  1761. function TfcTreeNodes.GetFirstNode: TfcTreeNode;
  1762. begin
  1763.   Result := GetNode(TreeView_GetRoot(Handle));
  1764. end;
  1765. function TfcTreeNodes.GetNodeFromIndex(Index: Integer): TfcTreeNode;
  1766. var
  1767.   I: Integer;
  1768. begin
  1769.   if Index < 0 then TreeViewError(sInvalidIndex);
  1770.   if (FNodeCache.CacheNode <> nil) and (Abs(FNodeCache.CacheIndex - Index) <= 1) then
  1771.   begin
  1772.     with FNodeCache do
  1773.     begin
  1774.       if Index = CacheIndex then Result := CacheNode
  1775.       else if Index < CacheIndex then Result := CacheNode.GetPrev
  1776.       else Result := CacheNode.GetNext;
  1777.     end;
  1778.   end
  1779.   else begin
  1780.     Result := GetFirstNode;
  1781.     I := Index;
  1782.     while (I <> 0) and (Result <> nil) do
  1783.     begin
  1784.       Result := Result.GetNext;
  1785.       Dec(I);
  1786.     end;
  1787.   end;
  1788.   if Result = nil then TreeViewError(sInvalidIndex);
  1789.   FNodeCache.CacheNode := Result;
  1790.   FNodeCache.CacheIndex := Index;
  1791. end;
  1792. function TfcTreeNodes.GetNode(ItemId: HTreeItem): TfcTreeNode;
  1793. var
  1794.   Item: TTVItem;
  1795. begin
  1796.   with Item do
  1797.   begin
  1798.     hItem := ItemId;
  1799.     mask := TVIF_PARAM;
  1800.   end;
  1801.   if TreeView_GetItem(Handle, Item) then Result := TfcTreeNode(Item.lParam)
  1802.   else Result := nil;
  1803. end;
  1804. procedure TfcTreeNodes.SetItem(Index: Integer; Value: TfcTreeNode);
  1805. begin
  1806.   GetNodeFromIndex(Index).Assign(Value);
  1807. end;
  1808. procedure TfcTreeNodes.BeginUpdate;
  1809. begin
  1810.   if FUpdateCount = 0 then SetUpdateState(True);
  1811.   Inc(FUpdateCount);
  1812. end;
  1813. procedure TfcTreeNodes.SetUpdateState(Updating: Boolean);
  1814. begin
  1815.   SendMessage(Handle, WM_SETREDRAW, Ord(not Updating), 0);
  1816.   if not Updating then Owner.Refresh;
  1817. end;
  1818. procedure TfcTreeNodes.EndUpdate;
  1819. begin
  1820.   Dec(FUpdateCount);
  1821.   if FUpdateCount = 0 then SetUpdateState(False);
  1822. end;
  1823. procedure TfcTreeNodes.Assign(Source: TPersistent);
  1824. var
  1825.   TreeNodes: TfcTreeNodes;
  1826.   MemStream: TMemoryStream;
  1827. begin
  1828.   ClearCache;
  1829.   { 12/1/98 (RSW) Clear treeview display }
  1830.   SendMessage(Owner.Handle, WM_ERASEBkgnd, Owner.Canvas.Handle, 0);
  1831.   if Source is TfcTreeNodes then
  1832.   begin
  1833.     Owner.FStreamVersion:= 1;
  1834.     TreeNodes := TfcTreeNodes(Source);
  1835.     Clear;
  1836.     MemStream := TMemoryStream.Create;
  1837.     try
  1838.       TreeNodes.WriteData(MemStream);
  1839.       MemStream.Position := 0;
  1840.       ReadData(MemStream);
  1841.     finally
  1842.       MemStream.Free;
  1843.     end;
  1844.   end
  1845.   else inherited Assign(Source);
  1846.   if Count>0 then Owner.Selected:= Owner.Items[0];
  1847.   Owner.invalidate;
  1848.   // RSW - 1/13/99 Make sure some node is selected as the treeview common control
  1849.   // has problems in repainting in certain cases if no control has the selection
  1850. end;
  1851. procedure TfcTreeNodes.DefineProperties(Filer: TFiler);
  1852. {
  1853.   function WriteNodes: Boolean;
  1854.   var
  1855.     I: Integer;
  1856.     Nodes: TfcTreeNodes;
  1857.   begin
  1858.     Nodes := TfcTreeNodes(Filer.Ancestor);
  1859.     if Nodes = nil then
  1860.       Result := Count > 0
  1861.     else if Nodes.Count <> Count then
  1862.       Result := True
  1863.     else
  1864.     begin
  1865.       Result := False;
  1866.       for I := 0 to Count - 1 do
  1867.       begin
  1868.         Result := not Item[I].IsEqual(Nodes[I]);
  1869.         if Result then Break;
  1870.       end
  1871.     end;
  1872.   end;
  1873. }
  1874. begin
  1875.   inherited DefineProperties(Filer);
  1876. //  Filer.DefineBinaryProperty('Data', ReadData, WriteData, WriteNodes);
  1877.   Filer.DefineProperty('StreamVersion',
  1878.      ReadStreamVersion, WriteStreamVersion, True);
  1879.   Filer.DefineBinaryProperty('Data', ReadData, WriteData, True);
  1880. end;
  1881. procedure TfcTreeNodes.ReadStreamVersion(Reader: TReader);
  1882. begin
  1883.   Owner.FStreamVersion:= Reader.ReadInteger;
  1884. end;
  1885. procedure TfcTreeNodes.WriteStreamVersion(Writer: TWriter);
  1886. begin
  1887.    Owner.FStreamVersion:= 1;
  1888.    Writer.WriteInteger(Owner.StreamVersion)
  1889. end;
  1890. procedure TfcTreeNodes.ReadData(Stream: TStream);
  1891. var
  1892.   I, Count: Integer;
  1893.   NodeInfo: TfcNodeInfo;
  1894. begin
  1895.   FillChar(NodeInfo, SizeOf(TfcNodeInfo), 0);
  1896.   Clear;
  1897.   Stream.ReadBuffer(Count, SizeOf(Count));
  1898.   for I := 0 to Count - 1 do
  1899.     Add(nil, '').ReadData(Stream, @NodeInfo);
  1900.   Owner.FStreamVersion:= 1;
  1901. end;
  1902. procedure TfcTreeNodes.WriteData(Stream: TStream);
  1903. var
  1904.   I: Integer;
  1905.   Node: TfcTreeNode;
  1906.   NodeInfo: TfcNodeInfo;
  1907. begin
  1908.   Owner.FStreamVersion:=1;
  1909.   I := 0;
  1910.   Node := GetFirstNode;
  1911.   while Node <> nil do
  1912.   begin
  1913.     Inc(I);
  1914.     Node := Node.GetNextSibling;
  1915.   end;
  1916.   Stream.WriteBuffer(I, SizeOf(I));
  1917.   Node := GetFirstNode;
  1918.   while Node <> nil do
  1919.   begin
  1920.     Node.WriteData(Stream, @NodeInfo);
  1921.     Node := Node.GetNextSibling;
  1922.   end;
  1923. end;
  1924. procedure TfcTreeNodes.ClearCache;
  1925. begin
  1926.   FNodeCache.CacheNode := nil;
  1927. end;
  1928. {type
  1929.   TTreeStrings = class(TStrings)
  1930.   private
  1931.     FOwner: TfcTreeNodes;
  1932.   protected
  1933.     function Get(Index: Integer): string; override;
  1934.     function GetBufStart(Buffer: PChar; var Level: Integer): PChar;
  1935.     function GetCount: Integer; override;
  1936.     function GetObject(Index: Integer): TObject; override;
  1937.     procedure PutObject(Index: Integer; AObject: TObject); override;
  1938.     procedure SetUpdateState(Updating: Boolean); override;
  1939.   public
  1940.     constructor Create(AOwner: TfcTreeNodes);
  1941.     function Add(const S: string): Integer; override;
  1942.     procedure Clear; override;
  1943.     procedure Delete(Index: Integer); override;
  1944.     procedure Insert(Index: Integer; const S: string); override;
  1945.     procedure LoadTreeFromStream(Stream: TStream);
  1946.     procedure SaveTreeToStream(Stream: TStream);
  1947.     property Owner: TfcTreeNodes read FOwner;
  1948.   end;
  1949. constructor TTreeStrings.Create(AOwner: TfcTreeNodes);
  1950. begin
  1951.   inherited Create;
  1952.   FOwner := AOwner;
  1953. end;
  1954. function TTreeStrings.Get(Index: Integer): string;
  1955. const
  1956.   TabChar = #9;
  1957. var
  1958.   Level, I: Integer;
  1959.   Node: TfcTreeNode;
  1960. begin
  1961.   Result := '';
  1962.   Node := Owner.GetNodeFromIndex(Index);
  1963.   Level := Node.Level;
  1964.   for I := 0 to Level - 1 do Result := Result + TabChar;
  1965.   Result := Result + Node.Text;
  1966. end;
  1967. function TTreeStrings.GetBufStart(Buffer: PChar; var Level: Integer): PChar;
  1968. begin
  1969.   Level := 0;
  1970.   while Buffer^ in [' ', #9] do
  1971.   begin
  1972.     Inc(Buffer);
  1973.     Inc(Level);
  1974.   end;
  1975.   Result := Buffer;
  1976. end;
  1977. function TTreeStrings.GetObject(Index: Integer): TObject;
  1978. begin
  1979.   Result := Owner.GetNodeFromIndex(Index).Data;
  1980. end;
  1981. procedure TTreeStrings.PutObject(Index: Integer; AObject: TObject);
  1982. begin
  1983.   Owner.GetNodeFromIndex(Index).Data := AObject;
  1984. end;
  1985. function TTreeStrings.GetCount: Integer;
  1986. begin
  1987.   Result := Owner.Count;
  1988. end;
  1989. procedure TTreeStrings.Clear;
  1990. begin
  1991.   Owner.Clear;
  1992. end;
  1993. procedure TTreeStrings.Delete(Index: Integer);
  1994. begin
  1995.   Owner.GetNodeFromIndex(Index).Delete;
  1996. end;
  1997. procedure TTreeStrings.SetUpdateState(Updating: Boolean);
  1998. begin
  1999.   SendMessage(Owner.Handle, WM_SETREDRAW, Ord(not Updating), 0);
  2000.   if not Updating then Owner.Owner.Refresh;
  2001. end;
  2002. function TTreeStrings.Add(const S: string): Integer;
  2003. var
  2004.   Level, OldLevel, I: Integer;
  2005.   NewStr: string;
  2006.   Node: TfcTreeNode;
  2007. begin
  2008.   Result := GetCount;
  2009.   if (Length(S) = 1) and (S[1] = Chr($1A)) then Exit;
  2010.   Node := nil;
  2011.   OldLevel := 0;
  2012.   NewStr := GetBufStart(PChar(S), Level);
  2013.   if Result > 0 then
  2014.   begin
  2015.     Node := Owner.GetNodeFromIndex(Result - 1);
  2016.     OldLevel := Node.Level;
  2017.   end;
  2018.   if (Level > OldLevel) or (Node = nil) then
  2019.   begin
  2020.     if Level - OldLevel > 1 then TreeViewError(sInvalidLevel);
  2021.   end
  2022.   else begin
  2023.     for I := OldLevel downto Level do
  2024.     begin
  2025.       Node := Node.Parent;
  2026.       if (Node = nil) and (I - Level > 0) then
  2027.         TreeViewError(sInvalidLevel);
  2028.     end;
  2029.   end;
  2030.   Owner.AddChild(Node, NewStr);
  2031. end;
  2032. procedure TTreeStrings.Insert(Index: Integer; const S: string);
  2033. begin
  2034.   with Owner do
  2035.     Insert(GetNodeFromIndex(Index), S);
  2036. end;
  2037. procedure TTreeStrings.LoadTreeFromStream(Stream: TStream);
  2038. var
  2039.   List: TStringList;
  2040.   ANode, NextNode: TfcTreeNode;
  2041.   ALevel, i: Integer;
  2042.   CurrStr: string;
  2043. begin
  2044.   List := TStringList.Create;
  2045.   Owner.BeginUpdate;
  2046.   try
  2047.     try
  2048.       Clear;
  2049.       List.LoadFromStream(Stream);
  2050.       ANode := nil;
  2051.       for i := 0 to List.Count - 1 do
  2052.       begin
  2053.         CurrStr := GetBufStart(PChar(List[i]), ALevel);
  2054.         if ANode = nil then
  2055.           ANode := Owner.AddChild(nil, CurrStr)
  2056.         else if ANode.Level = ALevel then
  2057.           ANode := Owner.AddChild(ANode.Parent, CurrStr)
  2058.         else if ANode.Level = (ALevel - 1) then
  2059.           ANode := Owner.AddChild(ANode, CurrStr)
  2060.         else if ANode.Level > ALevel then
  2061.         begin
  2062.           NextNode := ANode.Parent;
  2063.           while NextNode.Level > ALevel do
  2064.             NextNode := NextNode.Parent;
  2065.           ANode := Owner.AddChild(NextNode.Parent, CurrStr);
  2066.         end
  2067.         else TreeViewErrorFmt(sInvalidLevelEx, [ALevel, CurrStr]);
  2068.       end;
  2069.     finally
  2070.       Owner.EndUpdate;
  2071.       List.Free;
  2072.     end;
  2073.   except
  2074.     Owner.Owner.Invalidate;  // force repaint on exception
  2075.     raise;
  2076.   end;
  2077. end;
  2078. procedure TTreeStrings.SaveTreeToStream(Stream: TStream);
  2079. const
  2080.   TabChar = #9;
  2081.   EndOfLine = #13#10;
  2082. var
  2083.   i: Integer;
  2084.   ANode: TfcTreeNode;
  2085.   NodeStr: string;
  2086. begin
  2087.   if Count > 0 then
  2088.   begin
  2089.     ANode := Owner[0];
  2090.     while ANode <> nil do
  2091.     begin
  2092.       NodeStr := '';
  2093.       for i := 0 to ANode.Level - 1 do NodeStr := NodeStr + TabChar;
  2094.       NodeStr := NodeStr + ANode.Text + EndOfLine;
  2095.       Stream.Write(Pointer(NodeStr)^, Length(NodeStr));
  2096.       ANode := ANode.GetNext;
  2097.     end;
  2098.   end;
  2099. end;
  2100. }
  2101. { TfcCustomTreeView }
  2102. constructor TfcCustomTreeView.Create(AOwner: TComponent);
  2103. begin
  2104.   inherited Create(AOwner);
  2105.   ControlStyle := ControlStyle - [csCaptureMouse] + [csDisplayDragImage, csReflector];
  2106.   Width := 121;
  2107.   Height := 97;
  2108.   TabStop := True;
  2109.   ParentColor := False;
  2110.   NodeClass := TfcTreeNode;
  2111.   FCanvas := TfcCanvas.Create;
  2112.   TControlCanvas(FCanvas).Control := Self;
  2113.   FTreeNodes := TfcTreeNodes.Create(Self);
  2114.   FBorderStyle := bsSingle;
  2115. //  FShowButtons := True;
  2116. //  FShowRoot := True;
  2117. //  FShowLines := True;
  2118. //  FHideSelection := True;
  2119.   FOptions:= [tvoExpandOnDblClk, tvoShowButtons, tvoShowRoot,
  2120.     tvoShowLines, tvoHideSelection, tvoToolTips];
  2121.   FSaveIndent := -1;
  2122.   FChangeTimer := TTimer.Create(Self);
  2123.   FChangeTimer.Enabled := False;
  2124.   FChangeTimer.Interval := 0;
  2125.   FChangeTimer.OnTimer := OnChangeTimer;
  2126. //  FToolTips := False;
  2127.   {$Warnings Off}
  2128.   FEditInstance := MakeObjectInstance(EditWndProc);
  2129.   {$Warnings On}
  2130.   FImageChangeLink := TChangeLink.Create;
  2131.   FImageChangeLink.OnChange := ImageListChange;
  2132.   FStateChangeLink := TChangeLink.Create;
  2133.   FStateChangeLink.OnChange := ImageListChange;
  2134. //  FOptions := [tvoExpandOnDblClk];
  2135.   FMultiSelectAttributes:= TfcTVMultiSelectAttributes.create(self);
  2136.   FMultiSelectList:= TList.create;
  2137.   FBorderWidth := GetSystemMetrics(SM_CXBORDER);
  2138.   if FFixBugImageList=nil then begin
  2139.      FFixBugImageList:= TImageList.create(nil);
  2140.      FFixBugImageList.Width:= FixBugImageListSize;
  2141.      FFixBugImageList.Height:= FixBugImageListSize;
  2142.   end;
  2143.   inc(RefCount); { 2/28/00 - Always increment refcount}
  2144.   FPaintBitmap:= TBitmap.create;
  2145.   FPaintCanvas:= TfcCanvas(FPaintBitmap.Canvas);
  2146.   FLineColor:= clBtnShadow;
  2147.   FInactiveFocusColor:= clBtnFace;
  2148.   FReadOnly:= False;
  2149.   Patch:= VarArrayCreate([0, 0], varVariant);
  2150.   Patch[0]:= False;
  2151. //  Patch[1]:= 0; { Used by TfcTreeNode ReadData }
  2152. end;
  2153. destructor TfcCustomTreeView.Destroy;
  2154. begin
  2155.   FPaintBitmap.Free;
  2156.   FMultiSelectList.Free;
  2157.   FMultiSelectAttributes.Free;
  2158.   dec(RefCount);
  2159.   if RefCount<=0 then
  2160.   begin
  2161.      FFixBugImageList.Free;
  2162.      FFixBugimageList:=nil;
  2163.   end;
  2164. //  Items.Free;
  2165.   FTreeNodes.Free;
  2166.   FTreeNodes:= nil;
  2167.   FChangeTimer.Free;
  2168.   FSaveItems.Free;
  2169.   FDragImage.Free;
  2170.   FMemStream.Free;
  2171.   {$Warnings Off}
  2172.   FreeObjectInstance(FEditInstance);
  2173.   {$Warnings On}
  2174.   FImageChangeLink.Free;
  2175.   FStateChangeLink.Free;
  2176.   FCanvas.Free;
  2177.   inherited Destroy;
  2178. end;
  2179. procedure TfcCustomTreeView.CreateParams(var Params: TCreateParams);
  2180. const
  2181.   TVS_TRACKSELECT         = $0200;
  2182.   TVS_NOTOOLTIPS          = $0080;
  2183.   TVS_INFOTIP             = $0800;
  2184.   TVS_SINGLEEXPAND        = $0400;
  2185.   BorderStyles: array[TBorderStyle] of DWORD = (0, WS_BORDER);
  2186.   LineStyles: array[Boolean] of DWORD = (0, TVS_HASLINES);
  2187.   RootStyles: array[Boolean] of DWORD = (0, TVS_LINESATROOT);
  2188.   ButtonStyles: array[Boolean] of DWORD = (0, TVS_HASBUTTONS);
  2189.   EditStyles: array[Boolean] of DWORD = (TVS_EDITLABELS, 0);
  2190.   HideSelections: array[Boolean] of DWORD = (TVS_SHOWSELALWAYS, 0);
  2191.   DragStyles: array[TDragMode] of DWORD = (TVS_DISABLEDRAGDROP, 0);
  2192.   HotTrackStyles: array[Boolean] of DWORD = (0, TVS_TRACKSELECT);
  2193.   ToolTipStyles: array[Boolean] of DWORD = (TVS_NOTOOLTIPS, TVS_NOTOOLTIPS);
  2194.   AutoExpandStyles: array[Boolean] of DWORD = (0, TVS_SINGLEEXPAND);
  2195.   {$ifdef fcDelphi4Up}
  2196.   RTLStyles: array[Boolean] of DWORD = (0, TVS_RTLREADING);
  2197.   RowSelectStyles: array[Boolean] of DWORD = (0, TVS_FULLROWSELECT);
  2198.   {$endif}
  2199.   TVS_NOSCROLL = $2000;
  2200. begin
  2201.   InitCommonControl(ICC_TREEVIEW_CLASSES);
  2202.   inherited CreateParams(Params);
  2203.   CreateSubClass(Params, WC_TREEVIEW);
  2204.   with Params do
  2205.   begin
  2206.     Style := Style or LineStyles[tvoShowLines in Options] or BorderStyles[FBorderStyle] or
  2207.       RootStyles[tvoShowRoot in Options] or ButtonStyles[tvoShowButtons in Options] or
  2208.       EditStyles[not (tvoEditText in Options)] or HideSelections[not (tvoHideSelection in Options)] or
  2209.       DragStyles[DragMode] or
  2210.       ToolTipStyles[False] or // FToolTips] or
  2211.       HotTrackStyles[tvoHotTrack in Options] or
  2212.       AutoExpandStyles[FAutoExpand]
  2213.       {$ifdef fcDelphi4Up}
  2214.        or
  2215.       RTLStyles[UseRightToLeftReading]
  2216.       {$endif};
  2217.     if Ctl3D and NewStyleControls and (FBorderStyle = bsSingle) then
  2218.     begin
  2219.       Style := Style and not WS_BORDER;
  2220.       ExStyle := Params.ExStyle or WS_EX_CLIENTEDGE;
  2221.     end;
  2222.     WindowClass.style := WindowClass.style and not (CS_HREDRAW or CS_VREDRAW);
  2223.   end;
  2224.   Params.Style := Params.Style or TVS_CHECKBOXES;
  2225. end;
  2226. function TreeView_SetBkColor(hwnd: HWND; clr: COLORREF): COLORREF;
  2227. const
  2228.   TVM_SETBKCOLOR              = TV_FIRST + 29;
  2229. begin
  2230.   Result := COLORREF(SendMessage(hwnd, TVM_SETBKCOLOR, 0, LPARAM(clr)));
  2231. end;
  2232. function TreeView_SetTextColor(hwnd: HWND; clr: COLORREF): COLORREF;
  2233. const
  2234.   TVM_SETTEXTCOLOR              = TV_FIRST + 30;
  2235. begin
  2236.   Result := COLORREF(SendMessage(hwnd, TVM_SETTEXTCOLOR, 0, LPARAM(clr)));
  2237. end;
  2238. procedure TfcCustomTreeView.CreateWnd;
  2239. var
  2240.   DC: HDC;
  2241.   SaveFont: HFont;
  2242.   TextSize: TSize;
  2243. begin
  2244.   FStateChanging := False;
  2245.   inherited CreateWnd;
  2246.   TreeView_SetBkColor(Handle, ColorToRGB(Color));
  2247.   TreeView_SetTextColor(Handle, ColorToRGB(Font.Color));
  2248.   if FMemStream <> nil then
  2249.   begin
  2250.     Items.ReadData(FMemStream);
  2251.     FMemStream.Destroy;
  2252.     FMemStream := nil;
  2253.     SetTopItem(Items.GetNodeFromIndex(FSaveTopIndex));
  2254.     FSaveTopIndex := 0;
  2255.     SetSelection(Items.GetNodeFromIndex(FSaveIndex));
  2256.     FSaveIndex := 0;
  2257.   end;
  2258.   if FSaveIndent <> -1 then Indent := FSaveIndent;
  2259.   if (Images <> nil) and Images.HandleAllocated then
  2260.     SetImageList(Images.Handle, TVSIL_NORMAL);
  2261.   if (StateImages <> nil) and StateImages.HandleAllocated then
  2262.     SetImageList(StateImages.Handle, TVSIL_STATE);
  2263.   { Create StateImageList if not assigned }
  2264.   DC := GetDC(0);
  2265.   SaveFont := SelectObject(DC, Font.Handle);
  2266.   GetTextExtentPoint32(DC, 'A', 1, TextSize);
  2267.   SelectObject(DC, SaveFont);
  2268.   ReleaseDC(0, DC);
  2269.   FFixBugImageList.Width:= fcMin(TextSize.cy+2, FixBugImageListSize);
  2270.   FFixBugImageList.Width:= fcMax(FixBugImageListSize, 16); { 2/1/99}
  2271.   FFixBugImageList.Height:= FFixBugImageList.Width;
  2272.   if HandleAllocated and (StateImages=Nil) then
  2273.      TreeView_SetImageList(Handle, FFixBugImageList.Handle, TVSIL_STATE);
  2274.   { 5/5/99 - Workaround for TreeView common control problem where this property is reset }
  2275.   if not (tvoHideSelection in Options) and HandleAllocated then
  2276.      SetComCtlStyle(Self, TVS_SHOWSELALWAYS, True);
  2277. end;
  2278. procedure TfcCustomTreeView.DestroyWnd;
  2279. var
  2280.   Node: TfcTreeNode;
  2281.   parentIsFrame: boolean;
  2282. begin
  2283.   FStateChanging := True;
  2284.   {$ifdef fcDelphi5Up}
  2285.   parentIsFrame:= parent is TCustomFrame;
  2286.   {$else}
  2287.   parentIsFrame:= false;
  2288.   {$endif}
  2289.   if (Items.Count > 0) and
  2290.     { 1/5/2000 - Fix TFrame duplicate streaming problem }
  2291.      not (parentIsFrame and (csLoading in ComponentState)) then
  2292.   begin
  2293.     FMemStream := TMemoryStream.Create;
  2294.     Items.WriteData(FMemStream);
  2295.     FMemStream.Position := 0;
  2296.     Node := GetTopItem;
  2297.     if Node <> nil then FSaveTopIndex := Node.AbsoluteIndex;
  2298.     Node := Selected;
  2299.     if Node <> nil then FSaveIndex := Node.AbsoluteIndex;
  2300.   end;
  2301.   FSaveIndent := Indent;
  2302.   inherited DestroyWnd;
  2303. end;
  2304. procedure TfcCustomTreeView.EditWndProc(var Message: TMessage);
  2305. var DisplayRect: TRect;
  2306. begin
  2307.   try
  2308.     with Message do
  2309.     begin
  2310.       case Msg of
  2311.         WM_WINDOWPOSCHANGED, WM_SIZE:
  2312.           begin
  2313.             If (EditNode<>Nil) and (Images<>Nil) and (EditNode.imageindex=-2) then
  2314.             begin
  2315.               DisplayRect:= EditNode.DisplayRect(True);
  2316.               SetWindowPos(FEditHandle, 0, fcmax(DisplayRect.Left, 0),DisplayRect.Top,0,0, //sp.x + DisplayRect.Left, sp.y + DisplayRect.Top, 0, 0,
  2317.                 SWP_NOZORDER OR SWP_NOSIZE OR SWP_NOACTIVATE);
  2318.               ValidateRect(Handle, nil);
  2319. //            Message.Result:= 1;
  2320.             end
  2321.             else if (EditNode<>Nil) and (Msg=WM_SIZE) then begin
  2322.                if (Patch[0]=False) then
  2323.                   ValidateRect(Handle, nil) // RSW (4/8/99 } Prevent flicker when edit box size changes
  2324.                else Patch[0]:= False;
  2325.             end
  2326.           end;
  2327.         WM_KEYDOWN,
  2328.         WM_SYSKEYDOWN: if DoKeyDown(TWMKey(Message)) then Exit;
  2329.         WM_CHAR: if DoKeyPress(TWMKey(Message)) then Exit;
  2330.         WM_KEYUP,
  2331.         WM_SYSKEYUP: if DoKeyUp(TWMKey(Message)) then Exit;
  2332.         CN_KEYDOWN,
  2333.         CN_CHAR, CN_SYSKEYDOWN,
  2334.         CN_SYSCHAR:
  2335.           begin
  2336.             WndProc(Message);
  2337.             Exit;
  2338.           end;
  2339.       end;
  2340.       Result := CallWindowProc(FDefEditProc, FEditHandle, Msg, WParam, LParam);
  2341.     end;
  2342.   except
  2343.     Application.HandleException(Self);
  2344.   end;
  2345. end;
  2346. procedure TfcCustomTreeView.CMColorChanged(var Message: TMessage);
  2347. begin
  2348.   inherited;
  2349.   RecreateWnd;
  2350. end;
  2351. procedure TfcCustomTreeView.CMCtl3DChanged(var Message: TMessage);
  2352. begin
  2353.   inherited;
  2354.   if FBorderStyle = bsSingle then RecreateWnd;
  2355. end;
  2356. procedure TfcCustomTreeView.CMFontChanged(var Message: TMessage);
  2357. begin
  2358.   inherited;
  2359.   TreeView_SetTextColor(Handle, ColorToRGB(Font.Color));
  2360. end;
  2361. procedure TfcCustomTreeView.CMSysColorChange(var Message: TMessage);
  2362. begin
  2363.   inherited;
  2364.   if not (csLoading in ComponentState) then
  2365.   begin
  2366.     Message.Msg := WM_SYSCOLORCHANGE;
  2367.     DefaultHandler(Message);
  2368.   end;
  2369. end;
  2370. function TfcCustomTreeView.AlphaSort: Boolean;
  2371. var
  2372.   Node: TfcTreeNode;
  2373. begin
  2374.   if HandleAllocated then
  2375.   begin
  2376.     Result := CustomSort(nil, 0);
  2377.     Node := FTreeNodes.GetFirstNode;
  2378.     while Node <> nil do
  2379.     begin
  2380.       if Node.HasChildren then Node.AlphaSort;
  2381.       Node := Node.GetNext;
  2382.     end;
  2383.   end
  2384.   else
  2385.     Result := False;
  2386. end;
  2387. function TfcCustomTreeView.CustomSort(SortProc: TTVCompare; Data: Longint): Boolean;
  2388. var
  2389.   SortCB: TTVSortCB;
  2390. //  Node: TfcTreeNode;
  2391. begin
  2392.   Result := False;
  2393.   if HandleAllocated then
  2394.   begin
  2395.     with SortCB do
  2396.     begin
  2397.       if not Assigned(SortProc) then lpfnCompare := @DefaultTreeViewSort
  2398.       else lpfnCompare := SortProc;
  2399.       hParent := TVI_ROOT;
  2400.       lParam := Data;
  2401.       Result := TreeView_SortChildrenCB(Handle, SortCB, 0);
  2402.     end;
  2403. {    Node := FTreeNodes.GetFirstNode;
  2404.     while Node <> nil do
  2405.     begin
  2406.       if Node.HasChildren then Node.CustomSort(SortProc, Data);
  2407.       Node := Node.GetNext;
  2408.     end;}
  2409.     Items.ClearCache;
  2410.   end;
  2411. end;
  2412. procedure TfcCustomTreeView.SetAutoExpand(Value: Boolean);
  2413. const
  2414.   TVS_SINGLEEXPAND        = $0400;
  2415. begin
  2416.   if FAutoExpand <> Value then
  2417.   begin
  2418.     FAutoExpand := Value;
  2419.     SetComCtlStyle(Self, TVS_SINGLEEXPAND, Value);
  2420.   end;
  2421. end;
  2422. {
  2423. procedure TfcCustomTreeView.SetHotTrack(Value: Boolean);
  2424. const
  2425.   TVS_TRACKSELECT         = $0200;
  2426. begin
  2427.   if FHotTrack <> Value then
  2428.   begin
  2429.     FHotTrack := Value;
  2430.     SetComCtlStyle(Self, TVS_TRACKSELECT, Value);
  2431.   end;
  2432. end;
  2433. }
  2434. {procedure TfcCustomTreeView.SetRowSelect(Value: Boolean);
  2435. const
  2436.   TVS_FULLROWSELECT       = $1000;
  2437. begin
  2438.   if (tvoRowSelect in Options) <> Value then
  2439.   begin
  2440.     FRowSelect := Value;
  2441.     SetComCtlStyle(Self, TVS_FULLROWSELECT, Value);
  2442.   end;
  2443. end;
  2444. }
  2445. {procedure TfcCustomTreeView.SetToolTips(Value: Boolean);
  2446. const TVS_NOTOOLTIPS          = $0080;
  2447. begin
  2448.   if FToolTips <> Value then
  2449.   begin
  2450.     FToolTips := Value;
  2451.     SetComCtlStyle(Self, TVS_NOTOOLTIPS, not Value);
  2452.   end;
  2453. end;
  2454. }
  2455. procedure TfcCustomTreeView.SetSortType(Value: TfcSortType);
  2456. begin
  2457.   if SortType <> Value then
  2458.   begin
  2459.     FSortType := Value;
  2460.     if ((SortType in [fcstData, fcstBoth]) and Assigned(OnCompare)) or
  2461.       (SortType in [fcstText, fcstBoth]) then
  2462.       AlphaSort;
  2463.   end;
  2464. end;
  2465. procedure TfcCustomTreeView.SetBorderStyle(Value: TBorderStyle);
  2466. begin
  2467.   if BorderStyle <> Value then
  2468.   begin
  2469.     FBorderStyle := Value;
  2470.     RecreateWnd;
  2471.   end;
  2472. end;
  2473. procedure TfcCustomTreeView.SetDragMode(Value: TDragMode);
  2474. begin
  2475.   if Value <> DragMode then
  2476.     SetComCtlStyle(Self, TVS_DISABLEDRAGDROP, Value = dmManual);
  2477.   inherited;
  2478. end;
  2479. {
  2480. procedure TfcCustomTreeView.SetButtonStyle(Value: Boolean);
  2481. begin
  2482.   if ShowButtons <> Value then
  2483.   begin
  2484.     FShowButtons := Value;
  2485.     SetComCtlStyle(Self, TVS_HASBUTTONS, Value);
  2486.   end;
  2487. end;
  2488. }
  2489. {
  2490. procedure TfcCustomTreeView.SetLineStyle(Value: Boolean);
  2491. begin
  2492.   if ShowLines <> Value then
  2493.   begin
  2494.     FShowLines := Value;
  2495.     SetComCtlStyle(Self, TVS_HASLINES, Value);
  2496.     SetComCtlStyle(Self, TVS_HASBUTTONS, Value);
  2497.   end;
  2498. end;
  2499. }
  2500. {
  2501. procedure TfcCustomTreeView.SetRootStyle(Value: Boolean);
  2502. begin
  2503.   if ShowRoot <> Value then
  2504.   begin
  2505.     FShowRoot := Value;
  2506.   end;
  2507. end;
  2508. }
  2509. procedure TfcCustomTreeView.SetReadOnly(Value: Boolean);
  2510. begin
  2511.   if ReadOnly <> Value then
  2512.   begin
  2513.     FReadOnly := Value;
  2514.     if FReadOnly then
  2515.     begin
  2516.        if (tvoEditText in Options) then SetComCtlStyle(Self, TVS_EDITLABELS, False);
  2517.     end