home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 September / Chip_2001-09_cd1.bin / zkuste / delphi / kolekce / d123456 / DFS.ZIP / SystemControlPack.pas < prev    next >
Pascal/Delphi Source File  |  2001-06-28  |  40KB  |  1,274 lines

  1. {$I DFS.INC}                    { Defines for all Delphi Free Stuff components }
  2. {$I SYSTEMCONTROLPACK.INC}      { Defines specific to these components }
  3.  
  4. { -----------------------------------------------------------------------------}
  5. { System Control Pack v0.98.5 BETA                                             }
  6. { -----------------------------------------------------------------------------}
  7. { A set of components that allow you to emulate most of the Windows Explorer   }
  8. { behavior.  Included is a treeview, listview and combobox.  This unit         }
  9. { provides only the base classes for these components, defining how they will  }
  10. { interact with each other, mostly through abstract methods.                   }
  11. {                                                                              }
  12. { Copyright 2000, Brad Stowers.  All Rights Reserved.                          }
  13. { TdfsSystemComboBox is also copyrighted 1999, Andrew Barnes.                  }
  14. {                                                                              }
  15. { Copyright:                                                                   }
  16. { All Delphi Free Stuff (hereafter "DFS") source code is copyrighted by        }
  17. { Bradley D. Stowers (hereafter "author"), and shall remain the exclusive      }
  18. { property of the author.                                                      }
  19. {                                                                              }
  20. { Distribution Rights:                                                         }
  21. { You are granted a non-exlusive, royalty-free right to produce and distribute }
  22. { compiled binary files (executables, DLLs, etc.) that are built with any of   }
  23. { the DFS source code unless specifically stated otherwise.                    }
  24. { You are further granted permission to redistribute any of the DFS source     }
  25. { code in source code form, provided that the original archive as found on the }
  26. { DFS web site (http://www.delphifreestuff.com) is distributed unmodified. For }
  27. { example, if you create a descendant of TDFSColorButton, you must include in  }
  28. { the distribution package the colorbtn.zip file in the exact form that you    }
  29. { downloaded it from http://www.delphifreestuff.com/mine/files/colorbtn.zip.   }
  30. {                                                                              }
  31. { Restrictions:                                                                }
  32. { Without the express written consent of the author, you may not:              }
  33. {   * Distribute modified versions of any DFS source code by itself. You must  }
  34. {     include the original archive as you found it at the DFS site.            }
  35. {   * Sell or lease any portion of DFS source code. You are, of course, free   }
  36. {     to sell any of your own original code that works with, enhances, etc.    }
  37. {     DFS source code.                                                         }
  38. {   * Distribute DFS source code for profit.                                   }
  39. {                                                                              }
  40. { Warranty:                                                                    }
  41. { There is absolutely no warranty of any kind whatsoever with any of the DFS   }
  42. { source code (hereafter "software"). The software is provided to you "AS-IS", }
  43. { and all risks and losses associated with it's use are assumed by you. In no  }
  44. { event shall the author of the softare, Bradley D. Stowers, be held           }
  45. { accountable for any damages or losses that may occur from use or misuse of   }
  46. { the software.                                                                }
  47. {                                                                              }
  48. { Support:                                                                     }
  49. { Support is provided via the DFS Support Forum, which is a web-based message  }
  50. { system.  You can find it at http://www.delphifreestuff.com/discus/           }
  51. { All DFS source code is provided free of charge. As such, I can not guarantee }
  52. { any support whatsoever. While I do try to answer all questions that I        }
  53. { receive, and address all problems that are reported to me, you must          }
  54. { understand that I simply can not guarantee that this will always be so.      }
  55. {                                                                              }
  56. { Clarifications:                                                              }
  57. { If you need any further information, please feel free to contact me directly.}
  58. { This agreement can be found online at my site in the "Miscellaneous" section.}
  59. {------------------------------------------------------------------------------}
  60. { The lateset version of my components are always available on the web at:     }
  61. {   http://www.delphifreestuff.com/                                            }
  62. { See SCP.txt for notes, known issues, and revision history.                   }
  63. { -----------------------------------------------------------------------------}
  64. { Date last modified:  June 28, 2001                                           }
  65. { -----------------------------------------------------------------------------}
  66.  
  67. unit SystemControlPack;
  68.  
  69. interface
  70.  
  71. uses
  72.   Windows, Messages, Controls, Classes, StdCtrls, SysUtils,
  73.   {$IFDEF DFS_COMPILER_3_UP} ShlObj, ActiveX, {$ELSE} MyShlObj, OLE2, {$ENDIF}
  74.   ComCtrls, CommCtrl;
  75.  
  76.  
  77. const
  78.   STV_READ_DELAY_TIMER = 33;
  79.   MEMLEAK_STR = 'Memory Leak Detected.  Not all folder data was freed.';
  80.   DFS_SCP_VERSION = 'v0.98.5 Beta';
  81.   {$IFDEF DFS_COMPILER_2}
  82.     {$DEFINE DFS_SCP_BROKEN_COLOR}
  83.   {$ENDIF}
  84.   {$IFDEF DFS_DELPHI_3}
  85.     {$DEFINE DFS_SCP_BROKEN_COLOR}
  86.   {$ENDIF}
  87.   {$IFDEF DFS_SCP_BROKEN_COLOR}
  88.   TVM_SETBKCOLOR   = TV_FIRST + 29;
  89.   TVM_SETTEXTCOLOR = TV_FIRST + 30;
  90.   {$ENDIF}
  91.  
  92. type
  93.   { Common Exception Types }
  94.   ENoRootFolder    = class(Exception);
  95.   ENoEnumObjects   = class(Exception);
  96.   ENoFolderData    = class(Exception);
  97.   ENoBindFolder    = class(Exception);
  98.   ENoDesktopFolder = class(Exception);
  99.   EInvokeFailed    = class(Exception);
  100.   ENoUIObject      = class(Exception);
  101.   ELeaking         = class(Exception);
  102.  
  103.  
  104.   { This type is shared by both the tree and list view. }
  105.   TPopupMenuMethod = (
  106.      pmmNone,        // Never display a popup menu
  107.      pmmContext,     // Only use system context menu
  108.      pmmUser,        // Only use PopupMenu property
  109.      pmmContextUser  // Use context menu first, and if none use PopupMenu
  110.     );
  111.  
  112.   { This class is uses by both the tree and list view. }
  113.   // A TFolderItem instance is stored in each node's Data property.  This is
  114.   // used to populate the children of that node, show context menus, etc.
  115.   TFolderItemData = class
  116.   private
  117.     FInitialized: boolean;             // Has it been populated yet?
  118.     FSFParent: IShellFolder;           // Parent IShellFolder object
  119.     FAttributes: UINT;
  120.     FIndent: UINT;
  121.     FSelected,
  122.     FNormal: integer;
  123.     FData: pointer;
  124.     FFileSizeHigh: DWORD;
  125.     FFileSizeLow: DWORD;
  126.   protected
  127.     {$IFDEF DFS_COMPILER_4_UP}
  128.     function GetFileSize: Int64;
  129.     {$ELSE}
  130.     {$IFDEF DFS_DELPHI}
  131.     function GetFileSize: Comp;
  132.     {$ENDIF}
  133.     {$ENDIF}
  134.   public
  135.     // I made these public because a lot of function take var parameter pidls
  136.     // and you wouldn't be able to pass the properties.
  137.     FIDList,                           // Relative (to SFParent) ID List
  138.     FFQ_IDList:  PItemIDList;          // Fully Qualified ID List
  139.  
  140.     constructor Create;
  141.     destructor Destroy; override;
  142.  
  143.     function ItemHasFlag(Flag: UINT): boolean;
  144.  
  145.     property Initialized: boolean
  146.        read FInitialized write FInitialized;
  147.     property SFParent: IShellFolder
  148.        read FSFParent write FSFParent;
  149.     property IDList: PItemIDList
  150.        read FIDList write FIDList;
  151.     property FQ_IDList: PItemIDList
  152.        read FFQ_IDList write FFQ_IDList;
  153.     property Attributes: UINT
  154.        read FAttributes write FAttributes;
  155.     property Indent: UINT
  156.        read FIndent write FIndent;
  157.     property Selected: integer
  158.        read FSelected write FSelected;
  159.     property Normal: integer
  160.        read FNormal write FNormal;
  161.     property FileSizeHigh: DWORD
  162.        read FFileSizeHigh write FFileSizeHigh;
  163.     property FileSizeLow: DWORD
  164.        read FFileSizeLow write FFileSizeLow;
  165.     {$IFDEF DFS_COMPILER_4_UP}
  166.     property FileSize: Int64
  167.        read GetFileSize;
  168.     {$ELSE}
  169.     {$IFDEF DFS_DELPHI}
  170.     property FileSize: Comp
  171.        read GetFileSize;
  172.     {$ENDIF}
  173.     {$ENDIF}
  174.     // This is never used by the components.  You can use it in place of the
  175.     // Data pointer I'm taking over.  I use Node.Data in the tree, but if you
  176.     // need something similar, you can now use TFolderItemData(Node.Data).Data.
  177.     property Data: pointer
  178.        read FData write FData;
  179.   end;
  180.  
  181.   { Forward declarations }
  182.   {$IFDEF DFS_SCP_SYSCOMBOBOX}
  183.   TdfsCustomSystemComboBox = class;
  184.   {$ENDIF}
  185.  
  186.   {$IFDEF DFS_SCP_SYSLISTVIEW}
  187.   TdfsCustomSystemListView = class;
  188.   {$ENDIF}
  189.  
  190. {$IFDEF DFS_SCP_SYSTREEVIEW}
  191.   TdfsCustomSystemTreeView = class(TCustomTreeView)
  192.   private
  193.     { Variables }
  194.     FReadDelay: word;
  195.     FReadDelayTimer: UINT;
  196.     FInhibitReadDelay: boolean;
  197.     {$IFDEF DFS_SCP_SYSLISTVIEW}
  198.     FListView: TdfsCustomSystemListView;
  199.     {$ENDIF}
  200.     {$IFDEF DFS_SCP_SYSCOMBOBOX}
  201.     FComboBox: TdfsCustomSystemComboBox;
  202.     {$ENDIF}
  203.  
  204.     function AppWinHook(var Message: TMessage): boolean;
  205.     procedure HookMainWin;
  206.     { Message Handlers }
  207.     procedure CMSysColorChange(var Message: TWMSysColorChange); message
  208.        CM_SYSCOLORCHANGE;
  209.     { Property Read/Write Methods }
  210.     {$IFDEF DFS_SCP_SYSLISTVIEW}
  211.     procedure SetListView(Val: TdfsCustomSystemListView);
  212.     {$ENDIF}
  213.     {$IFDEF DFS_SCP_SYSCOMBOBOX}
  214.     procedure SetComboBox(Val: TdfsCustomSystemComboBox);
  215.     {$ENDIF}
  216.   protected
  217.     procedure DeviceChanged; virtual;
  218.     procedure TimerEvent; virtual;
  219.     { Overridden Methods }
  220.     procedure Notification(AComponent: TComponent; AOperation: TOperation);
  221.        override;
  222.     procedure Change(Node: TTreeNode); override;
  223.     {$IFDEF DFS_SCP_BROKEN_COLOR}
  224.     procedure CreateWnd; override;
  225.     {$ENDIF}
  226.  
  227.     { New Virtual Methods }
  228.     procedure SetupImageList; dynamic;
  229.     function GetValidHandle: HWND; dynamic;
  230.  
  231.     { Abstract Methods }
  232.     // Implementation must return the actual ID list.  Caller will make a copy
  233.     // of it it wants it's own.  Implementer owns this one, i.e. it's the "real
  234.     // thing".  If there isn't one, return NIL.
  235.     function GetSelectionPIDL: PItemIDList; virtual; abstract;
  236.     function GetSelectionParentFolder: IShellFolder; virtual; abstract;
  237.     // Implementation notes: IDList parameter belongs to someone else.  If
  238.     // needed by this component, a copy must be made of it.  This differs from
  239.     // the Reset method in that it does not notify linked controls of a change
  240.     // because that could result in an endless cycle of notifications. Return
  241.     // value indicates success or failure.
  242.     function LinkedReset(const ParentFolder: IShellFolder; 
  243.        const IDList: PItemIDList; ForceUpdate: boolean): boolean; dynamic; abstract;
  244.  
  245.     { New Properties }
  246.     property InhibitReadDelay: boolean
  247.        read FInhibitReadDelay write FInhibitReadDelay;
  248.     property ReadDelay: word
  249.        read FReadDelay write FReadDelay default 500;
  250.     {$IFDEF DFS_SCP_SYSLISTVIEW}
  251.     property ListView: TdfsCustomSystemListView
  252.        read FListView write SetListView;
  253.     {$ENDIF}
  254.     {$IFDEF DFS_SCP_SYSCOMBOBOX}
  255.     property ComboBox: TdfsCustomSystemComboBox
  256.        read FComboBox write SetComboBox;
  257.     {$ENDIF}
  258.  
  259.   public
  260.     { Overriden Methods }
  261.     constructor Create(AOwner: TComponent); override;
  262.     destructor Destroy; override;
  263.  
  264.     { New Public Methods }
  265.     // Descendant implementation notes:  resets the control entirely.  This
  266.     // implementatino does nothing but notify linked controls of the change.
  267.     procedure Reset; dynamic;
  268.     // Usage note:  GetSelectionPIDL and GetSelectionParentFolder must be able to
  269.     // return the new value before this method is called.
  270.     procedure NotifyLinkedControls(ForceUpdate: boolean); dynamic;
  271.     procedure LinkedControlChanged(Sender: TObject; ForceUpdate: boolean); dynamic;
  272.  
  273.     { New Properties }
  274.     property SelectionPIDL: PItemIDList
  275.        read GetSelectionPIDL;
  276.     property SelectionParentFolder: IShellFolder
  277.        read GetSelectionParentFolder;
  278.   end;
  279. {$ENDIF} // DFS_SCP_SYSTREEVIEW
  280.  
  281.  
  282. {$IFDEF DFS_SCP_SYSLISTVIEW}
  283.   {$IFDEF DFS_SLV_USE_EXTLISTVIEW}
  284.   TdfsCustomSystemListView = class(TCustomExtListView)
  285.   {$ELSE} {$IFDEF DFS_SLV_USE_ENHLISTVIEW}
  286.   TdfsCustomSystemListView = class(TCustomEnhListView)
  287.   {$ELSE}
  288.   TdfsCustomSystemListView = class(TCustomListView)
  289.   {$ENDIF} {$ENDIF}
  290.   private
  291.     { Variables }
  292.     {$IFDEF DFS_SCP_SYSTREEVIEW}
  293.     FTreeView: TdfsCustomSystemTreeView;
  294.     {$ENDIF}
  295.     {$IFDEF DFS_SCP_SYSCOMBOBOX}
  296.     FComboBox: TdfsCustomSystemComboBox;
  297.     {$ENDIF}
  298.  
  299.     function AppWinHook(var Message: TMessage): boolean;
  300.     procedure HookMainWin;
  301.     { Message Handlers }
  302.     procedure CMSysColorChange(var Message: TWMSysColorChange); message
  303.        CM_SYSCOLORCHANGE;
  304.  
  305.     { Property Read/Write Methods }
  306.     {$IFDEF DFS_SCP_SYSTREEVIEW}
  307.     procedure SetTreeView(Val: TdfsCustomSystemTreeView);
  308.     {$ENDIF}
  309.     {$IFDEF DFS_SCP_SYSCOMBOBOX}
  310.     procedure SetComboBox(Val: TdfsCustomSystemComboBox);
  311.     {$ENDIF}
  312.   protected
  313.     procedure DeviceChanged; virtual;
  314.     { Overridden Methods }
  315.     procedure Notification(AComponent: TComponent; AOperation: TOperation);
  316.        override;
  317.  
  318.     { New Virtual Methods }
  319.     procedure SetupImageList; dynamic;
  320.     function GetValidHandle: HWND; dynamic;
  321.     {$IFDEF DFS_SCP_BROKEN_COLOR}
  322.     procedure CreateWnd; override;
  323.     {$ENDIF}
  324.  
  325.     { Abstract Methods }
  326.     // Implementation must return the actual ID list.  Caller will make a copy
  327.     // of it it wants it's own.  Implementer owns this one, i.e. it's the "real
  328.     // thing".  If there isn't one, return NIL.
  329.     function GetSelectionPIDL: PItemIDList; virtual; abstract;
  330.     function GetSelectionParentFolder: IShellFolder; virtual; abstract;
  331.     // Implementation notes: IDList parameter belongs to someone else.  If
  332.     // needed by this component, a copy must be made of it.  This differs from
  333.     // the Reset method in that it does not notify linked controls of a change
  334.     // because that could result in an endless cycle of notifications. Return
  335.     // value indicates success or failure.
  336.     function LinkedReset(const ParentFolder: IShellFolder;
  337.        const IDList: PItemIDList; ForceUpdate: boolean): boolean; dynamic; abstract;
  338.  
  339.     { New Properties }
  340.     {$IFDEF DFS_SCP_SYSTREEVIEW}
  341.     property TreeView: TdfsCustomSystemTreeView
  342.        read FTreeView write SetTreeView;
  343.     {$ENDIF}
  344.     {$IFDEF DFS_SCP_SYSCOMBOBOX}
  345.     property ComboBox: TdfsCustomSystemComboBox
  346.        read FComboBox write SetComboBox;
  347.     {$ENDIF}
  348.  
  349.   public
  350.     { Overriden Methods }
  351.     constructor Create(AOwner: TComponent); override;
  352.     destructor Destroy; override;
  353.  
  354.     { New Public Methods }
  355.     // Descendant implementation notes:  resets the control entirely.  This
  356.     // implementatino does nothing but notify linked controls of the change.
  357.     procedure Reset; dynamic;
  358.     // Usage note:  GetSelectionPIDL and GetSelectionParentFolder must be able to
  359.     // return the new value before this method is called.
  360.     procedure NotifyLinkedControls(ForceUpdate: boolean); dynamic;
  361.     procedure LinkedControlChanged(Sender: TObject; ForceUpdate: boolean); dynamic;
  362.  
  363.     { New Properties }
  364.     property SelectionPIDL: PItemIDList
  365.        read GetSelectionPIDL;
  366.     property SelectionParentFolder: IShellFolder
  367.        read GetSelectionParentFolder;
  368.   end;
  369. {$ENDIF} // DFS_SCP_SYSLISTVIEW
  370.  
  371.  
  372. {$IFDEF DFS_SCP_SYSCOMBOBOX}
  373.   TdfsCustomSystemComboBox = class(TCustomComboBox)
  374.   private
  375.     { Variables }
  376.     FImages: TImageList;
  377.     {$IFDEF DFS_SCP_SYSTREEVIEW}
  378.     FTreeView: TdfsCustomSystemTreeView;
  379.     {$ENDIF}
  380.     {$IFDEF DFS_SCP_SYSLISTVIEW}
  381.     FListView: TdfsCustomSystemListView;
  382.     {$ENDIF}
  383.  
  384.     function AppWinHook(var Message: TMessage): boolean;
  385.     procedure HookMainWin;
  386.     { Message Handlers }
  387.     procedure CMSysColorChange(var Message: TWMSysColorChange); message
  388.        CM_SYSCOLORCHANGE;
  389.  
  390.     { Property Read/Write Methods }
  391.     {$IFDEF DFS_SCP_SYSTREEVIEW}
  392.     procedure SetTreeView(Val: TdfsCustomSystemTreeView);
  393.     {$ENDIF}
  394.     {$IFDEF DFS_SCP_SYSLISTVIEW}
  395.     procedure SetListView(Val: TdfsCustomSystemListView);
  396.     {$ENDIF}
  397.     procedure SetImages(const Value: TImageList);
  398.   protected
  399.     procedure DeviceChanged; virtual;
  400.     { Overridden Methods }
  401.     procedure Notification(AComponent: TComponent; AOperation: TOperation);
  402.        override;
  403.     procedure Click; override;
  404.  
  405.     { New Virtual Methods }
  406.     procedure SetupImageList; dynamic;
  407.     function GetValidHandle: HWND; dynamic;
  408.  
  409.     { Abstract Methods }
  410.     // Implementation must return the actual ID list.  Caller will make a copy
  411.     // of it it wants it's own.  Implementer owns this one, i.e. it's the "real
  412.     // thing".  If there isn't one, return NIL.
  413.     function GetSelectionPIDL: PItemIDList; virtual; abstract;
  414.     function GetSelectionParentFolder: IShellFolder; virtual; abstract;
  415.     // Implementation notes: IDList parameter belongs to someone else.  If
  416.     // needed by this component, a copy must be made of it.  This differs from
  417.     // the Reset method in that it does not notify linked controls of a change
  418.     // because that could result in an endless cycle of notifications. Return
  419.     // value indicates success or failure.
  420.     function LinkedReset(const ParentFolder: IShellFolder;
  421.        const IDList: PItemIDList; ForceUpdate: boolean): boolean; dynamic; abstract;
  422.  
  423.     { New Properties }
  424.     property Images: TImageList
  425.        read FImages write SetImages;
  426.     {$IFDEF DFS_SCP_SYSTREEVIEW}
  427.     property TreeView: TdfsCustomSystemTreeView
  428.        read FTreeView write SetTreeView;
  429.     {$ENDIF}
  430.     {$IFDEF DFS_SCP_SYSLISTVIEW}
  431.     property ListView: TdfsCustomSystemListView
  432.        read FListView write SetListView;
  433.     {$ENDIF}
  434.  
  435.   public
  436.     { Overriden Methods }
  437.     constructor Create(AOwner: TComponent); override;
  438.     destructor Destroy; override;
  439.  
  440.     { New Public Methods }
  441.     // Descendant implementation notes:  resets the control entirely.  This
  442.     // implementatino does nothing but notify linked controls of the change.
  443.     procedure Reset; dynamic;
  444.     // Usage note:  GetSelectionPIDL and GetSelectionParentFolder must be able to
  445.     // return the new value before this method is called.
  446.     procedure NotifyLinkedControls(ForceUpdate: boolean); dynamic;
  447.     procedure LinkedControlChanged(Sender: TObject; ForceUpdate: boolean); dynamic;
  448.  
  449.     { New Properties }
  450.     property SelectionPIDL: PItemIDList
  451.        read GetSelectionPIDL;
  452.     property SelectionParentFolder: IShellFolder
  453.        read GetSelectionParentFolder;
  454.  
  455.     { Modified Existing Properties }
  456.     // Leave Items public because you can't change at design-time.  Also, don't
  457.     // store the stuff in it, it's system dependent and must be built when run.
  458.     property Items stored FALSE;
  459.   end;
  460. {$ENDIF} // DFS_SCP_SYSCOMBOBOX
  461.  
  462. implementation
  463.  
  464. uses
  465.   Graphics, Forms, dialogs,
  466.   {$IFDEF DFS_DEBUG} EJHkEng, {$ENDIF}
  467.   {$IFDEF DFS_COMPILER_4_UP} ImgList, {$ENDIF}
  468.   ShellAPI, PidlHelp;
  469.  
  470.  
  471. {$IFDEF DFS_SCP_SYSTREEVIEW}
  472. var
  473.   FTimerTrees: TList;
  474.   FMainWinHookSet: boolean;
  475.   FMyComputerID: PItemIDList;
  476.  
  477. procedure TimerCallback(Wnd: HWND; Msg, TimerID: UINT; CurTime: DWORD); stdcall;
  478. var
  479.   x: integer;
  480. begin
  481.   for x := 0 to FTimerTrees.Count - 1 do
  482.     if TdfsCustomSystemTreeView(FTimerTrees[x]).FReadDelayTimer = TimerID then
  483.     begin
  484.       TdfsCustomSystemTreeView(FTimerTrees[x]).TimerEvent;
  485.       break;
  486.     end;
  487. end;
  488.  
  489. { TdfsCustomSystemTreeView }
  490.  
  491. function TdfsCustomSystemTreeView.AppWinHook(var Message: TMessage): boolean;
  492. begin
  493.   if (Message.Msg = WM_DEVICECHANGE) and ((Message.WParam = $8000) or
  494.     (Message.WParam = $8004)) then
  495.     DeviceChanged;
  496.   Result := FALSE;
  497. end;
  498.  
  499. procedure TdfsCustomSystemTreeView.Change(Node: TTreeNode);
  500. begin
  501.   inherited Change(Node);
  502.  
  503.   if (FReadDelay > 0) and (not FInhibitReadDelay) then
  504.   begin
  505.     // Delay refreshing linked.  Do it when the timer fires.
  506.     if FReadDelayTimer <> 0 then
  507.       KillTimer(0, FReadDelayTimer);
  508.     FReadDelayTimer := SetTimer(0, STV_READ_DELAY_TIMER, FReadDelay, @TimerCallback);
  509.   end else begin
  510.     // No read delay, just tell them to refresh now.
  511.     if ([csLoading] * ComponentState) = [] then
  512.       FInhibitReadDelay := FALSE;
  513.     NotifyLinkedControls(FALSE);
  514.   end;
  515. end;
  516.  
  517. procedure TdfsCustomSystemTreeView.CMSysColorChange(var Message: TWMSysColorChange);
  518. var
  519.   RealColor: TColor;
  520. begin
  521.   SetupImageList;
  522.  
  523.   inherited;
  524.  
  525.   // There is apparently a bug in the VCl that doesn't correctly reset the
  526.   // tree/list color on a system color change.  The window background color gets
  527.   // changed correctly, but the text background color doesn't.  This may be
  528.   // specific to D4, I'm not certain.
  529.   RealColor := Color;
  530.   // Change the color to something else, doesn't matter what so long as it's
  531.   // different.
  532.   if Color = clBlack then
  533.     Color := clWhite
  534.   else
  535.     Color := clBlack;
  536.   // Put back the real color
  537.   Color := RealColor;
  538. end;
  539.  
  540. constructor TdfsCustomSystemTreeView.Create(AOwner: TComponent);
  541. begin
  542.   inherited Create(AOwner);
  543.  
  544.   FTimerTrees.Add(Self);
  545.   FReadDelay := 500;
  546.   FReadDelayTimer := 0;
  547.   FInhibitReadDelay := TRUE;
  548.  
  549.   HookMainWin;
  550.  
  551.   // Initialize the image list to the system's image list
  552.   SetupImageList;
  553. end;
  554.  
  555. {$IFDEF DFS_SCP_BROKEN_COLOR}
  556. procedure TdfsCustomSystemTreeView.CreateWnd;
  557. begin
  558.   inherited;
  559.   Perform(TVM_SETBKCOLOR, 0, LPARAM(ColorToRGB(Color)));
  560.   Perform(TVM_SETTEXTCOLOR, 0, LPARAM(ColorToRGB(Font.Color)));
  561. end;
  562. {$ENDIF}
  563.  
  564. destructor TdfsCustomSystemTreeView.Destroy;
  565. begin
  566.   if FMainWinHookSet then
  567.   begin
  568.     Application.UnHookMainWindow(AppWinHook);
  569.     FMainWinHookSet := FALSE;
  570.   end;
  571.  
  572.   if FReadDelayTimer <> 0 then
  573.     KillTimer(0, FReadDelayTimer);
  574.   FTimerTrees.Remove(Self);
  575.  
  576.   inherited Destroy;
  577. end;
  578.  
  579. procedure TdfsCustomSystemTreeView.DeviceChanged;
  580. begin
  581.   // One of the drives changed.
  582.   Reset;
  583. end;
  584.  
  585. function TdfsCustomSystemTreeView.GetValidHandle: HWND;
  586. begin
  587.   if HandleAllocated then
  588.     Result := Handle
  589.   else if assigned(Parent) and Parent.HandleAllocated then
  590.     Result := Parent.Handle
  591.   else if (GetParentForm(Self) <> NIL) and
  592.      (GetParentForm(Self).HandleAllocated) then
  593.     Result := GetParentForm(Self).Handle
  594.   else if assigned(Application.MainForm) and
  595.      Application.MainForm.HandleAllocated then
  596.     Result := Application.MainForm.Handle
  597.   else
  598.     Result := 0;
  599. end;
  600.  
  601. procedure TdfsCustomSystemTreeView.HookMainWin;
  602. begin
  603.   if not FMainWinHookSet then
  604.   begin
  605.     Application.HookMainWindow(AppWinHook);
  606.     FMainWinHookSet := TRUE;
  607.   end;
  608. end;
  609.  
  610. procedure TdfsCustomSystemTreeView.LinkedControlChanged(Sender: TObject;
  611.    ForceUpdate: boolean);
  612. begin
  613.   if csDesigning in ComponentState then
  614.     exit;
  615.  
  616.   // Have to get linked's new pidl and refresh using it
  617.   {$IFDEF DFS_SCP_SYSLISTVIEW}
  618.   if (Sender = ListView) then
  619.     LinkedReset(ListView.SelectionParentFolder, ListView.SelectionPIDL,
  620.        ForceUpdate);
  621.   {$ENDIF}
  622.  
  623.   {$IFDEF DFS_SCP_SYSCOMBOBOX}
  624.   if (Sender = ComboBox) then
  625.     LinkedReset(ComboBox.SelectionParentFolder, ComboBox.SelectionPIDL,
  626.        ForceUpdate);
  627.   {$ENDIF}
  628. end;
  629.  
  630. procedure TdfsCustomSystemTreeView.Notification(AComponent: TComponent;
  631.   AOperation: TOperation);
  632. begin
  633.   inherited Notification(AComponent, AOperation);
  634.  
  635.   case AOperation of
  636.     opInsert:
  637.       begin
  638.         {$IFDEF DFS_SCP_SYSLISTVIEW}
  639.         if (AComponent is TdfsCustomSystemListView) and (FListView = NIL) then
  640.         begin
  641.           ListView := TdfsCustomSystemListView(AComponent);
  642.           ListView.TreeView := Self;
  643.         end;
  644.         {$ENDIF}
  645.  
  646.         {$IFDEF DFS_SCP_SYSCOMBOBOX}
  647.         if (AComponent is TdfsCustomSystemComboBox) and (FComboBox = NIL) then
  648.         begin
  649.           ComboBox := TdfsCustomSystemComboBox(AComponent);
  650.           ComboBox.TreeView := Self;
  651.         end;
  652.         {$ENDIF}
  653.       end;
  654.  
  655.     opRemove:
  656.       begin
  657.         {$IFDEF DFS_SCP_SYSLISTVIEW}
  658.         if AComponent = FListView then
  659.           ListView := NIL;
  660.         {$ENDIF}
  661.  
  662.         {$IFDEF DFS_SCP_SYSCOMBOBOX}
  663.         if AComponent = FComboBox then
  664.           ComboBox := NIL;
  665.         {$ENDIF}
  666.       end;
  667.   end;
  668. end;
  669.  
  670. procedure TdfsCustomSystemTreeView.NotifyLinkedControls(ForceUpdate: boolean);
  671. begin
  672.   {$IFDEF DFS_SCP_SYSLISTVIEW}
  673.   if FListView <> NIL then
  674.     ListView.LinkedControlChanged(Self, ForceUpdate);
  675.   {$ENDIF}
  676.  
  677.   {$IFDEF DFS_SCP_SYSCOMBOBOX}
  678.   if FComboBox <> NIL then
  679.     ComboBox.LinkedControlChanged(Self, ForceUpdate);
  680.   {$ENDIF}
  681. end;
  682.  
  683. procedure TdfsCustomSystemTreeView.Reset;
  684. begin
  685.   NotifyLinkedControls(FALSE);
  686. end;
  687.  
  688. {$IFDEF DFS_SCP_SYSCOMBOBOX}
  689. procedure TdfsCustomSystemTreeView.SetComboBox(Val: TdfsCustomSystemComboBox);
  690. begin
  691.   if FComboBox <> Val then
  692.   begin
  693.     FComboBox := Val;
  694.   end;
  695. end;
  696. {$ENDIF}
  697.  
  698. {$IFDEF DFS_SCP_SYSLISTVIEW}
  699. procedure TdfsCustomSystemTreeView.SetListView(Val: TdfsCustomSystemListView);
  700. begin
  701.   if FListView <> Val then
  702.   begin
  703.     FListView := Val;
  704.   end;
  705. end;
  706. {$ENDIF}
  707.  
  708. procedure TdfsCustomSystemTreeView.SetupImageList;
  709. var
  710.   SysIL: HImageList;
  711.   SFI: TSHFileInfo;
  712. begin
  713.   if Images <> NIL then
  714.     Images.Free;
  715.   // Because we are the owner, it'll get freed automatically when we do.
  716.   Images := TImageList.Create(Self);
  717.   SysIL := SHGetFileInfo('', 0, SFI, SizeOf(SFI), SHGFI_SYSICONINDEX or
  718.      SHGFI_SMALLICON);
  719.   if SysIL <> 0 then
  720.   begin
  721.     if Images.HandleAllocated then
  722.       Images.Handle := 0;
  723.     Images.Masked := TRUE;
  724. //    Images.BkColor := ImageList_GetBkColor(SysIL);
  725.     Images.BkColor := clNone;
  726.     Images.DrawingStyle := dsTransparent;
  727.     Images.Handle := SysIL;
  728.     Images.ShareImages := TRUE;  // DON'T FREE THE SYSTEM IMAGE LIST!!!!!
  729.                                  // BAD IDEA (tm)!
  730.   end;
  731. end;
  732.  
  733. procedure TdfsCustomSystemTreeView.TimerEvent;
  734. begin
  735.   KillTimer(0, FReadDelayTimer);
  736.   FReadDelayTimer := 0;
  737.   // Delay timer fired, notify linked controls
  738.   NotifyLinkedControls(FALSE);
  739. end;
  740.  
  741. {$ENDIF}
  742.  
  743.  
  744.  
  745.  
  746. {$IFDEF DFS_SCP_SYSLISTVIEW}
  747.  
  748. { TdfsCustomSystemListView }
  749.  
  750. function TdfsCustomSystemListView.AppWinHook(var Message: TMessage): boolean;
  751. begin
  752.   if (Message.Msg = WM_DEVICECHANGE) and ((Message.WParam = $8000) or
  753.     (Message.WParam = $8004)) then
  754.     DeviceChanged;
  755.   Result := FALSE;
  756. end;
  757.  
  758. procedure TdfsCustomSystemListView.CMSysColorChange(var Message: TWMSysColorChange);
  759. var
  760.   RealColor: TColor;
  761. begin
  762.   SetupImageList;
  763.   inherited;
  764.  
  765.   // There is apparently a bug in the VCl that doesn't correctly reset the
  766.   // tree/list color on a system color change.  The window background color gets
  767.   // changed correctly, but the text background color doesn't.  This may be
  768.   // specific to D4, I'm not certain.
  769.   RealColor := Color;
  770.   // Change the color to something else, doesn't matter what so long as it's
  771.   // different.
  772.   if Color = clBlack then
  773.     Color := clWhite
  774.   else
  775.     Color := clBlack;
  776.   // Put back the real color
  777.   Color := RealColor;
  778. end;
  779.  
  780.  
  781. constructor TdfsCustomSystemListView.Create(AOwner: TComponent);
  782. begin
  783.   inherited Create(AOwner);
  784.  
  785.   HookMainWin;
  786.   // Initialize the image list to the system's image list
  787.   SetupImageList;
  788. end;
  789.  
  790. {$IFDEF DFS_SCP_BROKEN_COLOR}
  791. procedure TdfsCustomSystemListView.CreateWnd;
  792. begin
  793.   inherited;
  794.   Perform(LVM_SETBKCOLOR, 0, LPARAM(ColorToRGB(Color)));
  795. end;
  796. {$ENDIF}
  797.  
  798. destructor TdfsCustomSystemListView.Destroy;
  799. begin
  800.   if FMainWinHookSet then
  801.   begin
  802.     Application.UnHookMainWindow(AppWinHook);
  803.     FMainWinHookSet := FALSE;
  804.   end;
  805.  
  806.   inherited;
  807. end;
  808.  
  809. procedure TdfsCustomSystemListView.DeviceChanged;
  810. begin
  811.   // One of the drives changed.
  812.   {$IFDEF DFS_SCP_SYSTREEVIEW}
  813.   if TreeView <> NIL then
  814.     TreeView.Reset
  815.   else
  816.   {$ENDIF}
  817.     Reset;
  818. end;
  819.  
  820. function TdfsCustomSystemListView.GetValidHandle: HWND;
  821. begin
  822.   if HandleAllocated then
  823.     Result := Handle
  824.   else if assigned(Parent) and Parent.HandleAllocated then
  825.     Result := Parent.Handle
  826.   else if (GetParentForm(Self) <> NIL) and
  827.      (GetParentForm(Self).HandleAllocated) then
  828.     Result := GetParentForm(Self).Handle
  829.   else if assigned(Application.MainForm) and
  830.      Application.MainForm.HandleAllocated then
  831.     Result := Application.MainForm.Handle
  832.   else
  833.     Result := 0;
  834. end;
  835.  
  836. procedure TdfsCustomSystemListView.HookMainWin;
  837. begin
  838.   if not FMainWinHookSet then
  839.   begin
  840.     Application.HookMainWindow(AppWinHook);
  841.     FMainWinHookSet := TRUE;
  842.   end;
  843. end;
  844.  
  845. procedure TdfsCustomSystemListView.LinkedControlChanged(Sender: TObject;
  846.    ForceUpdate: boolean);
  847. begin
  848.   if csDesigning in ComponentState then
  849.     exit;
  850.  
  851.   // Have to get linked's new pidl and refresh using it
  852.   {$IFDEF DFS_SCP_SYSTREEVIEW}
  853.   if (Sender = TreeView) then
  854.     LinkedReset(TreeView.SelectionParentFolder, TreeView.SelectionPIDL,
  855.        ForceUpdate);
  856.   {$ENDIF}
  857.  
  858.   {$IFDEF DFS_SCP_SYSCOMBOBOX}
  859.   if (Sender = ComboBox) then
  860.     LinkedReset(ComboBox.SelectionParentFolder, ComboBox.SelectionPIDL,
  861.        ForceUpdate);
  862.   {$ENDIF}
  863. end;
  864.  
  865. procedure TdfsCustomSystemListView.Notification(AComponent: TComponent;
  866.   AOperation: TOperation);
  867. begin
  868.   inherited Notification(AComponent, AOperation);
  869.  
  870.   case AOperation of
  871.     opInsert:
  872.       begin
  873.         {$IFDEF DFS_SCP_SYSTREEVIEW}
  874.         if (AComponent is TdfsCustomSystemTreeView) and (FTreeView = NIL) then
  875.         begin
  876.           TreeView := TdfsCustomSystemTreeView(AComponent);
  877.           TreeView.ListView := Self;
  878.         end;
  879.         {$ENDIF}
  880.  
  881.         {$IFDEF DFS_SCP_SYSCOMBOBOX}
  882.         if (AComponent is TdfsCustomSystemComboBox) and (FComboBox = NIL) then
  883.         begin
  884.           ComboBox := TdfsCustomSystemComboBox(AComponent);
  885.           ComboBox.ListView := Self;
  886.         end;
  887.         {$ENDIF}
  888.       end;
  889.  
  890.     opRemove:
  891.       begin
  892.         {$IFDEF DFS_SCP_SYSTREEVIEW}
  893.         if AComponent = FTreeView then
  894.           TreeView := NIL;
  895.         {$ENDIF}
  896.  
  897.         {$IFDEF DFS_SCP_SYSCOMBOBOX}
  898.         if AComponent = FComboBox then
  899.           ComboBox := NIL;
  900.         {$ENDIF}
  901.       end;
  902.   end;
  903. end;
  904.  
  905. procedure TdfsCustomSystemListView.NotifyLinkedControls(ForceUpdate: boolean);
  906. begin
  907.   {$IFDEF DFS_SCP_SYSTREEVIEW}
  908.   if FTreeView <> NIL then
  909.     TreeView.LinkedControlChanged(Self, ForceUpdate);
  910.   {$ENDIF}
  911.  
  912.   {$IFDEF DFS_SCP_SYSCOMBOBOX}
  913.   if FComboBox <> NIL then
  914.     ComboBox.LinkedControlChanged(Self, ForceUpdate);
  915.   {$ENDIF}
  916. end;
  917.  
  918. procedure TdfsCustomSystemListView.Reset;
  919. begin
  920.   NotifyLinkedControls(FALSE);
  921. end;
  922.  
  923. {$IFDEF DFS_SCP_SYSCOMBOBOX}
  924. procedure TdfsCustomSystemListView.SetComboBox(Val: TdfsCustomSystemComboBox);
  925. begin
  926.   if FComboBox <> Val then
  927.   begin
  928.     FComboBox := Val;
  929.   end;
  930. end;
  931. {$ENDIF}
  932.  
  933. {$IFDEF DFS_SCP_SYSTREEVIEW}
  934. procedure TdfsCustomSystemListView.SetTreeView(Val: TdfsCustomSystemTreeView);
  935. begin
  936.   if FTreeView <> Val then
  937.   begin
  938.     FTreeView := Val;
  939.   end;
  940. end;
  941. {$ENDIF}
  942.  
  943. procedure TdfsCustomSystemListView.SetupImageList;
  944. var
  945.   SysIL: HImageList;
  946.   SFI: TSHFileInfo;
  947. begin
  948.   if LargeImages <> NIL then
  949.     LargeImages.Free;
  950.   // Because we are the owner, it'll get freed automatically when we do.
  951.   LargeImages := TImageList.Create(Self);
  952.   SysIL := SHGetFileInfo('', 0, SFI, SizeOf(SFI), SHGFI_SYSICONINDEX or
  953.      SHGFI_LARGEICON);
  954.   if SysIL <> 0 then
  955.   begin
  956.     if LargeImages.HandleAllocated then
  957.       LargeImages.Handle := 0;
  958.     LargeImages.Masked := TRUE;
  959. //    LargeImages.BkColor := ImageList_GetBkColor(SysIL);
  960.     LargeImages.BkColor := clNone;
  961.     LargeImages.DrawingStyle := dsTransparent;
  962.     LargeImages.Handle := SysIL;
  963.     LargeImages.ShareImages := TRUE;  // DON'T FREE THE SYSTEM IMAGE LIST!!!!!
  964.                                       // BAD IDEA (tm)!
  965.   end;
  966.  
  967.   if SmallImages <> NIL then
  968.     SmallImages.Free;
  969.   // Because we are the owner, it'll get freed automatically when we do.
  970.   SmallImages := TImageList.Create(Self);
  971.   SysIL := SHGetFileInfo('', 0, SFI, SizeOf(SFI), SHGFI_SYSICONINDEX or
  972.      SHGFI_SMALLICON);
  973.   if SysIL <> 0 then
  974.   begin
  975.     if SmallImages.HandleAllocated then
  976.       SmallImages.Handle := 0;
  977.     SmallImages.Masked := TRUE;
  978. //    SmallImages.BkColor := ImageList_GetBkColor(SysIL);
  979.     SmallImages.BkColor := clNone;
  980.     SmallImages.DrawingStyle := dsTransparent;
  981.     SmallImages.Handle := SysIL;
  982.     SmallImages.ShareImages := TRUE;  // DON'T FREE THE SYSTEM IMAGE LIST!!!!!
  983.                                       // BAD IDEA (tm)!
  984.   end;
  985. end;
  986.  
  987. {$ENDIF}
  988.  
  989. { TdfsCustomSystemComboBox }
  990.  
  991. {$IFDEF DFS_SCP_SYSCOMBOBOX}
  992.  
  993. function TdfsCustomSystemComboBox.AppWinHook(var Message: TMessage): boolean;
  994. begin
  995.   if (Message.Msg = WM_DEVICECHANGE) and ((Message.WParam = $8000) or
  996.     (Message.WParam = $8004)) then
  997.     DeviceChanged;
  998.   Result := FALSE;
  999. end;
  1000.  
  1001. procedure TdfsCustomSystemComboBox.Click;
  1002. begin
  1003.   NotifyLinkedControls(FALSE);
  1004.  
  1005.   inherited Click;
  1006. end;
  1007.  
  1008. procedure TdfsCustomSystemComboBox.CMSysColorChange(var Message: TWMSysColorChange);
  1009. begin
  1010.   SetupImageList;
  1011.  
  1012.   inherited;
  1013. end;
  1014.  
  1015. constructor TdfsCustomSystemComboBox.Create(AOwner: TComponent);
  1016. begin
  1017.   inherited Create(AOwner);
  1018.  
  1019.   HookMainWin;
  1020.   // Initialize the image list to the system's image list
  1021.   SetupImageList;
  1022. end;
  1023.  
  1024. destructor TdfsCustomSystemComboBox.Destroy;
  1025. begin
  1026.   if FMainWinHookSet then
  1027.   begin
  1028.     Application.UnHookMainWindow(AppWinHook);
  1029.     FMainWinHookSet := FALSE;
  1030.   end;
  1031.  
  1032.   inherited;
  1033. end;
  1034.  
  1035. procedure TdfsCustomSystemComboBox.DeviceChanged;
  1036. begin
  1037.   // One of the drives changed.
  1038.   {$IFDEF DFS_SCP_SYSTREEVIEW}
  1039.   if TreeView <> NIL then
  1040.     TreeView.Reset
  1041.   else
  1042.   {$ENDIF}
  1043.     Reset;
  1044. end;
  1045.  
  1046. function TdfsCustomSystemComboBox.GetValidHandle: HWND;
  1047. begin
  1048.   if HandleAllocated then
  1049.     Result := Handle
  1050.   else if assigned(Parent) and Parent.HandleAllocated then
  1051.     Result := Parent.Handle
  1052.   else if (GetParentForm(Self) <> NIL) and
  1053.      (GetParentForm(Self).HandleAllocated) then
  1054.     Result := GetParentForm(Self).Handle
  1055.   else if assigned(Application.MainForm) and
  1056.      Application.MainForm.HandleAllocated then
  1057.     Result := Application.MainForm.Handle
  1058.   else
  1059.     Result := 0;
  1060. end;
  1061.  
  1062. procedure TdfsCustomSystemComboBox.HookMainWin;
  1063. begin
  1064.   if not FMainWinHookSet then
  1065.   begin
  1066.     Application.HookMainWindow(AppWinHook);
  1067.     FMainWinHookSet := TRUE;
  1068.   end;
  1069. end;
  1070.  
  1071. procedure TdfsCustomSystemComboBox.LinkedControlChanged(Sender: TObject;
  1072.    ForceUpdate: boolean);
  1073. begin
  1074.   if csDesigning in ComponentState then
  1075.     exit;
  1076.  
  1077.   // Have to get linked's new pidl and refresh using it
  1078.   {$IFDEF DFS_SCP_SYSTREEVIEW}
  1079.   if (Sender = TreeView) then
  1080.     LinkedReset(TreeView.SelectionParentFolder, TreeView.SelectionPIDL,
  1081.        ForceUpdate);
  1082.   {$ENDIF}
  1083.  
  1084.   {$IFDEF DFS_SCP_SYSLISTVIEW}
  1085.   if (Sender = ListView) then
  1086.     LinkedReset(ListView.SelectionParentFolder, ListView.SelectionPIDL,
  1087.        ForceUpdate);
  1088.   {$ENDIF}
  1089. end;
  1090.  
  1091. procedure TdfsCustomSystemComboBox.Notification(AComponent: TComponent;
  1092.   AOperation: TOperation);
  1093. begin
  1094.   inherited Notification(AComponent, AOperation);
  1095.  
  1096.   case AOperation of
  1097.     opInsert:
  1098.       begin
  1099.         {$IFDEF DFS_SCP_SYSTREEVIEW}
  1100.         if (AComponent is TdfsCustomSystemTreeView) and (FTreeView = NIL) then
  1101.         begin
  1102.           TreeView := TdfsCustomSystemTreeView(AComponent);
  1103.           TreeView.ComboBox := Self;
  1104.         end;
  1105.         {$ENDIF}
  1106.  
  1107.         {$IFDEF DFS_SCP_SYSLISTVIEW}
  1108.         if (AComponent is TdfsCustomSystemListView) and (FListView = NIL) then
  1109.         begin
  1110.           ListView := TdfsCustomSystemListView(AComponent);
  1111.           ListView.ComboBox := Self;
  1112.         end;
  1113.         {$ENDIF}
  1114.       end;
  1115.  
  1116.     opRemove:
  1117.       begin
  1118.         {$IFDEF DFS_SCP_SYSTREEVIEW}
  1119.         if AComponent = FTreeView then
  1120.           TreeView := NIL;
  1121.         {$ENDIF}
  1122.  
  1123.         {$IFDEF DFS_SCP_SYSLISTVIEW}
  1124.         if AComponent = FListView then
  1125.           ListView := NIL;
  1126.         {$ENDIF}
  1127.       end;
  1128.   end;
  1129. end;
  1130.  
  1131. procedure TdfsCustomSystemComboBox.NotifyLinkedControls(ForceUpdate: boolean);
  1132. begin
  1133.   {$IFDEF DFS_SCP_SYSLISTVIEW}
  1134.   if FListView <> NIL then
  1135.     ListView.LinkedControlChanged(Self, ForceUpdate);
  1136.   {$ENDIF}
  1137.  
  1138.   {$IFDEF DFS_SCP_SYSTREEVIEW}
  1139.   if FTreeView <> NIL then
  1140.     TreeView.LinkedControlChanged(Self, ForceUpdate);
  1141.   {$ENDIF}
  1142. end;
  1143.  
  1144. procedure TdfsCustomSystemComboBox.Reset;
  1145. begin
  1146.   NotifyLinkedControls(FALSE);
  1147. end;
  1148.  
  1149. procedure TdfsCustomSystemComboBox.SetImages(const Value: TImageList);
  1150. begin
  1151.   if FImages <> NIL then
  1152.     FImages.Free;
  1153.   // Because we are the owner, it'll get freed automatically when we do.
  1154.   FImages := TImageList.Create(Self);
  1155.   FImages.Assign(Value);
  1156. end;
  1157.  
  1158. {$IFDEF DFS_SCP_SYSLISTVIEW}
  1159. procedure TdfsCustomSystemComboBox.SetListView(Val: TdfsCustomSystemListView);
  1160. begin
  1161.   if FListView <> Val then
  1162.   begin
  1163.     FListView := Val;
  1164.   end;
  1165. end;
  1166. {$ENDIF}
  1167.  
  1168. {$IFDEF DFS_SCP_SYSTREEVIEW}
  1169. procedure TdfsCustomSystemComboBox.SetTreeView(Val: TdfsCustomSystemTreeView);
  1170. begin
  1171.   if FTreeView <> Val then
  1172.   begin
  1173.     FTreeView := Val;
  1174.   end;
  1175. end;
  1176. {$ENDIF}
  1177.  
  1178. procedure TdfsCustomSystemComboBox.SetupImageList;
  1179. var
  1180.   SysIL: HImageList;
  1181.   SFI: TSHFileInfo;
  1182. begin
  1183.   if FImages <> NIL then
  1184.     FImages.Free;
  1185.   // Because we are the owner, it'll get freed automatically when we do.
  1186.   FImages := TImageList.Create(Self);
  1187.   SysIL := SHGetFileInfo('', 0, SFI, SizeOf(SFI), SHGFI_SYSICONINDEX or
  1188.      SHGFI_SMALLICON);
  1189.   if SysIL <> 0 then
  1190.   begin
  1191.     if FImages.HandleAllocated then
  1192.       FImages.Handle := 0;
  1193.     FImages.Masked := TRUE;
  1194. //    Images.BkColor := ImageList_GetBkColor(SysIL);
  1195.     FImages.BkColor := clNone;
  1196.     FImages.DrawingStyle := dsTransparent;
  1197.     FImages.Handle := SysIL;
  1198.     FImages.ShareImages := TRUE;  // DON'T FREE THE SYSTEM IMAGE LIST!!!!!
  1199.                                  // BAD IDEA (tm)!
  1200.   end;
  1201. end;
  1202.  
  1203. {$ENDIF}
  1204.  
  1205.  
  1206. { TFolderItemData }
  1207.  
  1208. var
  1209.   NewCount: integer;
  1210.  
  1211. constructor TFolderItemData.Create;
  1212. begin
  1213.   inherited;
  1214.   inc(NewCount);
  1215. end;
  1216.  
  1217. destructor TFolderItemData.Destroy;
  1218. begin
  1219.   inherited;
  1220.   dec(NewCount);
  1221. end;
  1222.  
  1223. {$IFDEF DFS_COMPILER_4_UP}
  1224.  
  1225. function TFolderItemData.GetFileSize: Int64;
  1226. begin
  1227.   Result := (FFileSizeHigh SHR 32) + FFileSizeLow;
  1228. end;
  1229.  
  1230. {$ELSE}
  1231. {$IFDEF DFS_DELPHI}
  1232.  
  1233. function TFolderItemData.GetFileSize: Comp;
  1234. var
  1235.   LI: TLargeInteger;
  1236. begin
  1237.   LI.LowPart := FFileSizeLow;
  1238.   LI.HighPart := FFileSizeHigh;
  1239.   Result := Comp(LI);
  1240. end;
  1241.  
  1242. {$ENDIF}
  1243. {$ENDIF}
  1244.  
  1245. function TFolderItemData.ItemHasFlag(Flag: UINT): boolean;
  1246. begin
  1247.   Result := (Attributes and Flag) <> 0;
  1248. end;
  1249.  
  1250. var
  1251.   Malloc: IMalloc;
  1252.  
  1253. initialization
  1254.   NewCount := 0;
  1255.   FTimerTrees := TList.Create;
  1256.   FMainWinHookSet := FALSE;
  1257.   ShGetSpecialFolderLocation(0, CSIDL_DRIVES, FMyComputerID);
  1258. finalization
  1259.   FTimerTrees.Free;
  1260.   ShGetMalloc(Malloc);
  1261.   try
  1262.     Malloc.Free(FMyComputerID);
  1263.   finally;
  1264.     {$IFDEF DFS_COMPILER_2}
  1265.     ShellMalloc.Release;
  1266.     {$ENDIF}
  1267.   end;
  1268.   if NewCount > 0 then
  1269.     raise ELeaking.Create(MEMLEAK_STR);
  1270. end.
  1271.  
  1272.  
  1273.  
  1274.