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

  1. {$I DFS.INC}  { Standard defines for all Delphi Free Stuff components }
  2.  
  3. {.$DEFINE DFS_DEBUG}
  4. {.$DEFINE DFS_TRY_BACKGROUND_IMAGE}
  5.  
  6. {------------------------------------------------------------------------------}
  7. { TdfsExtListView v3.72                                                        }
  8. {------------------------------------------------------------------------------}
  9. { A list view control that enables access to the new style types provieded     }
  10. { by the updated list view control.  The updated list view is provided in      }
  11. { the COMCTL32.DLL file that comes with Microsoft's new internet software.     }
  12. {                                                                              }
  13. { Copyright 1998-2001, Brad Stowers.  All Rights Reserved.                     }
  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 ELV.txt for notes, known issues, and revision history.                   }
  63. {------------------------------------------------------------------------------}
  64. { Date last modified:  June 28, 2001                                           }
  65. {------------------------------------------------------------------------------}
  66.  
  67.  
  68. unit ExtListView;
  69.  
  70. interface
  71.  
  72. {$IFNDEF DFS_WIN32}
  73.   ERROR!  This unit only available for Delphi 2.0 or higher!!!
  74. {$ENDIF}
  75.  
  76. uses
  77.   Windows, Messages, Classes, Controls, ComCtrls, CommCtrl, SysUtils, Graphics,
  78. {$IFDEF DFS_COMPILER_4_UP}
  79.   ImgList,
  80. {$ENDIF}
  81.   StdCtrls, Menus, EnhListView;
  82.  
  83. const
  84.   { This shuts up C++Builder 3 about the redefiniton being different. There
  85.     seems to be no equivalent in C1.  Sorry. }
  86.   {$IFDEF DFS_CPPB_3_UP}
  87.   {$EXTERNALSYM DFS_COMPONENT_VERSION}
  88.   {$ENDIF}
  89.   DFS_COMPONENT_VERSION = 'TdfsExtListView v3.72';
  90.  
  91. // Setting a subitem image (lvxSubItemImages ExtendStyle) to -1 does not
  92. // properly clear the image for the subitem.  The current COMCTL32.DLL
  93. // implementation does not seem to store this value and instead it gets a
  94. // random value assigned to it.  The work-around that I have found is to set
  95. // the index to a value that does not exist in the image list.  To make this
  96. // a bit easier, I have declared this constant.  Assigning this value to
  97. // SubItem_ImageIndex[itemindex] will clear the image from the subitem as long
  98. // as your image list does not have more than 2,147,483,646 images in it. :)
  99. const
  100.   ELV_NO_SUBITEM_IMAGE    = MAXINT - 1;
  101.  
  102.  
  103. // C3 and D4 CommCtrl.pas have almost everything we need
  104. {$IFDEF DFS_CPPB_3_UP}
  105.   {$DEFINE DFS_C3D4COMMCTRL}
  106. {$ELSE} {$IFDEF DFS_DELPHI_4_UP}
  107.   {$DEFINE DFS_C3D4COMMCTRL}
  108. {$ENDIF} {$ENDIF}
  109.  
  110. {$IFNDEF DFS_C3D4COMMCTRL}
  111. type
  112.   TLVDispInfo = TLVDispInfoA; // Borland forgot this one in D2, D3 & C1s
  113. {$ENDIF}
  114.  
  115. {$IFNDEF DFS_C3D4COMMCTRL}
  116. const
  117.   LVIF_INDENT             = $0010;
  118.   LVIF_NORECOMPUTE        = $0800;
  119.  
  120. {.$IFDEF DFS_DELPHI_2}
  121. { These are in COMMCTRL unit
  122.   LVCF_FMT                = $0001;
  123.   LVCF_WIDTH              = $0002;
  124.   LVCF_TEXT               = $0004;
  125.   LVCF_SUBITEM            = $0008;
  126. }
  127. {.$ENDIF}
  128.   LVCF_IMAGE              = $0010;
  129.   LVCF_ORDER              = $0020;
  130.  
  131. {.$IFDEF DFS_DELPHI_2}
  132. { These are in COMMCTRL unit
  133.   LVCFMT_LEFT             = $0000;
  134.   LVCFMT_RIGHT            = $0001;
  135.   LVCFMT_CENTER           = $0002;
  136.   LVCFMT_JUSTIFYMASK      = $0003;
  137. }
  138. {.$ENDIF}
  139.   LVCFMT_IMAGE            = $0800; // Item displays an image from an image list.
  140.   LVCFMT_BITMAP_ON_RIGHT  = $1000; // Image appears to right of Text.
  141.   LVCFMT_COL_HAS_IMAGES   = $8000; // Undocumented.
  142.  
  143.   LVIS_ACTIVATING         = $0020;
  144. {$ENDIF}
  145.  
  146. type
  147.   PLVItemEx = ^TLVItemEx;
  148.   TLVItemEx = packed record
  149.     mask: UINT;
  150.     iItem: Integer;
  151.     iSubItem: Integer;
  152.     state: UINT;
  153.     stateMask: UINT;
  154.     pszText: PAnsiChar;
  155.     cchTextMax: Integer;
  156.     iImage: Integer;
  157.     lParam: LPARAM;
  158.     iIndent: integer;
  159.   end;
  160.  
  161.   PLVDispInfoEx = ^TLVDispInfoEx;
  162.   TLVDispInfoEx = packed record
  163.     hdr:   TNMHDR;
  164.     item:  TLVItemEx;
  165.   end;
  166.  
  167.   TLVColumnEx = packed record
  168.     mask: UINT;
  169.     fmt: Integer;
  170.     cx: Integer;
  171.     pszText: PAnsiChar;
  172.     cchTextMax: Integer;
  173.     iSubItem: Integer;
  174.     iImage: integer; // New
  175.     iOrder: integer; // New
  176.   end;
  177.  
  178.  
  179. // These functions already exist, and there is no way to override them, so I'll
  180. // just rename them and you can use them as best you can.
  181. function ListView_GetColumnEx(LVWnd: HWND; iCol: Integer;
  182.    var pcol: TLVColumnEx): Bool;
  183. function ListView_SetColumnEx(LVWnd: HWnd; iCol: Integer;
  184.    const pcol: TLVColumnEx): Bool;
  185. function ListView_InsertColumnEx(LVWnd: HWND; iCol: Integer;
  186.    const pcol: TLVColumnEx): Integer;
  187.  
  188.  
  189. {$IFNDEF DFS_C3D4COMMCTRL}
  190. const
  191.   LVM_GETHEADER           = LVM_FIRST + 31;
  192.  
  193. function ListView_GetHeader(LVWnd: HWnd): HWnd;
  194. {$ENDIF}
  195.  
  196.  
  197. {$IFNDEF DFS_COMPILER_3_UP}
  198. const
  199.   LVM_SETICONSPACING      = LVM_FIRST + 53;
  200.  
  201.  
  202. // -1 for cx and cy means we'll use the default (system settings)
  203. // 0 for cx or cy means use the current setting (allows you to change just one
  204. // param)
  205. function ListView_SetIconSpacing(LVWnd: HWnd; cx, cy: integer): DWORD;
  206.  
  207. const
  208.   LVS_EX_GRIDLINES             = $00000001;  // Report mode only.
  209.   LVS_EX_SUBITEMIMAGES         = $00000002;  // Report mode only.
  210.   LVS_EX_CHECKBOXES            = $00000004;
  211.   LVS_EX_TRACKSELECT           = $00000008;
  212.   LVS_EX_HEADERDRAGDROP        = $00000010;  // Report mode only.
  213.   LVS_EX_FULLROWSELECT         = $00000020;  // Report mode only.
  214.   LVS_EX_ONECLICKACTIVATE      = $00000040;
  215.   LVS_EX_TWOCLICKACTIVATE      = $00000080;
  216.  
  217.   LVM_SETEXTENDEDLISTVIEWSTYLE = LVM_FIRST + 54; // optional wParam = mask
  218.  
  219. function ListView_SetExtendedListViewStyle(LVWnd: HWnd; ExStyle: LPARAM): DWORD;
  220.  
  221. const
  222.   LVM_GETEXTENDEDLISTVIEWSTYLE = LVM_FIRST + 55;
  223.  
  224. function ListView_GetExtendedListViewStyle(LVWnd: HWnd): DWORD;
  225.  
  226. {$ENDIF}
  227.  
  228. (* These were already defined in everything...
  229. const
  230.   LVIR_BOUNDS             = 0;
  231.   LVIR_ICON               = 1;
  232.   LVIR_LABEL              = 2;
  233.   LVIR_SELECTBOUNDS       = 3;
  234. *)
  235.  
  236. {$IFDEF DFS_COMPILER_2}
  237. const
  238.   LVM_GETSUBITEMRECT      = LVM_FIRST + 56;
  239.  
  240. function ListView_GetSubItemRect(LVWnd: HWnd; ParentItem, SubItem,
  241.    Code: integer; var Rect: TRect): boolean;
  242.  
  243. const
  244.   LVM_SUBITEMHITTEST      = LVM_FIRST + 57;
  245. {$ENDIF}
  246.  
  247. {$IFNDEF DFS_C3D4COMMCTRL}
  248. const
  249.   LVS_EX_FLATSB           = $00000100;
  250.   LVS_EX_REGIONAL         = $00000200;
  251.   LVS_EX_INFOTIP          = $00000400;
  252.   LVS_EX_UNDERLINEHOT     = $00000800;
  253.   LVS_EX_UNDERLINECOLD    = $00001000;
  254.   LVS_EX_MULTIWORKAREAS   = $00002000;
  255.  
  256. // Pass the LVS_EX_* styles you want to modify in Mask and ExStyle will apply
  257. // only to those.  Others will be left in current state.  For example, if you
  258. // pass LVS_EX_FULLROWSELECT for Mask and 0 for ExStyle, the
  259. // LVS_EX_FULLROWSELECT style will be cleared, but all other styles will remain
  260. // the same.
  261. function ListView_SetExtendedListViewStyleEx(LVWnd: HWnd; Mask: DWord;
  262.    ExStyle: LPARAM): DWORD;
  263. {$ENDIF}
  264.  
  265. // Should be COMPILER not DELPHI, but can't get Builder 5 to compile it.
  266. {$IFNDEF DFS_CPPB}
  267. {$IFNDEF DFS_DELPHI_7_UP}
  268. const
  269.   LVS_EX_LABELTIP         = $00004000; // Requires ComCtl32.DLL v5.80
  270. {$ENDIF}
  271. {$ENDIF}
  272. (*
  273. {$IFNDEF DFS_COMPILER_7_UP}
  274. const
  275.   LVS_EX_LABELTIP         = $00004000; // Requires ComCtl32.DLL v5.80
  276. {$ENDIF}
  277. *)
  278.  
  279. {$IFNDEF DFS_C3D4COMMCTRL}
  280.   // C3 & D4 users don't need this because their COMMCTRL.PAS file has it right
  281.   // and they can simply use the existing TLVHitTestInfo and
  282.   // ListView_SubItemHitTest()
  283. type
  284.   PLVHitTestInfoEx = ^TLVHitTestInfoEx;
  285.   TLVHitTestInfoEx = packed record
  286.     pt: TPoint;
  287.     flags: UINT;
  288.     iItem: integer;
  289.     iSubItem: integer;
  290.   end;
  291.  
  292. function ListView_SubItemHitTestEx(LVWnd: HWnd;
  293.    var HitTestInfo: TLVHitTestInfoEx): integer;
  294. {$ENDIF}
  295.  
  296. {$IFNDEF DFS_COMPILER_3_UP}
  297. const
  298.   LVM_SETCOLUMNORDERARRAY = LVM_FIRST + 58;
  299.  
  300. function ListView_SetColumnOrderArray(LVWnd: HWnd; Count: integer;
  301.    IntArray: PIntArray): boolean;
  302.  
  303. const
  304.   LVM_GETCOLUMNORDERARRAY = LVM_FIRST + 59;
  305.  
  306. function ListView_GetColumnOrderArray(LVWnd: HWnd; Count: integer;
  307.    IntArray: PIntArray): boolean;
  308.  
  309. const
  310.   LVM_SETHOTITEM  = LVM_FIRST + 60;
  311.  
  312. function ListView_SetHotItem(LVWnd: HWnd; Item: integer): integer;
  313.  
  314. const
  315.   LVM_GETHOTITEM  = LVM_FIRST + 61;
  316.  
  317. function ListView_GetHotItem(LVWnd: HWnd): integer;
  318.  
  319. const
  320.   LVM_SETHOTCURSOR  = LVM_FIRST + 62;
  321.  
  322. function ListView_SetHotCursor(LVWnd: HWnd; Cursor: HCursor): HCursor;
  323.  
  324. const
  325.   LVM_GETHOTCURSOR  = LVM_FIRST + 63;
  326.  
  327. function ListView_GetHotCursor(LVWnd: HWnd): HCursor;
  328.  
  329. const
  330.   LVM_APPROXIMATEVIEWRECT = LVM_FIRST + 64;
  331.  
  332. function ListView_ApproximateViewRect(LVWnd: HWnd; Width, Height,
  333.    Count: integer): DWORD;
  334.  
  335. const
  336.   LVM_SETWORKAREA         = LVM_FIRST + 65;
  337.  
  338. function ListView_SetWorkArea(LVWnd: HWnd; const Rect: TRect): boolean;
  339.  
  340. function ListView_GetCheckState(LVWnd: HWnd; Index: UINT): boolean;
  341.  
  342. procedure ListView_SetCheckState(LVWnd: HWnd; Index: UINT; Checked: boolean);
  343. {$ENDIF}
  344.  
  345. {$IFNDEF DFS_C3D4COMMCTRL}
  346. const
  347.   LVSICF_NOINVALIDATEALL  = $00000001;
  348.   LVSICF_NOSCROLL         = $00000002;
  349.  
  350. procedure ListView_SetItemCountEx(LVWnd: HWnd; Items: integer; Flags: DWORD);
  351. {$ENDIF}
  352.  
  353. {$IFNDEF DFS_COMPILER_3_UP}
  354. const
  355.   // New list view style flags.
  356.   LVS_OWNERDATA                = $1000; // Specifies a "virtual" control.
  357.  
  358.   // New notification messages.
  359.   LVN_ODCACHEHINT              = LVN_FIRST-13;
  360.   LVN_ODFINDITEMA              = LVN_FIRST-52;
  361.   LVN_ODFINDITEMW              = LVN_FIRST-79;
  362.   LVN_ODFINDITEM               = LVN_ODFINDITEMA;
  363. {$ENDIF}
  364.  
  365. {$IFNDEF DFS_C3D4COMMCTRL}
  366. const
  367.   LVN_ITEMACTIVATE             = LVN_FIRST-14;
  368.   LVN_ODSTATECHANGED           = LVN_FIRST-15;
  369.   LVN_MARQUEEBEGIN             = LVN_FIRST-56;
  370. {$ENDIF}
  371.  
  372. {$IFNDEF DFS_COMPILER_3_UP}
  373. type
  374.   PNMCacheHint = ^TNMCacheHint;
  375.   TNMCacheHint = packed record
  376.     hdr:       TNMHDR;
  377.     iFrom:     integer;
  378.     iTo:       integer;
  379.   end;
  380.  
  381.   PNMFindItem = ^TNMFindItem;
  382.   TNMFindItem = packed record
  383.     hdr:       TNMHDR;
  384.     iStart:    integer;
  385.     lvif:      TLVFindInfo;
  386.   end;
  387. {$ENDIF}
  388.  
  389. type
  390.   PNMODStateChange = ^TNMODStateChange;
  391.   TNMODStateChange = packed record
  392.     hdr:       TNMHDR;
  393.     iFrom:     integer;
  394.     iTo:       integer;
  395.     uNewState: UINT;
  396.     uOldState: UINT;
  397.   end;
  398.  
  399.  
  400. {$IFNDEF DFS_C3D4COMMCTRL}
  401. const
  402.   LVM_GETSELECTIONMARK = (LVM_FIRST + 66);
  403.  
  404. function ListView_GetSelectionMark(LVWnd: HWnd): integer;
  405.  
  406. const
  407.   LVM_SETSELECTIONMARK = (LVM_FIRST + 67);
  408.  
  409. function ListView_SetSelectionMark(LVWnd: HWnd; iIndex: integer): integer;
  410.  
  411. const
  412.   LVM_SETHOVERTIME = (LVM_FIRST + 71);
  413.  
  414. function ListView_SetHoverTime(LVWnd: HWnd; dwHoverTimeMS: DWORD): DWORD;
  415.  
  416. const
  417.   LVM_GETHOVERTIME = (LVM_FIRST + 72);
  418.  
  419. function ListView_GetHoverTime(LVWnd: HWnd): DWORD;
  420.  
  421. const
  422.   LVM_SETTOOLTIPS = (LVM_FIRST + 74);
  423.  
  424. function ListView_SetToolTips(LVWnd, NewWnd: HWnd): HWnd;
  425.  
  426. const
  427.   LVM_GETTOOLTIPS = (LVM_FIRST + 78);
  428.  
  429. function ListView_GetToolTips(LVWnd: HWnd): HWnd;
  430. {$ENDIF}
  431.  
  432. type
  433.   PLVBkImageA = ^TLVBkImageA;
  434.   TLVBkImageA = packed record
  435.     ulFlags: ULONG;              // LVBKIF_*
  436.     hbm: HBITMAP;
  437.     pszImage: PChar;
  438.     cchImageMax: UINT;
  439.     xOffsetPercent: integer;
  440.     yOffsetPercent: integer;
  441.   end;
  442.  
  443.   PLVBkImageW = ^TLVBkImageW;
  444.   TLVBkImageW = packed record
  445.     ulFlags: ULONG;              // LVBKIF_*
  446.     hbm: HBITMAP;
  447.     pszImage: PWideChar;
  448.     cchImageMax: UINT;
  449.     xOffsetPercent: integer;
  450.     yOffsetPercent: integer;
  451.   end;
  452.  
  453.   PLVBkImage = PLVBkImageA;
  454.   TLVBkImage = TLVBkImageA;
  455.  
  456. {$IFNDEF DFS_C3D4COMMCTRL}
  457. const
  458.   LVBKIF_SOURCE_NONE      = $00000000;
  459.   LVBKIF_SOURCE_HBITMAP   = $00000001;
  460.   LVBKIF_SOURCE_URL       = $00000002;
  461.   LVBKIF_SOURCE_MASK      = $00000003;
  462.   LVBKIF_STYLE_NORMAL     = $00000000;
  463.   LVBKIF_STYLE_TILE       = $00000010;
  464.   LVBKIF_STYLE_MASK       = $00000010;
  465.  
  466.   LVM_SETBKIMAGEA         = (LVM_FIRST + 68);
  467.   LVM_SETBKIMAGEW         = (LVM_FIRST + 138);
  468.   LVM_GETBKIMAGEA         = (LVM_FIRST + 69);
  469.   LVM_GETBKIMAGEW         = (LVM_FIRST + 139);
  470.  
  471. const
  472.   LVM_SETBKIMAGE          = LVM_SETBKIMAGEA;
  473.  
  474. function ListView_SetBkImage(LVWnd: HWnd; plvbki: PLVBkImage): BOOL;
  475.  
  476. const
  477.   LVM_GETBKIMAGE          = LVM_GETBKIMAGEA;
  478.  
  479. function ListView_GetBkImage(LVWnd: HWnd; plvbki: PLVBkImage): BOOL;
  480.  
  481. const
  482.   LVN_HOTTRACK            = (LVN_FIRST-21);
  483. {$ENDIF}
  484.  
  485. type
  486.   PNMLVGetInfoTipA = ^TNMLVGetInfoTipA;
  487.   TNMLVGetInfoTipA = packed record
  488.     hdr: TNMHDR;
  489.     dwFlags: DWORD;
  490.     pszText: PChar;
  491.     cchTextMax: integer;
  492.     iItem: integer;
  493.     iSubItem: integer;
  494.     lParam: LPARAM;
  495.   end;
  496.  
  497.   PNMLVGetInfoTipW = ^TNMLVGetInfoTipW;
  498.   TNMLVGetInfoTipW = packed record
  499.     hdr: TNMHDR;
  500.     dwFlags: DWORD;
  501.     pszText: PWideChar;
  502.     cchTextMax: integer;
  503.     iItem: integer;
  504.     iSubItem: integer;
  505.     lParam: LPARAM;
  506.   end;
  507.  
  508.   PNMLVGetInfoTip = PNMLVGetInfoTipA;
  509.   TNMLVGetInfoTip = TNMLVGetInfoTipA;
  510.  
  511. {$IFNDEF DFS_C3D4COMMCTRL}
  512. // NMLVGETINFOTIPA.dwFlag values
  513. const
  514.   LVGIT_UNFOLDED          = $0001;
  515.  
  516.   LVN_GETINFOTIPA         = (LVN_FIRST-57);
  517.   LVN_GETINFOTIPW         = (LVN_FIRST-58);
  518.   LVN_GETINFOTIP          = LVN_GETINFOTIPA;
  519. {$ENDIF}
  520.  
  521. type
  522.   EELVException = class(Exception);
  523.   EELVOldComCtl = class(EELVException);
  524.  
  525.   // New extended style flags converted to set format (RPM = Report Mode Only).
  526.   //  lvxGridlines: Adds grid lines to seperate items and columns. RPM
  527.   //  lvxSubItemImages: Allows images to be displayed for subitems. RPM
  528.   //  lvxCheckboxes: Adds checkboxes to items.  Checked items are stored
  529.   //      internally as selected items.
  530.   //  lvxTrackSelect: Tracks the mouse and highlights the item it currently
  531.   //      positioned over by changing it's color.  If mouse is left over an
  532.   //      item for a brief period of time, it will be automatically selected.
  533.   //  lvxHeaderDragDrop: Allows headers to be dragged to new positions and
  534.   //      dropped, allowing users to reorder column information.
  535.   //  lvxFullRowSelect: Allows user to click anywhere on an item to select it,
  536.   //      highlighting the entire length of the item.  Without this style,
  537.   //      users must click inside the Text of column 0.  It is only useful in
  538.   //      vsReport view style.
  539.   //  lvxOneClickActivate: Sends an LVN_ITEMACTIVATE notification message to
  540.   //      the parent when the user clicks an item.
  541.   //  lvxTwoClickActivate: Sends an LVN_ITEMACTIVATE notification message to
  542.   //      the parent when the user double clicks an item.
  543.   //  lvxFlatScrollBar: Enables flat scroll bars in the list view.
  544.   //  lvxInfoTip: Enables the OnInfoTip event that allows notification and/or
  545.   //      modification of a tooltip before it is displayed.  Only allowed for
  546.   //      vsIcon ViewStyle.
  547.   //  lvxUnderlineHot: Causes hot items to be displayed with underlined Text.
  548.   //      This style is ignored if lvxOneClickActivate or lvxTwoClickActivate
  549.   //      is not set.
  550.   //  lvxUnderlineCold: Causes nonhot items to be displayed with underlined
  551.   //      Text. This style is ignored if lvxOneClickActivate is not set.
  552.   //  lvxLabelTip: If a partially hidden label in any list view mode lacks
  553.   //      tooltip text, the list view control will unfold the label. If this
  554.   //      style is not set, the list view control will unfold partly hidden
  555.   //      labels only for the large icon mode.  Requires ComCtl32.dll v5.80. 
  556.   TLVExtendedStyle = (lvxGridLines, lvxSubItemImages, lvxCheckboxes,
  557.      lvxTrackSelect, lvxHeaderDragDrop, lvxFullRowSelect, lvxOneClickActivate,
  558.      lvxTwoClickActivate, lvxFlatScrollBar, lvxInfoTip, lvxUnderlineHot,
  559.      lvxUnderlineCold, lvxLabelTip);
  560.  
  561.   // A set of the new style bits.
  562.   TLVExtendedStyles = set of TLVExtendedStyle;
  563.  
  564.   TLVItemCountFlag = (lvsicfNoInvalidateAll, lvsicfNoScroll);
  565.   TLVItemCountFlags = set of TLVItemCountFlag;
  566.  
  567.   TLVVMMaskItem = (lvifText, lvifImage, lvifParam, lvifState, lvifIndent);
  568.   TLVVMMaskItems = set of TLVVMMaskItem;
  569.   TLVVMStateMaskItem = (lvisCut, lvisDropHighlighted, lvisFocused, lvisSelected,
  570.      lvisOverlayMask);
  571.   TLVVMStateMaskItems = set of TLVVMStateMaskItem;
  572.  
  573.   TColumnImageAlign = (ciaLeftOfText, ciaRightOfText);
  574.  
  575.   TLVItemCheckedEvent = procedure (Sender: TObject; ItemIndex: integer;
  576.     Checked: boolean) of object;
  577.   TLVMarqueeBeginEvent = procedure(Sender: TObject;
  578.      var CanBegin: boolean) of object;
  579.   TLVItemActivateEvent = TNotifyEvent;
  580.   TLVInfoTipEvent = procedure(Sender: TObject; ItemIndex, SubItemIndex: integer;
  581.      Current: string; var Additional: string) of object;
  582.   TLVHotTrackEvent = procedure(Sender: TObject; var ItemIndex: integer;
  583.      SubItemIndex: integer; Location: TPoint;
  584.      var AllowSelect: boolean) of object;
  585.   TLVVMGetItemInfoEvent = procedure(Sender: TObject; Item, SubItem: integer;
  586.      var Mask: TLVVMMaskItems; var Image: integer; var OverlayImage,
  587.      StateImage: word; var Param: LPARAM; var State: UINT; var StateMask: UINT;
  588.      var Indent: integer; var Text: string) of object;
  589.   TLVVMCacheHintEvent = procedure(Sender: TObject;
  590.      var HintInfo: TNMCacheHint) of object;
  591.   TLVVMFindItemEvent = procedure(Sender: TObject; var FindInfo: TNMFindItem;
  592.      var Found: integer) of object;
  593.   TLVVMStateChangedEvent = procedure(Sender: TObject;
  594.      var StateInfo: TNMODStateChange) of object;
  595.   TLVVMCaptionEditedEvent = procedure (Sender: TObject; Item: integer;
  596.     Canceled: boolean; const Text: string) of object;
  597.   {$IFNDEF DFS_COMPILER_4_UP}
  598.   TLVSubItemImageEvent = procedure(Sender: TObject; Item: TListItem; SubItem: Integer;
  599.     var ImageIndex: Integer) of object;
  600.   {$ENDIF}
  601.  
  602.  
  603.   TCustomExtListView = class; { forward declaration }
  604.  
  605.  
  606. {$IFDEF DFS_TRY_BACKGROUND_IMAGE}
  607.   // Class for BackgroundImage property
  608.   TELVBackgroundImage = class(TPersistent)
  609.   private
  610.     FOwningListView: TCustomExtListView;
  611.     FFilename: string;
  612.     FBrushBmp: TBitmap;
  613.     FTile: boolean;
  614.     FXOffsetPercent: integer;
  615.     FYOffsetPercent: integer;
  616.   protected
  617.     procedure SetFilename(const Val: string);
  618.     procedure SetTile(Val: boolean);
  619.     procedure SetXOffsetPercent(Val: integer);
  620.     procedure SetYOffsetPercent(Val: integer);
  621.  
  622.     procedure ApplyToListView; virtual;
  623.   public
  624.     constructor Create(AOwner: TCustomExtListView); virtual;
  625.     destructor Destroy; override;
  626.     procedure Assign(Source: TPersistent); override;
  627.   published
  628.     property Filename: string
  629.        read FFilename
  630.        write SetFilename;
  631.     property Tile: boolean
  632.        read FTile
  633.        write SetTile
  634.        default FALSE;
  635.     property XOffsetPercent: integer
  636.        read FXOffsetPercent
  637.        write SetXOffsetPercent
  638.        default 0;
  639.     property YOffsetPercent: integer
  640.        read FYOffsetPercent
  641.        write SetYOffsetPercent
  642.        default 0;
  643.   end;
  644. {$ENDIF}
  645.  
  646.  
  647.   // Class for saved settings
  648.   TdfsExtLVSaveSettings = class(TdfsEnhLVSaveSettings)
  649.   private
  650.     FSaveColumnOrder: boolean;
  651.   public
  652.     constructor Create; override;
  653.     procedure StoreColumnOrder(ColCount: integer;
  654.        const IntArray: array of integer);
  655.     procedure ReadColumnOrder(ColCount: integer;
  656.        var IntArray: array of integer);
  657.   published
  658.     property SaveColumnOrder: boolean
  659.        read FSaveColumnOrder
  660.        write FSaveColumnOrder
  661.        default TRUE;
  662.   end;
  663.  
  664.  
  665.   TdfsExtListColumn = class(TCollectionItem)
  666.   private
  667.     FSmallImageIndex: Integer;
  668.     FImageAlignment : TColumnImageAlign;
  669.     FAllowResize: boolean;
  670.     procedure DoChange;
  671.     procedure SetSmallImageIndex(Value: Integer);
  672.     procedure SetImageAlignment(Value: TColumnImageAlign);
  673.   public
  674.     constructor Create(Collection: TCollection); override;
  675.     destructor Destroy; override;
  676.     procedure Assign(Source: TPersistent); override;
  677.   published
  678.     property ImageIndex: integer
  679.        read FSmallImageIndex
  680.        write SetSmallImageIndex
  681.        default -1;
  682.     property ImageAlignment: TColumnImageAlign
  683.        read FImageAlignment
  684.        write SetImageAlignment
  685.        default ciaRightOfText;
  686.     property AllowResize: boolean
  687.        read FAllowResize
  688.        write FAllowResize
  689.        default TRUE;
  690.   end;
  691.  
  692.   TdfsExtListColumns = class(TCollection)
  693.   private
  694.     FListView: TCustomExtListView;
  695.     function GetItem(Index: Integer): TdfsExtListColumn;
  696.     procedure SetItem(Index: Integer; Value: TdfsExtListColumn);
  697.   protected
  698.     function GetOwner: TPersistent; {$IFDEF DFS_COMPILER_3_UP} override; {$ENDIF}
  699.     procedure Update(Item: TCollectionItem); override;
  700.   public
  701.     constructor Create(AListView: TCustomExtListView);
  702.     procedure Assign(Source: TPersistent); override;
  703.     function Add: TdfsExtListColumn;
  704.     procedure Refresh;
  705.     property ListView: TCustomExtListView
  706.        read FListView;
  707.     property Items[Index: Integer]: TdfsExtListColumn
  708.        read GetItem
  709.        write SetItem;
  710.        default;
  711.   end;
  712.  
  713.   // The new class.
  714.   TCustomExtListView = class(TCustomEnhListView)
  715.   private
  716.     FExtendedStyles: TLVExtendedStyles;
  717.     FColumnOrder: PIntArray;
  718.     FColumnOrderCount: integer;
  719.     FColumnsFormat: TdfsExtListColumns;
  720.     FVirtualMode: boolean;
  721.     FSaveSettings: TdfsExtLVSaveSettings;
  722.     FColumnsFormatChangeLink: TChangeLink;
  723.     FSelectionMark: integer;
  724.     FHoverTime: Longint;
  725.     FRequireComCtlUpdate: boolean;
  726. {$IFDEF DFS_TRY_BACKGROUND_IMAGE}
  727.     FBackgroundImage: TELVBackgroundImage;
  728. {$ENDIF}
  729.     FItemCountEx: integer;
  730.     FItemCountExFlags: TLVItemCountFlags;
  731.     FRecreateStream: TMemoryStream;
  732. {$IFDEF DFS_COMPILER_4_UP}
  733.     FInhibitFeedData: boolean;
  734. {$ENDIF}
  735.     FChecked: boolean;
  736.     FCheckedListItemIndex: integer;
  737.  
  738.     FOnItemChecked: TLVItemCheckedEvent;
  739.     FOnMarqueeBegin: TLVMarqueeBeginEvent;
  740.     FOnItemActivate: TLVItemActivateEvent;
  741.     FOnHotTrack: TLVHotTrackEvent;
  742.     FOnInfoTip: TLVInfoTipEvent;
  743.     FOnVMGetItemInfo: TLVVMGetItemInfoEvent;
  744.     FOnVMCacheHint: TLVVMCacheHintEvent;
  745.     FOnVMFindItem: TLVVMFindItemEvent;
  746.     FOnVMStateChanged: TLVVMStateChangedEvent;
  747.     FOnVMCaptionEdited: TLVVMCaptionEditedEvent;
  748.  
  749.     // Function to convert from our set type to expected API value.
  750.     function SetValueToAPIValue(Styles: TLVExtendedStyles): LPARAM;
  751.     function SetValueFromAPIValue(Styles: DWORD): TLVExtendedStyles;
  752.  
  753.     procedure ColumnHeaderImagesChange(Sender: TObject);
  754.  
  755.     procedure CNNotify(var Message: TWMNotify); message CN_NOTIFY;
  756.     procedure WMNotify(var Message: TWMNotify); message WM_NOTIFY;
  757.     function GetItemIndent(Index: integer): Integer;
  758.     procedure SetItemIndent(Index: integer; Value: Integer);
  759. {$IFDEF DFS_COMPILER_4_UP}
  760.     procedure FeedOwnerDataMode(Sender: TObject; Item: TListItem);
  761. {$ENDIF}
  762.   protected
  763.     // Property method for setting styles.
  764.     procedure SetExtendedStyles(Val: TLVExtendedStyles);
  765.     function GetExtendedStyles: TLVExtendedStyles;
  766.     function GetHeaderHandle: HWnd;
  767.     function GetSubItemRect(Item, SubItem: integer; Index: integer): TRect;
  768.     procedure SetHotItem(Val: integer);
  769.     function GetHotItem: integer;
  770.     procedure SetHotCursor(const Val: HCursor);
  771.     function GetHotCursor: HCursor;
  772.     procedure SetWorkArea(Rect: TRect);
  773.     procedure SetCheckState(Index: integer; Checked: boolean);
  774.     function GetCheckState(Index: integer): boolean;
  775.     procedure SetVirtualMode(Val: boolean);
  776.     procedure SetColumnsFormat(Value: TdfsExtListColumns);
  777.     function GetSubItemImageIndex(Item, SubItem: integer): integer;
  778.     procedure SetSubItemImageIndex(Item, SubItem, Value: integer);
  779.     function GetSelectionMark: integer;
  780.     procedure SetSelectionMark(Val: integer);
  781.     function GetHoverTime: Longint;
  782.     procedure SetHoverTime(Val: Longint);
  783.     procedure SetRequireComCtlUpdate(Value: boolean);
  784. {$IFDEF DFS_TRY_BACKGROUND_IMAGE}
  785.     procedure SetBackgroundImage(Value: TELVBackgroundImage);
  786. {$ENDIF}
  787.     function GetStateImages: {$IFDEF DFS_COMPILER_4_UP} TCustomImageList; {$ELSE} TImageList; {$ENDIF}
  788.     procedure SetStateImages(Value: {$IFDEF DFS_COMPILER_4_UP} TCustomImageList {$ELSE} TImageList {$ENDIF});
  789.     function GetSmallImages: {$IFDEF DFS_COMPILER_4_UP} TCustomImageList; {$ELSE} TImageList; {$ENDIF}
  790.     procedure SetSmallImages(Value: {$IFDEF DFS_COMPILER_4_UP} TCustomImageList {$ELSE} TImageList {$ENDIF});
  791.     function GetShowSortArrows: boolean;
  792.     procedure SetShowSortArrows(Value: boolean);
  793.     function GetVersion: string; override;
  794.     function GetSubItemText(Index, SubItem: integer): string; override;
  795.     function ActualColumnIndex(Index: integer): integer; override;
  796.     function GetActualColumn(Index: integer): TListColumn; override;
  797.     procedure DestroyWnd; override;
  798.     procedure RestoreChecks;
  799.     procedure SaveChecks;
  800.     procedure MeasureItem(var Height: UINT); override;
  801.     procedure DrawItem(var Canvas: TCanvas; Index: Integer; Rect: TRect;
  802.        State: TOwnerDrawState; var DefaultDrawing,
  803.        FullRowSelect: boolean); override;
  804.     procedure DrawSubItem(Index, SubItem: Integer; Rect: TRect;
  805.        State: TOwnerDrawState; var DefaultDrawing: boolean); override;
  806.     procedure DefaultDrawHeader(var Canvas: TCanvas; Index: Integer;
  807.        var Rect: TRect; Selected: boolean); override;
  808.     procedure CreateParams(var Params: TCreateParams); override;
  809.     procedure CreateWnd; override;
  810.     procedure Loaded; override;
  811.     procedure DefaultDrawItem(Index: Integer; Rect: TRect;
  812.        State: TOwnerDrawState; FullRowSelect: boolean); override;
  813.     procedure DefaultDrawSubItem(Index, SubItem: integer; Rect: TRect;
  814.        State: TOwnerDrawState); override;
  815.     // Event method handlers -- fire the events if they exist.
  816.     procedure ItemChecked(ItemIndex: integer; Checked: boolean); virtual;
  817.     function MarqueeBegin: boolean; virtual;
  818.     procedure ItemActivate; virtual;
  819.     function HotTrack(var Item: TNMListView): boolean; virtual;
  820.     procedure GetInfoTip(InfoTip: PNMLVGetInfoTip); virtual;
  821.  
  822.     procedure VMGetDispInfo(var ItemInfo: TLVItemEx); virtual;
  823.     procedure VMCacheHint(var HintInfo: TNMCacheHint); virtual;
  824.     function VMFindItem(var FindInfo: TNMFindItem): integer; virtual;
  825.     procedure VMStateChanged(var StateInfo: TNMODStateChange); virtual;
  826.     procedure VMCaptionEdited(Item: integer; Canceled: boolean; const Text: string);
  827.  
  828.     // These should be redeclared as PUBLIC as needed.
  829.     property HeaderHandle: HWnd
  830.        read GetHeaderHandle;
  831.     property SubItem_BoundsRect[Item: integer; SubItem: integer]: TRect
  832.        index LVIR_BOUNDS
  833.        read GetSubItemRect;
  834.     property SubItem_IconRect[Item: integer; SubItem: integer]: TRect
  835.        index LVIR_ICON
  836.        read GetSubItemRect;
  837.     property SubItem_LabelRect[Item: integer; SubItem: integer]: TRect
  838.        index LVIR_LABEL
  839.        read GetSubItemRect;
  840.     property SubItem_SelectBoundsRect[Item: integer; SubItem: integer]: TRect
  841.        index LVIR_SELECTBOUNDS
  842.        read GetSubItemRect;
  843.     property HotItem: integer
  844.        read GetHotItem
  845.        write SetHotItem;
  846.     property HotCursor: HCursor
  847.        read GetHotCursor
  848.        write SetHotCursor;
  849.     property WorkArea: TRect
  850.        write SetWorkArea;
  851.     property IsChecked[Index: integer]: boolean
  852.        read GetCheckState
  853.        write SetCheckState;
  854.     property SubItem_ImageIndex[Item: integer; SubItem: integer]: integer
  855.        read GetSubItemImageIndex
  856.        write SetSubItemImageIndex;
  857.     property SelectionMark: integer
  858.        read GetSelectionMark
  859.        write SetSelectionMark;
  860.     property ItemIndent[Index: integer]: integer
  861.        read GetItemIndent
  862.        write SetItemIndent;
  863.  
  864.     // These should be redeclared as PUBLIC or PUBLISHED as needed
  865.     property ExtendedStyles: TLVExtendedStyles
  866.        read GetExtendedStyles
  867.        write SetExtendedStyles
  868.        default [lvxInfoTip];
  869.     property VirtualMode: boolean
  870.        read FVirtualMode
  871.        write SetVirtualMode
  872.        default FALSE;
  873.     property HoverTime: Longint
  874.        read GetHoverTime
  875.        write SetHoverTime
  876.        default -1;
  877.     property RequireComCtlUpdate: boolean
  878.        read FRequireComCtlUpdate
  879.        write SetRequireComCtlUpdate
  880.        default FALSE;
  881. {$IFDEF DFS_TRY_BACKGROUND_IMAGE}
  882.     property BackgroundImage: TELVBackgroundImage
  883.        read FBackgroundImage
  884.        write SetBackgroundImage;
  885. {$ENDIF}
  886.  
  887.     // Autosave settings property.
  888.     property SaveSettings: TdfsExtLVSaveSettings
  889.        read FSaveSettings
  890.        write FSaveSettings;
  891.  
  892.     property ColumnsFormat: TdfsExtListColumns
  893.        read FColumnsFormat
  894.        write SetColumnsFormat;
  895.  
  896.     // Events
  897.     property OnItemChecked: TLVItemCheckedEvent
  898.        read FOnItemChecked
  899.        write FOnItemChecked;
  900.     property OnMarqueeBegin: TLVMarqueeBeginEvent
  901.        read FOnMarqueeBegin
  902.        write FOnMarqueeBegin;
  903.     property OnItemActivate: TLVItemActivateEvent
  904.        read FOnItemActivate
  905.        write FOnItemActivate;
  906.     property OnHotTrack: TLVHotTrackEvent
  907.        read FOnHotTrack
  908.        write FOnHotTrack;
  909.     property OnInfoTip: TLVInfoTipEvent
  910.        read FOnInfoTip
  911.        write FOnInfoTip;
  912.     property OnVMGetItemInfo: TLVVMGetItemInfoEvent
  913.        read FOnVMGetItemInfo
  914.        write FOnVMGetItemInfo;
  915.     property OnVMCacheHint: TLVVMCacheHintEvent
  916.        read FOnVMCacheHint
  917.        write FOnVMCacheHint;
  918.     property OnVMFindItem: TLVVMFindItemEvent
  919.        read FOnVMFindItem
  920.        write FOnVMFindItem;
  921.     property OnVMStateChanged: TLVVMStateChangedEvent
  922.        read FOnVMStateChanged
  923.        write FOnVMStateChanged;
  924.     property OnVMCaptionEdited: TLVVMCaptionEditedEvent
  925.        read FOnVMCaptionEdited
  926.        write FOnVMCaptionEdited;
  927.     property ShowSortArrows: boolean
  928.        read GetShowSortArrows
  929.        write SetShowSortArrows
  930.        stored TRUE
  931.        default FALSE;
  932.     // Redeclare so we can reset checkboxes.
  933.     property StateImages: {$IFDEF DFS_COMPILER_4_UP} TCustomImageList {$ELSE} TImageList {$ENDIF}
  934.        read GetStateImages
  935.        write SetStateImages;
  936.     // Redeclare so we can know when it changes and hook into it.
  937.     property SmallImages: {$IFDEF DFS_COMPILER_4_UP} TCustomImageList {$ELSE} TImageList {$ENDIF}
  938.        read GetSmallImages
  939.        write SetSmallImages;
  940.   public
  941.     constructor Create(AOwner: TComponent); override;
  942.     destructor Destroy; override;
  943.  
  944.     // Force reset of column image information
  945.     procedure UpdateColumnsImages;
  946.     procedure UpdateColumnImage(Index: integer);
  947.  
  948.     procedure SetIconSpacing(X, Y: integer);
  949.     function GetSubItemAt(X, Y: integer): string;
  950.     procedure SetColumnOrder(Count: integer; const IntArray: array of integer);
  951.     function GetColumnOrder(Count: integer;
  952.        var IntArray: array of integer): boolean;
  953.     function ApproximateViewRect(Count: integer;
  954.        const Proposed: TPoint): TPoint;
  955.     procedure SetItemCountEx(Count: integer; Flags: TLVItemCountFlags);
  956.     function StoreSettings: boolean; override;
  957.     function WriteSettings: boolean; override;
  958.     function LoadSettings: boolean; override;
  959.     function ReadSettings: boolean; override;
  960.     function CheckComCtlVersion(MajorHi, MajorLo,
  961.        MinorHi, MinorLo: word): boolean;
  962.  
  963.     procedure ELV_EditCaption(Item: integer);
  964.     function ELV_GetNextItem(StartItem: integer; Direction: TSearchDirection;
  965.        States: TItemStates): integer;
  966.     procedure ELV_SetItemState(Index: integer; States: TItemStates;
  967.        Setting: boolean);
  968.   end;
  969.  
  970.   TdfsExtListView = class(TCustomExtListView)
  971.   public
  972.     property LastColumnClicked;
  973.     property CurrentColumnWidth;
  974.     property HeaderHandle;
  975.     property SubItem_BoundsRect;
  976.     property SubItem_IconRect;
  977.     property SubItem_LabelRect;
  978.     property SubItem_SelectBoundsRect;
  979.     property HotItem;
  980.     property HotCursor;
  981.     property WorkArea;
  982.     property IsChecked;
  983.     property SubItem_ImageIndex;
  984.     property SelectionMark;
  985.     property ItemIndent;
  986.     property CurrentSortAscending;
  987.   published
  988.     property Columns;
  989.     property ColumnSearch;
  990.     property HideSelection;
  991.     property ExtendedStyles;
  992.     property VirtualMode;
  993.     property HoverTime;
  994.     property RequireComCtlUpdate;
  995. {$IFDEF BACKGROUND_FIXED}
  996.     property BackgroundImage;
  997. {$ENDIF}
  998.     property NoColumnResize;
  999.     property SaveSettings;
  1000.     property ColumnsFormat;
  1001.     // New Events
  1002.     property OnItemChecked;
  1003.     property OnMarqueeBegin;
  1004.     property OnItemActivate;
  1005.     property OnHotTrack;
  1006.     property OnInfoTip;
  1007.     property OnVMGetItemInfo;
  1008.     property OnVMCacheHint;
  1009.     property OnVMFindItem;
  1010.     property OnVMStateChanged;
  1011.     property OnVMCaptionEdited;
  1012.     property ShowSortArrows;
  1013.  
  1014.  
  1015.     // Publish inherited protected properties
  1016.     property AutoColumnSort;
  1017.     property AutoSortStyle;
  1018.     property AutoResort;
  1019.     property AutoSortAscending;
  1020.     property ReverseSortArrows;
  1021.     property Style;
  1022.  
  1023.     property OnDrawHeader;
  1024.     property OnMeasureItem;
  1025.     property OnDrawItem;
  1026.     property OnDrawSubItem;
  1027.     property OnAfterDefaultDrawItem;
  1028.     property OnSortItems;
  1029.     property OnSortBegin;
  1030.     property OnSortFinished;
  1031.     property OnEditCanceled;
  1032.  
  1033.  
  1034.     property Align;
  1035. {$IFDEF DFS_COMPILER_4_UP}
  1036.     property Anchors;
  1037.     property BiDiMode;
  1038. {$ENDIF}
  1039.     property BorderStyle;
  1040. {$IFDEF DFS_COMPILER_4_UP}
  1041.     property BorderWidth;
  1042. {$ENDIF}
  1043.     property Color;
  1044.     property ColumnClick;
  1045. {$IFDEF DFS_COMPILER_4_UP}
  1046.     property Constraints;
  1047. {$ENDIF}
  1048.     property OnClick;
  1049.     property OnDblClick;
  1050.     property Ctl3D;
  1051.     property DragMode;
  1052. {$IFDEF DFS_COMPILER_4_UP}
  1053.     property DragKind;
  1054. {$ENDIF}
  1055.     property ReadOnly
  1056.        default False;
  1057.     property Enabled;
  1058.     property Font;
  1059.     property IconOptions;
  1060.     property Items;
  1061.     property AllocBy;
  1062.     property MultiSelect;
  1063.     property OnChange;
  1064.     property OnChanging;
  1065.     property OnColumnClick;
  1066.     property OnDeletion;
  1067.     property OnEdited;
  1068.     property OnEditing;
  1069. {$IFDEF DFS_COMPILER_4_UP}
  1070.     property OnEndDock;
  1071. {$ENDIF}
  1072.     property OnEnter;
  1073.     property OnExit;
  1074.     property OnInsert;
  1075.     property OnDragDrop;
  1076.     property OnDragOver;
  1077.     property DragCursor;
  1078.     property OnStartDrag;
  1079.     property OnEndDrag;
  1080.     property OnGetImageIndex;
  1081. {$IFDEF DFS_COMPILER_5_UP}
  1082.     property OnGetSubItemImage;
  1083. {$ENDIF}
  1084.     property OnMouseDown;
  1085.     property OnMouseMove;
  1086.     property OnMouseUp;
  1087. {$IFDEF DFS_COMPILER_4_UP}
  1088.     property OnResize;
  1089.     property OnSelectItem;
  1090.     property OnStartDock;
  1091. {$ENDIF}
  1092.     property ParentColor
  1093.        default False;
  1094.     property ParentFont;
  1095.     property ParentShowHint;
  1096. {$IFDEF DFS_COMPILER_4_UP}
  1097.     property ParentBiDiMode;
  1098. {$ENDIF}
  1099.     property ShowHint;
  1100.     property PopupMenu;
  1101.     property ShowColumnHeaders;
  1102.     property TabOrder;
  1103.     property TabStop
  1104.        default True;
  1105.     property ViewStyle;
  1106.     property Visible;
  1107.     property OnKeyDown;
  1108.     property OnKeyPress;
  1109.     property OnKeyUp;
  1110.     property LargeImages;
  1111.     property SmallImages;
  1112.     property StateImages;
  1113.   end;
  1114.  
  1115.  
  1116. { You may find this function useful in install programs and such.  Example of
  1117.   usage is:
  1118.      if not CheckDLLVersion('COMCTL32.DLL', 4, 70, 0, 0) then ....
  1119.   which returns TRUE if COMCTL32.DLL is version 4.70.0.0 or higher. }
  1120. function CheckDLLVersion(const DLLName: string; MajorHi, MajorLo,
  1121.    MinorHi, MinorLo: word): boolean;
  1122.  
  1123.  
  1124. implementation
  1125.  
  1126. uses
  1127. {$IFDEF DFS_COMPILER_3_UP}
  1128.   ActiveX,
  1129. {$ELSE}
  1130.   OLE2, ExtColEd,
  1131. {$ENDIF}
  1132.   Registry;
  1133.  
  1134.  
  1135. function ListView_GetColumnEx(LVWnd: HWND; iCol: Integer;
  1136.    var pcol: TLVColumnEx): bool;
  1137. begin
  1138.   Result := bool(SendMessage(LVWnd, LVM_GETCOLUMN, iCol, LPARAM(@pcol)));
  1139. end;
  1140.  
  1141. function ListView_SetColumnEx(LVWnd: HWnd; iCol: Integer;
  1142.    const pcol: TLVColumnEx): Bool;
  1143. begin
  1144.   Result := bool(SendMessage(LVWnd, LVM_SETCOLUMN, iCol, Longint(@pcol)));
  1145. end;
  1146.  
  1147. function ListView_InsertColumnEx(LVWnd: HWND; iCol: Integer;
  1148.                                  const pcol: TLVColumnEx): Integer;
  1149. begin
  1150.   Result := SendMessage(LVWnd, LVM_INSERTCOLUMN, iCol, Longint(@pcol));
  1151. end;
  1152.  
  1153. function ListView_GetHeader(LVWnd: HWnd): HWnd;
  1154. begin
  1155.   Result := HWnd(SendMessage(LVWnd, LVM_GETHEADER, 0, 0));
  1156. end;
  1157.  
  1158. function ListView_SetIconSpacing(LVWnd: HWnd; cx, cy: integer): DWORD;
  1159. begin
  1160.   Result := SendMessage(LVWnd, LVM_SETICONSPACING, 0, MAKELONG(cx,cy));
  1161. end;
  1162.  
  1163. function ListView_SetExtendedListViewStyle(LVWnd: HWnd; ExStyle: LPARAM): DWORD;
  1164. begin
  1165.   Result := SendMessage(LVWnd, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, ExStyle);
  1166. end;
  1167.  
  1168. function ListView_GetExtendedListViewStyle(LVWnd: HWnd): DWORD;
  1169. begin
  1170.   Result := SendMessage(LVWnd, LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);
  1171. end;
  1172.  
  1173. function ListView_GetSubItemRect(LVWnd: HWnd; ParentItem, SubItem,
  1174.    Code: integer; var Rect: TRect): boolean;
  1175. begin
  1176.   Rect.Top := SubItem;
  1177.   Rect.Left := Code;
  1178.   Result := (SendMessage(LVWnd, LVM_GETSUBITEMRECT, ParentItem,
  1179.      LPARAM(@Rect)) <> 0);
  1180. end;
  1181.  
  1182. {$IFNDEF DFS_C3D4COMMCTRL}
  1183.   // C3 & D4 users don't need this because their COMMCTRL.PAS file has it right
  1184.   // and they can simply use the existing TLVHitTestInfo and
  1185.   // ListView_SubItemHitTest
  1186. function ListView_SubItemHitTestEx(LVWnd: HWnd;
  1187.    var HitTestInfo: TLVHitTestInfoEx): integer;
  1188. begin
  1189.   Result := SendMessage(LVWnd, LVM_SUBITEMHITTEST, 0, LPARAM(@HitTestInfo));
  1190. end;
  1191. {$ENDIF}
  1192.  
  1193. function ListView_SetColumnOrderArray(LVWnd: HWnd; Count: integer;
  1194.                                       IntArray: PIntArray): boolean;
  1195. begin
  1196.   Result := (SendMessage(LVWnd, LVM_SETCOLUMNORDERARRAY, Count,
  1197.      LPARAM(IntArray)) <> 0);
  1198. end;
  1199.  
  1200. function ListView_GetColumnOrderArray(LVWnd: HWnd; Count: integer;
  1201.                                       IntArray: PIntArray): boolean;
  1202. begin
  1203.   Result := (SendMessage(LVWnd, LVM_GETCOLUMNORDERARRAY, Count,
  1204.      LPARAM(IntArray)) <> 0);
  1205. end;
  1206.  
  1207. function ListView_SetHotItem(LVWnd: HWnd; Item: integer): integer;
  1208. begin
  1209.   Result := SendMessage(LVWnd, LVM_SETHOTITEM, Item, 0);
  1210. end;
  1211.  
  1212. function ListView_GetHotItem(LVWnd: HWnd): integer;
  1213. begin
  1214.   Result := SendMessage(LVWnd, LVM_GETHOTITEM, 0, 0);
  1215. end;
  1216.  
  1217. function ListView_SetHotCursor(LVWnd: HWnd; Cursor: HCursor): HCursor;
  1218. begin
  1219.   Result := HCursor(SendMessage(LVWnd, LVM_SETHOTCURSOR, 0, LPARAM(Cursor)));
  1220. end;
  1221.  
  1222. function ListView_GetHotCursor(LVWnd: HWnd): HCursor;
  1223. begin
  1224.   Result := HCursor(SendMessage(LVWnd, LVM_GETHOTCURSOR, 0, 0));
  1225. end;
  1226.  
  1227. function ListView_ApproximateViewRect(LVWnd: HWnd; Width, Height,
  1228.    Count: integer): DWORD;
  1229. begin
  1230.   Result := SendMessage(LVWnd, LVM_APPROXIMATEVIEWRECT, Count,
  1231.      MAKELPARAM(Width, Height));
  1232. end;
  1233.  
  1234. function ListView_SetWorkArea(LVWnd: HWnd; const Rect: TRect): boolean;
  1235. begin
  1236.   Result := (SendMessage(LVWnd, LVM_SETWORKAREA, 0, LPARAM(@Rect)) <> 0);
  1237. end;
  1238.  
  1239. function ListView_GetCheckState(LVWnd: HWnd; Index: UINT): boolean;
  1240. begin
  1241.   Result := (SendMessage(LVWnd, LVM_GETITEMSTATE, Index,
  1242.      LVIS_STATEIMAGEMASK) SHR 12)-1 <> 0;
  1243. end;
  1244.  
  1245. procedure ListView_SetCheckState(LVWnd: HWnd; Index: UINT; Checked: boolean);
  1246. const
  1247.   LVIS_UNCHECKED = $1000;
  1248.   LVIS_CHECKED = $2000;
  1249. var
  1250.   Data: integer;
  1251. begin
  1252.   if Checked then Data := LVIS_CHECKED
  1253.   else Data := LVIS_UNCHECKED;
  1254.   ListView_SetItemState(LVWnd, Index, Data, LVIS_STATEIMAGEMASK);
  1255. end;
  1256.  
  1257. procedure ListView_SetItemCountEx(LVWnd: HWnd; Items: integer; Flags: DWORD);
  1258. begin
  1259.   SendMessage(LVWnd, LVM_SETITEMCOUNT, Items, Flags);
  1260. end;
  1261.  
  1262. {$IFNDEF DFS_C3D4COMMCTRL}
  1263. function ListView_SetExtendedListViewStyleEx(LVWnd: HWnd; Mask: DWord;
  1264.    ExStyle: LPARAM): DWORD;
  1265. begin
  1266.   Result := SendMessage(LVWnd, LVM_SETEXTENDEDLISTVIEWSTYLE, Mask, ExStyle);
  1267. end;
  1268. {$ENDIF}
  1269.  
  1270. function ListView_GetSelectionMark(LVWnd: HWnd): integer;
  1271. begin
  1272.   Result := SendMessage(LVWnd, LVM_GETSELECTIONMARK, 0, 0);
  1273. end;
  1274.  
  1275. function ListView_SetSelectionMark(LVWnd: HWnd; iIndex: integer): integer;
  1276. begin
  1277.   Result := SendMessage(LVWnd, LVM_SETSELECTIONMARK, 0, iIndex);
  1278. end;
  1279.  
  1280. {$IFNDEF DFS_C3D4COMMCTRL}
  1281. function ListView_SetHoverTime(LVWnd: HWnd; dwHoverTimeMS: DWORD): DWORD;
  1282. begin
  1283.   Result := SendMessage(LVWnd, LVM_SETHOVERTIME, 0, dwHoverTimeMs);
  1284. end;
  1285.  
  1286. function ListView_GetHoverTime(LVWnd: HWnd): DWORD;
  1287. begin
  1288.   Result := DWORD(SendMessage(LVWnd, LVM_GETHOVERTIME, 0, 0));
  1289. end;
  1290.  
  1291. function ListView_SetToolTips(LVWnd, NewWnd: HWnd): HWnd;
  1292. begin
  1293.   Result := SendMessage(LVWnd, LVM_SETTOOLTIPS, NewWnd, 0);
  1294. end;
  1295.  
  1296. function ListView_GetToolTips(LVWnd: HWnd): HWnd;
  1297. begin
  1298.   Result := SendMessage(LVWnd, LVM_GETTOOLTIPS, 0, 0);
  1299. end;
  1300.  
  1301. function ListView_SetBkImage(LVWnd: HWnd; plvbki: PLVBkImage): BOOL;
  1302. begin
  1303.   Result := (SendMessage(LVWnd, LVM_SETBKIMAGE, 0, LPARAM(plvbki)) <> 0);
  1304. end;
  1305.  
  1306. function ListView_GetBkImage(LVWnd: HWnd; plvbki: PLVBkImage): BOOL;
  1307. begin
  1308.   Result := (SendMessage(LVWnd, LVM_GETBKIMAGE, 0, LPARAM(plvbki)) <> 0);
  1309. end;
  1310. {$ENDIF}
  1311.  
  1312.  
  1313.  
  1314. {$IFDEF DFS_TRY_BACKGROUND_IMAGE}
  1315.  
  1316. constructor TELVBackgroundImage.Create(AOwner: TCustomExtListView);
  1317. begin
  1318.   inherited Create;
  1319.   FBrushBmp := TBitmap.Create;
  1320.   FOwningListView := AOwner;
  1321. end;
  1322.  
  1323. destructor TELVBackgroundImage.Destroy;
  1324. begin
  1325.   FBrushBmp.Free;
  1326.   inherited Destroy;
  1327. end;
  1328.  
  1329. procedure TELVBackgroundImage.Assign(Source: TPersistent);
  1330. begin
  1331.   if Source is TELVBackgroundImage then
  1332.   begin
  1333.     FFilename := TELVBackgroundImage(Source).Filename;
  1334.     FTile := TELVBackgroundImage(Source).Tile;
  1335.     FXOffsetPercent := TELVBackgroundImage(Source).XOffsetPercent;
  1336.     FYOffsetPercent := TELVBackgroundImage(Source).YOffsetPercent;
  1337.     ApplyToListView;
  1338.   end;
  1339. end;
  1340.  
  1341. procedure TELVBackgroundImage.SetFilename(const Val: string);
  1342. begin
  1343.   if FFilename <> Val then
  1344.     FFilename := Val;
  1345.   ApplyToListView;
  1346. end;
  1347.  
  1348. procedure TELVBackgroundImage.SetTile(Val: boolean);
  1349. begin
  1350.   if FTile <> Val then
  1351.     FTile := Val;
  1352.   ApplyToListView;
  1353. end;
  1354.  
  1355. procedure TELVBackgroundImage.SetXOffsetPercent(Val: integer);
  1356. begin
  1357.   if FXOffsetPercent <> Val then
  1358.     FXOffsetPercent := Val;
  1359.   ApplyToListView;
  1360. end;
  1361.  
  1362. procedure TELVBackgroundImage.SetYOffsetPercent(Val: integer);
  1363. begin
  1364.   if FYOffsetPercent <> Val then
  1365.     FYOffsetPercent := Val;
  1366.   ApplyToListView;
  1367. end;
  1368.  
  1369. procedure TELVBackgroundImage.ApplyToListView;
  1370. var
  1371.   LVBkImg: TLVBkImage;
  1372. begin
  1373.   if assigned(FOwningListView) and FOwningListView.HandleAllocated then
  1374.   begin
  1375.     if FFilename <> '' then
  1376.       LVBkImg.ulFlags := LVBKIF_SOURCE_URL
  1377.     else
  1378.       LVBkImg.ulFlags := LVBKIF_SOURCE_NONE;
  1379.     if FTile then
  1380.       LVBkImg.ulFlags := LVBkImg.ulFlags or LVBKIF_STYLE_TILE
  1381.     else
  1382.       LVBkImg.ulFlags := LVBkImg.ulFlags or LVBKIF_STYLE_NORMAL;
  1383.     LVBkImg.hbm := 0;
  1384.     LVBkImg.pszImage := PChar(FFilename);
  1385.     LVBkImg.cchImageMax := Length(FFilename);
  1386.     LVBkImg.xOffsetPercent := FXOffsetPercent;
  1387.     LVBkImg.yOffsetPercent := FYOffsetPercent;
  1388.     // Transparent
  1389.     ListView_SettExtBkColor(FOwningListView.Handle, $FFFFFFFF);
  1390.     ListView_SetBkImage(FOwningListView.Handle, @LVBkImg);
  1391.   end;
  1392. end;
  1393. {$ENDIF}
  1394.  
  1395.  
  1396. constructor TdfsExtLVSaveSettings.Create;
  1397. begin
  1398.   inherited Create;
  1399.   FSaveColumnOrder := TRUE;
  1400. end;
  1401.  
  1402. procedure TdfsExtLVSaveSettings.StoreColumnOrder(ColCount: integer;
  1403.    const IntArray: array of integer);
  1404. var
  1405.   Reg: TRegIniFile;
  1406.   x: integer;
  1407.   s: string;
  1408. begin
  1409.   if ColCount < 1 then exit;
  1410.   s := '';
  1411.   for x := 0 to ColCount-1 do
  1412.     s := s + IntToStr(IntArray[x]) + ',';
  1413.   SetLength(s, Length(s)-1);
  1414.   Reg := TRegIniFile.Create(RegistryKey);
  1415.   try
  1416.     Reg.WriteString('Columns', 'Order', s);
  1417.   finally
  1418.     Reg.Free;
  1419.   end;
  1420. end;
  1421.  
  1422. procedure TdfsExtLVSaveSettings.ReadColumnOrder(ColCount: integer;
  1423.    var IntArray: array of integer);
  1424. var
  1425.   Reg: TRegIniFile;
  1426.   x,y: integer;
  1427.   s: string;
  1428. begin
  1429.   if ColCount < 1 then exit;
  1430.   s := '';
  1431.   Reg := TRegIniFile.Create(RegistryKey);
  1432.   try
  1433.     s := Reg.ReadString('Columns', 'Order', '');
  1434.   finally
  1435.     Reg.Free;
  1436.   end;
  1437.   if s = '' then
  1438.   begin
  1439.     for x := 0 to ColCount-1 do
  1440.       IntArray[x] := x;
  1441.     exit;
  1442.   end;
  1443.   y := 0;
  1444.   for x := 0 to ColCount-1 do
  1445.   begin
  1446.     try
  1447.       y := Pos(',', s);
  1448.       if y = 0 then
  1449.         y := Length(s)+1;
  1450.       IntArray[x] := StrToInt(Copy(s, 1, y-1));
  1451.     except
  1452.       IntArray[x] := 0;
  1453.     end;
  1454.     s := copy(s, y+1, length(s));
  1455.     if s = '' then break;
  1456.   end;
  1457. end;
  1458.  
  1459.  
  1460.  
  1461. // Override constructor to "zero out" our internal variable.
  1462. constructor TCustomExtListView.Create(AOwner: TComponent);
  1463. begin
  1464.   inherited Create(AOwner);
  1465.  
  1466.   FItemCountEx := 0;
  1467.   FItemCountExFlags := [];
  1468.   FSelectionMark := -1;
  1469.   FHoverTime := -1;
  1470.   FExtendedStyles := [lvxInfoTip];
  1471.   FColumnOrder := NIL;
  1472.   FColumnOrderCount := 0;
  1473.   FRequireComCtlUpdate := FALSE;
  1474.   FSaveSettings := TdfsExtLVSaveSettings.Create;
  1475.   FColumnsFormatChangeLink := TChangeLink.Create;
  1476.   FColumnsFormatChangeLink.OnChange := ColumnHeaderImagesChange;
  1477.   FVirtualMode := FALSE;
  1478.   FColumnsFormat := TdfsExtListColumns.Create(Self);
  1479. {$IFDEF DFS_TRY_BACKGROUND_IMAGE}
  1480.   FBackgroundImage := TELVBackgroundImage.Create(Self);
  1481. {$ENDIF}
  1482. {$IFDEF DFS_COMPILER_4_UP}
  1483.   OnData := FeedOwnerDataMode;
  1484. {$ENDIF}
  1485. end;
  1486.  
  1487. destructor TCustomExtListView.Destroy;
  1488. begin
  1489.   FColumnsFormat.Free; { don't think i need this, it has an Owner property }
  1490.   FColumnsFormatChangeLink.Free;
  1491.  
  1492.   if FColumnOrder <> NIL then
  1493.     FreeMem(FColumnOrder, FColumnOrderCount * SizeOf(Integer));
  1494.   FRecreateStream.Free;
  1495.   FRecreateStream := NIL;
  1496.  
  1497.   inherited Destroy;
  1498.  
  1499.   FSaveSettings.Free;
  1500. {$IFDEF DFS_TRY_BACKGROUND_IMAGE}
  1501.   { Free after inherited because inherited calls DestroyWnd and it is needed
  1502.     until after that...}
  1503.   FBackgroundImage.Free;
  1504. {$ENDIF}
  1505. end;
  1506.  
  1507. procedure TCustomExtListView.CreateParams(var Params: TCreateParams);
  1508. begin
  1509.   inherited CreateParams(Params);
  1510.  
  1511.   if FVirtualMode then
  1512.     Params.Style := Params.Style or LVS_OWNERDATA;
  1513. end;
  1514.  
  1515. procedure TCustomExtListView.CreateWnd;
  1516. begin
  1517.   inherited CreateWnd;
  1518.  
  1519. //  RestoreChecks;
  1520.   SetSelectionMark(FSelectionMark);
  1521.   SetHoverTime(FHoverTime);
  1522.   SetExtendedStyles(FExtendedStyles);
  1523.   if VirtualMode and (FItemCountEx > 0) then
  1524.     SetItemCountEx(FItemCountEx, FItemCountExFlags);
  1525.  
  1526.   if FColumnOrder <> NIL then
  1527.   begin
  1528.     SendMessage(Handle, LVM_SETCOLUMNORDERARRAY, FColumnOrderCount,
  1529.        LongInt(FColumnOrder));
  1530.     Refresh;
  1531.   end;
  1532. {$IFDEF DFS_TRY_BACKGROUND_IMAGE}
  1533.   FBackgroundImage.ApplyToListView;
  1534. {$ENDIF}
  1535.   if not (csLoading in ComponentState) then
  1536.   begin
  1537.     if (StateImages <> NIL) then
  1538.       ListView_SetCallbackMask(Handle, ListView_GetCallbackMask(Handle) or
  1539.         LVIS_STATEIMAGEMASK);
  1540.     ListView_SetCallbackMask(Handle, ListView_GetCallbackMask(Handle) or
  1541.       LVIS_OVERLAYMASK);
  1542.   end;
  1543.   RestoreChecks;
  1544. end;
  1545.  
  1546. procedure TCustomExtListView.Loaded;
  1547. begin
  1548.   inherited Loaded;
  1549.  
  1550.   HandleNeeded;
  1551.   UpdateColumnsImages;
  1552.   if StateImages <> NIL then
  1553.     ListView_SetCallbackMask(Handle, ListView_GetCallbackMask(Handle) or
  1554.       LVIS_STATEIMAGEMASK);
  1555.   ListView_SetCallbackMask(Handle, ListView_GetCallbackMask(Handle) or
  1556.     LVIS_OVERLAYMASK);
  1557. end;
  1558.  
  1559. // Subitem set to -1 means Caption Text
  1560. function TCustomExtListView.GetSubItemText(Index, SubItem: integer): string;
  1561. var
  1562.   x,
  1563.   ColCount: integer;
  1564.   ColArray: PIntArray;
  1565. begin
  1566.   // needs to account for modified column order
  1567.   Result := '';
  1568.   if Items[Index] = NIL then
  1569.     exit;
  1570.  
  1571.   ColCount := Columns.Count;
  1572.   if (SubItem + 2 > ColCount) then
  1573.   begin
  1574.     if SubItem < Items[Index].SubItems.Count then
  1575.       Result := Items[Index].SubItems[SubItem];
  1576.   end else begin
  1577.     GetMem(ColArray, SizeOf(Integer)*ColCount);
  1578.     try
  1579.       GetColumnOrder(ColCount, ColArray^);
  1580.       x := ColArray[SubItem+1];
  1581.       if x = 0 then
  1582.         Result := Items[Index].Caption
  1583.       else
  1584.         Result := Items[Index].SubItems[x-1];
  1585.     finally
  1586.       FreeMem(ColArray);
  1587.     end;
  1588.   end;
  1589. end;
  1590.  
  1591. function TCustomExtListView.GetActualColumn(Index: integer): TListColumn;
  1592. var
  1593. //  x,
  1594.   ColCount: integer;
  1595.   ColArray: PIntArray;
  1596. begin
  1597.   // account for modified column order
  1598.  
  1599.   // Delphi 2 and C++B 1 have a bug in TListColumn.GetWidth.  It returns zero
  1600.   // for the width if the handle hasn't been allocated yet instead of returning
  1601.   // the value of the internal storage variable like Delphi 3 does.  I've also
  1602.   // had some problems similar under Delphi 3, so I'm just always requiring the
  1603.   // handle to be valid.
  1604.   HandleNeeded;
  1605.  
  1606.   Result := NIL;
  1607.   ColCount := Columns.Count;
  1608.   if Index >= ColCount then
  1609.     exit;
  1610.  
  1611.   GetMem(ColArray, SizeOf(Integer)*ColCount);
  1612.   try
  1613.     GetColumnOrder(ColCount, ColArray^);
  1614.     Result := Columns[ColArray[Index]];
  1615. (* I must have been high
  1616.     for x := 0 to ColCount-1 do
  1617.       if ColArray[x] = Index then
  1618.       begin
  1619.         Result := Columns[ColArray[x]];
  1620.         exit;
  1621.       end;
  1622. *)
  1623.   finally
  1624.     FreeMem(ColArray);
  1625.   end;
  1626. end;
  1627.  
  1628. procedure TCustomExtListView.MeasureItem(var Height: UINT);
  1629. begin
  1630.   inherited MeasureItem(Height);
  1631. end;
  1632.  
  1633. procedure TCustomExtListView.DrawItem(var Canvas: TCanvas; Index: Integer;
  1634.    Rect: TRect; State: TOwnerDrawState; var DefaultDrawing,
  1635.    FullRowSelect: boolean);
  1636. begin
  1637.   { Default to whatever is in ExtendedStyles settings }
  1638.   FullRowSelect := lvxFullRowSelect in ExtendedStyles;
  1639.   inherited DrawItem(Canvas, Index, Rect, State, DefaultDrawing,
  1640.      FullRowSelect);
  1641. end;
  1642.  
  1643. procedure TCustomExtListView.DrawSubItem(Index, SubItem: Integer; Rect: TRect;
  1644.    State: TOwnerDrawState; var DefaultDrawing: boolean);
  1645. begin
  1646.   inherited DrawSubItem(Index, SubItem, Rect, State, DefaultDrawing);
  1647. end;
  1648.  
  1649. procedure TCustomExtListView.DefaultDrawHeader(var Canvas: TCanvas;
  1650.    Index: Integer; var Rect: TRect; Selected: boolean);
  1651. var
  1652.   TheColumn: TListColumn;
  1653.   ExtColumn: TdfsExtListColumn;
  1654.   ImageOffset: integer;
  1655.   Offset: integer;
  1656.   R, CR: TRect;
  1657.   Bmp: TBitmap;
  1658. begin
  1659.  
  1660. (******************************************************************************)
  1661. (* NOTE:  This method is overriden and replaced from the one in TdfsEnhListView. *)
  1662. (*   That means that if changes are made here, they will also need to be made *)
  1663. (*   in EnhListView.pas' DefaultDrawHeader method.                            *)
  1664. (******************************************************************************)
  1665.  
  1666.   if not Selected then
  1667.     InflateRect(Rect, -2, -2);
  1668.   Canvas.FillRect(Rect);
  1669.   if Selected then
  1670.     InflateRect(Rect, -2, -2);
  1671.  
  1672.   if (Index >= 0) and (Index < Columns.Count) then
  1673.   begin
  1674.     // Don't use ActualColumn[] here!  That's for SubItem foolery, not header.
  1675.     TheColumn := Columns[Index];
  1676. //    TheColumn := ActualColumn[Index];
  1677.  
  1678.     if Selected then
  1679.     begin
  1680.       inc(Rect.Top);
  1681.       inc(Rect.Left);
  1682.     end;
  1683.  
  1684.     R := Rect;
  1685.  
  1686.     case TheColumn.Alignment of
  1687.       taRightJustify:
  1688.         Dec(R.Right, 4);
  1689.       taLeftJustify:
  1690.         Inc(R.Left, 4);
  1691.       // taCenter needs no modification
  1692.     end;
  1693.  
  1694.     if (Index < ColumnsFormat.Count) and assigned(SmallImages) and
  1695.        ((ColumnsFormat[Index].ImageIndex >= 0) and
  1696.        (ColumnsFormat[Index].ImageIndex < SmallImages.Count)) then
  1697.       ExtColumn := ColumnsFormat[Index]
  1698.     else
  1699.       ExtColumn := NIL;
  1700.  
  1701.     if assigned(ExtColumn) then
  1702.     begin
  1703.       case ExtColumn.ImageAlignment of
  1704.         ciaLeftOfText:
  1705.           Inc(R.Left, SmallImages.Width + 4);
  1706.         ciaRightOfText:
  1707.           Dec(R.Right, SmallImages.Width + 4);
  1708.       end;
  1709.     end;
  1710.  
  1711.     if ShowSortArrows and (LastColumnClicked = Index) and
  1712.        ((AutoColumnSort <> acsNoSort) or (assigned(OnSortItems))) then
  1713.     begin
  1714.       if CurrentSortAscending then
  1715.         Bmp := SortUpBmp
  1716.       else
  1717.         Bmp := SortDownBmp;
  1718.  
  1719.       Dec(R.Right, Bmp.Width + 8);
  1720.       if R.Right < R.Left then
  1721.         R.Right := R.Left;
  1722.  
  1723.       { How big of a rectangle do we have to work with for the Text? }
  1724.       CR := R;
  1725.       DrawTextEx(Canvas.Handle, PChar(TheColumn.Caption), -1, CR,
  1726.          DRAWTEXTEX_FLAGS or DT_CALCRECT or
  1727.          DRAWTEXTEX_ALIGNMENT[TheColumn.Alignment], NIL);
  1728.       { Note that DT_CALCRECT does not adjust for alignment. We must do that }
  1729.       case TheColumn.Alignment of
  1730.         taRightJustify:
  1731.           R.Left := R.Right - (CR.Right - CR.Left);
  1732.         taCenter:
  1733.           begin
  1734.             R.Left := R.Left + (((R.Right - R.Left) - (CR.Right - CR.Left)) div
  1735.                2);
  1736.             R.Right := R.Left + (CR.Right - CR.Left);
  1737.           end;
  1738.       else // taLeftJustify: doesn't matter, that is what DT_CALCRECT returns
  1739.         R := CR;
  1740.       end;
  1741.       if R.Left < Rect.Left then
  1742.         R.Left := Rect.Left;
  1743.       if R.Right > Rect.Right then
  1744.         R.Right := Rect.Right;
  1745.  
  1746.       if Selected then
  1747.         OffsetRect(R, 1, 1);
  1748.       // Draw the caption in the rect available
  1749.       DrawTextEx(Canvas.Handle, PChar(TheColumn.Caption), -1, R,
  1750.          DRAWTEXTEX_FLAGS or DRAWTEXTEX_ALIGNMENT[TheColumn.Alignment], NIL);
  1751.  
  1752.       // Draw column image if we have one
  1753.       if assigned(ExtColumn) then
  1754.       begin
  1755.         ImageOffset := (Rect.Bottom - Rect.Top - SmallImages.Height) div 2;
  1756.         case ExtColumn.ImageAlignment of
  1757.           ciaLeftOfText:
  1758.             SmallImages.Draw(Canvas, R.Left - (SmallImages.Width + 4),
  1759.                R.Top + ImageOffset, ExtColumn.ImageIndex);
  1760.           ciaRightOfText:
  1761.             begin
  1762.               SmallImages.Draw(Canvas, R.Right + 4, R.Top + ImageOffset,
  1763.                  ExtColumn.ImageIndex);
  1764.               inc(R.Right, SmallImages.Width);
  1765.               if R.Right > Rect.Right then
  1766.                 R.Right := Rect.Right;
  1767.             end;
  1768.         end;
  1769.       end;
  1770.  
  1771.       // Draw the sort arrow bitmap
  1772.       Offset := (Rect.Bottom - Rect.Top - Bmp.Height) div 2;
  1773.       // Only draw if we have enough room
  1774.       if (R.Right + Bmp.Width + 8) <= Rect.Right then
  1775.         Canvas.Draw(R.Right + 8, R.Top + Offset, Bmp);
  1776.     end else begin
  1777.       if Selected then
  1778.         OffsetRect(R, 1, 1);
  1779.       CR := R;
  1780.  
  1781.       DrawTextEx(Canvas.Handle, PChar(TheColumn.Caption), -1, CR,
  1782.          DRAWTEXTEX_FLAGS or DT_CALCRECT or
  1783.          DRAWTEXTEX_ALIGNMENT[TheColumn.Alignment], NIL);
  1784.       { Note that DT_CALCRECT does not adjust for alignment. We must do that }
  1785.       case TheColumn.Alignment of
  1786.         taRightJustify:
  1787.           R.Left := R.Right - (CR.Right - CR.Left);
  1788.         taCenter:
  1789.           begin
  1790.             R.Left := R.Left + (((R.Right - R.Left) - (CR.Right - CR.Left)) div
  1791.                2);
  1792.             R.Right := R.Left + (CR.Right - CR.Left);
  1793.           end;
  1794.       else // taLeftJustify: doesn't matter, that is what DT_CALCRECT returns
  1795.         R := CR;
  1796.       end;
  1797.       if R.Left < Rect.Left then
  1798.         R.Left := Rect.Left;
  1799.       if R.Right > Rect.Right then
  1800.         R.Right := Rect.Right;
  1801.  
  1802.       DrawTextEx(Canvas.Handle, PChar(TheColumn.Caption), -1, R,
  1803.          DRAWTEXTEX_FLAGS or DRAWTEXTEX_ALIGNMENT[TheColumn.Alignment], NIL);
  1804.  
  1805.       // Draw column image if we have one
  1806.       if assigned(ExtColumn) then
  1807.       begin
  1808.         ImageOffset := (Rect.Bottom - Rect.Top - SmallImages.Height) div 2;
  1809.         case ExtColumn.ImageAlignment of
  1810.           ciaLeftOfText:
  1811.             // Only draw if we have enough room
  1812.             if (R.Left - (SmallImages.Width + 4)) >= Rect.Left then
  1813.               SmallImages.Draw(Canvas, R.Left - (SmallImages.Width + 4),
  1814.                  R.Top + ImageOffset, ExtColumn.ImageIndex);
  1815.           ciaRightOfText:
  1816.             // Only draw if we have enough room
  1817.             if (R.Right + SmallImages.Width + 4) <= Rect.Right then
  1818.               SmallImages.Draw(Canvas, R.Right + 4, R.Top + ImageOffset,
  1819.                  ExtColumn.ImageIndex);
  1820.         end;
  1821.       end;
  1822.     end;
  1823.   end;
  1824. end;
  1825.  
  1826.  
  1827. const
  1828.   API_STYLES: array[Low(TLVExtendedStyle)..High(TLVExtendedStyle)] of LPARAM = (
  1829.      LVS_EX_GRIDLINES, LVS_EX_SUBITEMIMAGES, LVS_EX_CHECKBOXES,
  1830.      LVS_EX_TRACKSELECT, LVS_EX_HEADERDRAGDROP, LVS_EX_FULLROWSELECT,
  1831.      LVS_EX_ONECLICKACTIVATE, LVS_EX_TWOCLICKACTIVATE, LVS_EX_FLATSB,
  1832.      LVS_EX_INFOTIP, LVS_EX_UNDERLINEHOT, LVS_EX_UNDERLINECOLD,
  1833.      {$IFDEF DFS_DELPHI} LVS_EX_LABELTIP {$ELSE} $00004000 {$ENDIF});
  1834.      // LVS_EX_REGIONAL, LVS_EX_MULTIWORKAREAS - not implemented
  1835.  
  1836. // Function to convert our style set type into the value expected by the API.
  1837. function TCustomExtListView.SetValueToAPIValue(Styles: TLVExtendedStyles): LPARAM;
  1838. var
  1839.   x: TLVExtendedStyle;
  1840. begin
  1841.   Result := 0;
  1842.   { Check for each possible style. }
  1843.   for x := Low(TLVExtendedStyle) to High(TLVExtendedStyle) do
  1844.     { If the style is set... }
  1845.     if x in Styles then
  1846.       { OR the appropriate value into the result. }
  1847.       Result := Result OR API_STYLES[x];
  1848. end;
  1849.  
  1850. // Function to convert from the API values to our style set type.
  1851. function TCustomExtListView.SetValueFromAPIValue(Styles: DWORD): TLVExtendedStyles;
  1852. var
  1853.   x: TLVExtendedStyle;
  1854. begin
  1855.   Result := [];
  1856.   { Check for each possible style. }
  1857.   for x := Low(TLVExtendedStyle) to High(TLVExtendedStyle) do
  1858.     { If the style is set... }
  1859.     if (API_STYLES[x] and Styles) <> 0 then
  1860.       { OR the appropriate value into the result. }
  1861.       Result := Result + [x];
  1862. end;
  1863.  
  1864. // Property method to get the extended style bits.
  1865. function TCustomExtListView.GetExtendedStyles: TLVExtendedStyles;
  1866. begin
  1867.   if HandleAllocated then
  1868.     FExtendedStyles :=
  1869.        SetValueFromAPIValue(ListView_GetExtendedListViewStyle(Handle));
  1870.   Result := FExtendedStyles;
  1871. end;
  1872.  
  1873. // Property method to set new style bits.
  1874. procedure TCustomExtListView.SetExtendedStyles(Val: TLVExtendedStyles);
  1875. begin
  1876.   { Update the window with the new styles. }
  1877.   if (Val * [lvxUnderlineHot, lvxUnderlineCold] <> []) then
  1878.   begin
  1879.     // lvxUnderlineHot and lvxUnderlineCold require lvxOneClickActivate and/or
  1880.     // lvxTwoClickActivate
  1881.     if (lvxUnderlineCold in Val) and (not (lvxOneClickActivate in Val)) then
  1882.       Include(Val, lvxOneClickActivate);
  1883.     if (lvxUnderlineHot in Val) and
  1884.        (Val * [lvxOneClickActivate, lvxTwoClickActivate] = []) then
  1885.       Include(Val, lvxOneClickActivate);
  1886.   end;
  1887.  
  1888.   // A real world use of XOR!!!  We need to invalidate if subitem images is in
  1889.   // new value and not in old, or in old value and not in new, but NOT if it is
  1890.   // set or cleared in both.
  1891.   if ((lvxSubItemImages in Val) xor (lvxSubItemImages in FExtendedStyles)) and
  1892.     (HandleAllocated) then
  1893.     Invalidate;
  1894.   FExtendedStyles := Val;
  1895.   if HandleAllocated then
  1896.     ListView_SetExtendedListViewStyle(Handle, SetValueToAPIValue(Val));
  1897. end;
  1898.  
  1899. function TCustomExtListView.GetHeaderHandle: HWnd;
  1900. begin
  1901.   if FHeaderHandle <> 0 then
  1902.     Result := FHeaderHandle
  1903.   else begin
  1904.     if HandleAllocated then
  1905.       Result := ListView_GetHeader(Handle)
  1906.     else
  1907.       Result := 0;
  1908.   end;
  1909. end;
  1910.  
  1911. procedure TCustomExtListView.SetIconSpacing(X, Y: integer);
  1912. begin
  1913. // Not sure about how to update the view after changing this.  Refresh doesn't
  1914. // do the job.  Seems the best way to do it is in client code, something like:
  1915. (*
  1916.   SetIconSpacing(X, Y);
  1917.   // Does strange things if ViewStyle is not set to vsIcon!
  1918.   if ViewStyle = vsIcon then
  1919.   begin
  1920.     SendMessage(Handle, WM_SETREDRAW, 0, 0);
  1921.     try
  1922.       ViewStyle := vsSmallIcon;
  1923.       ViewStyle := vsIcon;
  1924.     finally
  1925.       SendMessage(Handle, WM_SETREDRAW, 1, 0);
  1926.     end;
  1927.   end;
  1928. *)
  1929.  
  1930.   if HandleAllocated then
  1931.     if ViewStyle = vsIcon then
  1932.       ListView_SetIconSpacing(Handle, X, Y);
  1933. end;
  1934.  
  1935. function TCustomExtListView.GetSubItemRect(Item, SubItem: integer;
  1936.    Index: integer): TRect;
  1937. begin
  1938.   if HandleAllocated then
  1939.     ListView_GetSubItemRect(Handle, Item, SubItem, Index, Result);
  1940. end;
  1941.  
  1942. function TCustomExtListView.GetSubItemAt(X, Y: integer): string;
  1943. var
  1944. {$IFNDEF DFS_C3D4COMMCTRL}
  1945.   Info: TLVHitTestInfoEx;
  1946. {$ELSE}
  1947.   Info: TLVHitTestInfo;
  1948. {$ENDIF}
  1949. begin
  1950.   Result := '';
  1951.   if HandleAllocated then
  1952.   begin
  1953.     Info.pt := Point(X, Y);
  1954. {$IFNDEF DFS_C3D4COMMCTRL}
  1955.     if ListView_SubItemHitTestEx(Handle, Info) <> -1 then
  1956. {$ELSE}
  1957.     if ListView_SubItemHitTest(Handle, @Info) <> -1 then
  1958. {$ENDIF}
  1959.     begin
  1960.       if (Info.iItem > -1) and (Items[Info.iItem] <> NIL) then
  1961.       begin
  1962.         if Info.iSubItem = 0 then
  1963.           Result := Items[Info.iItem].Caption
  1964.         else
  1965.           Result := Items[Info.iItem].SubItems[Info.iSubItem-1];
  1966.       end;
  1967.     end;
  1968.   end;
  1969. end;
  1970.  
  1971. procedure TCustomExtListView.SetColumnOrder(Count: integer; const IntArray:
  1972.    array of integer);
  1973. begin
  1974.   if FColumnOrder <> NIL then
  1975.     FreeMem(FColumnOrder, FColumnOrderCount * SizeOf(Integer));
  1976.   FColumnOrderCount := Count;
  1977.   GetMem(FColumnOrder, FColumnOrderCount * SizeOf(Integer));
  1978.   Move(IntArray, FColumnOrder^, FColumnOrderCount * SizeOf(Integer));
  1979.   if HandleAllocated then
  1980.   begin
  1981.     ListView_SetColumnOrderArray(Handle, Count, @IntArray);
  1982.     Refresh;
  1983.   end;
  1984. end;
  1985.  
  1986. function TCustomExtListView.GetColumnOrder(Count: integer;
  1987.                                      var IntArray: array of integer): boolean;
  1988. begin
  1989.   if HandleAllocated then
  1990.   begin
  1991.     if Count <> FColumnOrderCount then
  1992.     begin
  1993.       FColumnOrderCount := Count;
  1994.       if FColumnOrder <> NIL then
  1995.         FreeMem(FColumnOrder, FColumnOrderCount * SizeOf(Integer));
  1996.       GetMem(FColumnOrder, FColumnOrderCount * SizeOf(Integer));
  1997.     end;
  1998.     Result := ListView_GetColumnOrderArray(Handle, FColumnOrderCount,
  1999.        @IntArray);
  2000.     Move(IntArray, FColumnOrder^, FColumnOrderCount * SizeOf(Integer));
  2001.   end else begin
  2002.     if FColumnOrder <> NIL then
  2003.     begin
  2004.       Move(FColumnOrder^, IntArray, Count * SizeOf(Integer));
  2005.       Result := TRUE;
  2006.     end else
  2007.       Result := FALSE;
  2008.   end;
  2009. end;
  2010.  
  2011. procedure TCustomExtListView.SetHotItem(Val: integer);
  2012. begin
  2013.   if HandleAllocated then
  2014.     ListView_SetHotItem(Handle, Val);
  2015. end;
  2016.  
  2017. function TCustomExtListView.GetHotItem: integer;
  2018. begin
  2019.   if HandleAllocated then
  2020.     Result := ListView_GetHotItem(Handle)
  2021.   else
  2022.     Result := -1;
  2023. end;
  2024.  
  2025. procedure TCustomExtListView.SetHotCursor(const Val: HCursor);
  2026. begin
  2027.   if HandleAllocated then
  2028.     ListView_SetHotCursor(Handle, Val);
  2029. end;
  2030.  
  2031. function TCustomExtListView.GetHotCursor: HCursor;
  2032. begin
  2033.   if HandleAllocated then
  2034.     Result := ListView_GetHotCursor(Handle)
  2035.   else
  2036.     Result := 0;
  2037. end;
  2038.  
  2039. function TCustomExtListView.ApproximateViewRect(Count: integer;
  2040.    const Proposed: TPoint): TPoint;
  2041. var
  2042.   Res: DWORD;
  2043. begin
  2044.   if HandleAllocated then
  2045.   begin
  2046.     Res := ListView_ApproximateViewRect(Handle, Proposed.X, Proposed.Y, Count);
  2047.     Result := Point(LoWord(Res), HiWord(Res));
  2048.   end else
  2049.     Result := Point(-1, -1);
  2050. end;
  2051.  
  2052. procedure TCustomExtListView.SetWorkArea(Rect: TRect);
  2053. begin
  2054.   if HandleAllocated then
  2055.     ListView_SetWorkArea(Handle, Rect);
  2056. end;
  2057.  
  2058. procedure TCustomExtListView.SetCheckState(Index: integer; Checked: boolean);
  2059. begin
  2060.   if HandleAllocated then
  2061.     ListView_SetCheckState(Handle, Index, Checked);
  2062. end;
  2063.  
  2064. function TCustomExtListView.GetCheckState(Index: integer): boolean;
  2065. begin
  2066.   if HandleAllocated then
  2067.     Result := ListView_GetCheckState(Handle, Index)
  2068.   else
  2069.     Result := FALSE;
  2070. end;
  2071.  
  2072. procedure TCustomExtListView.SetItemCountEx(Count: integer; Flags: TLVItemCountFlags);
  2073. var
  2074.   APIFlags: DWORD;
  2075. begin
  2076.   FItemCountEx := Count;
  2077.   FItemCountExFlags := Flags;
  2078.   if HandleAllocated then
  2079.   begin
  2080.     APIFlags := 0;
  2081.     if lvsicfNoInvalidateAll in Flags then
  2082.       APIFlags := LVSICF_NOINVALIDATEALL;
  2083.     if lvsicfNoScroll in Flags then
  2084.       APIFlags := APIFlags or LVSICF_NOSCROLL;
  2085.     ListView_SetItemCountEx(Handle, Count, APIFlags);
  2086.   end;
  2087. end;
  2088.  
  2089. procedure TCustomExtListView.SetVirtualMode(Val: boolean);
  2090. begin
  2091.   if Val = FVirtualMode then exit;
  2092.   FVirtualMode := Val;
  2093.   if Items <> NIL then
  2094.     Items.Clear;
  2095.   {$IFDEF DFS_COMPILER_4_UP}
  2096.   OwnerData := Val;
  2097.   {$ELSE}
  2098.   if HandleAllocated then
  2099.   begin
  2100.     RecreateWnd;
  2101.     HandleNeeded;
  2102.   end;
  2103.   {$ENDIF}
  2104. end;
  2105.  
  2106. function TCustomExtListView.GetItemIndent(Index: integer): Integer;
  2107. var
  2108.   APIItem: TLVItemEx;
  2109. begin
  2110.   HandleNeeded;
  2111.   { Which item do they want? }
  2112.   APIItem.iItem := Index;
  2113.   { Indenting is only supported for items, not subitems, by COMCTL32.DLL }
  2114.   APIItem.iSubItem := 0;
  2115.   { Tell it that only the iIndent value is to be set for the item so it }
  2116.   { leaves the rest of the stuff alone }
  2117.   APIItem.mask := LVIF_INDENT;
  2118.   { Get it. }
  2119.   if SendMessage(Handle, LVM_GETITEM, 0, LPARAM(@APIItem)) <> 0 then
  2120.     Result := APIItem.iIndent
  2121.   else
  2122.     Result := -1;
  2123. end;
  2124.  
  2125.  
  2126. procedure TCustomExtListView.SetItemIndent(Index: integer; Value: Integer);
  2127. var
  2128.   APIItem: TLVItemEx;
  2129. begin
  2130.   HandleNeeded;
  2131.   { Which item do they want? }
  2132.   APIItem.iItem := Index;
  2133.   { Indenting is only supported for items, not subitems, by COMCTL32.DLL }
  2134.   APIItem.iSubItem := 0;
  2135.   { Tell it that only the iIndent value is set for the item so it }
  2136.   { leaves the rest of the stuff alone }
  2137.   APIItem.mask := LVIF_INDENT;
  2138.   APIItem.iIndent := Value;
  2139.   { Set it. }
  2140.   if SendMessage(Handle, LVM_SETITEM, 0, LPARAM(@APIItem)) = 0 then
  2141.     messagebeep(1);
  2142. end;
  2143.  
  2144. procedure TCustomExtListView.ItemChecked(ItemIndex: integer; Checked: boolean);
  2145. begin
  2146.   if assigned(FOnItemChecked) then
  2147.     FOnItemChecked(Self, ItemIndex, Checked);
  2148. end;
  2149.  
  2150. procedure TCustomExtListView.CNNotify(var Message: TWMNotify);
  2151. var
  2152.   CallInherited: boolean;
  2153.   RenameText: string;
  2154.   RenameCanceled: boolean;
  2155. begin
  2156.   if Message.NMHdr = NIL then
  2157.   begin
  2158.     inherited;
  2159.     exit;
  2160.   end;
  2161.  
  2162.   with Message.NMHdr^ do
  2163.   begin
  2164.     Message.Result := 0;
  2165.     CallInherited := FALSE;
  2166.     case code of
  2167.       LVN_ITEMCHANGING:
  2168.         begin
  2169.           inherited;
  2170.           // make sure we're going to change, and the change involves the state
  2171.           with PNMListView(Pointer(Message.NMHdr))^ do
  2172.             if ((uChanged and LVIF_STATE) <> 0) and (Message.Result = 0) then
  2173.             begin
  2174.               FCheckedListItemIndex := iItem;
  2175.               FChecked := IsChecked[iItem];
  2176.             end;
  2177.         end;
  2178.       LVN_ITEMCHANGED:
  2179.         begin
  2180.           inherited;
  2181.           // See if an item's checked state changed
  2182.           with PNMListView(Pointer(Message.NMHdr))^ do
  2183.             if ((uChanged and LVIF_STATE) <> 0) and (iItem =
  2184.               FCheckedListItemIndex) and (FChecked <> IsChecked[iItem]) then
  2185.               ItemChecked(FCheckedListItemIndex, not FChecked);
  2186.         end;
  2187.       // We only want to handle LVN_ENDLABELEDIT when in virtual mode
  2188.       LVN_ENDLABELEDIT:
  2189.         if FVirtualMode then
  2190.         begin
  2191.           RenameCanceled  := PLVDispInfo(pointer(Message.NMHdr))^.item.pszText =
  2192.             NIL;
  2193.           if RenameCanceled then
  2194.             RenameText := ''
  2195.           else
  2196.             RenameText := StrPas(
  2197.               PLVDispInfo(pointer(Message.NMHdr))^.item.pszText);
  2198.           VMCaptionEdited(PLVDispInfo(pointer(Message.NMHdr))^.item.iItem,
  2199.             RenameCanceled, RenameText);
  2200.         end
  2201.         else
  2202.           CallInherited := TRUE;
  2203.       // We only want to handle LVN_GETDISPINFO when in virtual mode
  2204.       LVN_GETDISPINFO:
  2205.         if FVirtualMode then
  2206.           VMGetDispInfo(PLVDispInfoEx(pointer(Message.NMHdr))^.item)
  2207.         else
  2208.           CallInherited := TRUE;
  2209.       LVN_ODCACHEHINT:
  2210.         VMCacheHint(PNMCacheHint(pointer(Message.NMHdr))^);
  2211.       LVN_ODSTATECHANGED:
  2212.         VMStateChanged(PNMODStateChange(pointer(Message.NMHdr))^);
  2213.       LVN_ODFINDITEM:
  2214.         Message.Result := VMFindItem(PNMFindItem(pointer(Message.NMHdr))^);
  2215.  
  2216.       LVN_ITEMACTIVATE:
  2217.         begin
  2218.           ItemActivate;
  2219.           Message.Result := 0;
  2220.         end;
  2221.       LVN_MARQUEEBEGIN:
  2222.         begin
  2223.           if MarqueeBegin then
  2224.             Message.Result := 0
  2225.           else
  2226.             Message.Result := 1;
  2227.         end;
  2228.       LVN_HOTTRACK:
  2229.         begin
  2230.           if HotTrack(PNMListView(Message.NMHdr)^) then
  2231.             Message.Result := 0
  2232.           else
  2233.             Message.Result := 1;
  2234.         end;
  2235.       LVN_GETINFOTIP:
  2236.         begin
  2237.           GetInfoTip(PNMLVGetInfoTip(Message.NMHdr));
  2238.           SetWindowPos(Handle, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOACTIVATE or SWP_NOREDRAW or
  2239.           SWP_NOSIZE or SWP_NOMOVE);
  2240.           Message.Result := 1;
  2241.         end;
  2242.     else
  2243.       CallInherited := TRUE;
  2244.     end;
  2245.   end;
  2246.   if CallInherited then
  2247.     inherited;
  2248. end;
  2249.  
  2250.  
  2251. procedure TCustomExtListView.WMNotify(var Message: TWMNotify);
  2252. var
  2253.   CallInherited: boolean;
  2254.   HTI: THDHitTestInfo;
  2255.   pt: TPoint;
  2256.   ExtColumn: TdfsExtListColumn;
  2257. begin
  2258.   CallInherited := TRUE;
  2259.  
  2260.   case Message.NMHdr.code of
  2261.     // For some reason, the SECOND time you drag a header width, it toasts the
  2262.     // bitmap.  I think it has to do with the TListView class somehow resetting
  2263.     // the column information, overwriting our information (image info).  Anyway,
  2264.     // catching the condition (begin column header drag) and resetting all the
  2265.     // extended information for that column fixes it.
  2266.     HDN_BEGINTRACK, HDN_BEGINTRACKW, // the ...W messages were necessary, why? I do not know.
  2267.     HDN_DIVIDERDBLCLICK, HDN_DIVIDERDBLCLICKW: // doubleclick also
  2268.     begin
  2269.       UpdateColumnImage(PHDNotify(Message.NMHdr).Item); // from above
  2270.       if HeaderHandle <> 0 then
  2271.       begin
  2272.         // get cursor position
  2273.         GetCursorPos(pt);
  2274.         // convert to coordinates on header control of the listview
  2275.         Windows.ScreentoClient(HeaderHandle,pt);
  2276.         // fill in hittest structure
  2277.         HTI.flags := HHT_ONHEADER Or HHT_ONDIVIDER;
  2278.         HTI.point.x := pt.x;
  2279.         HTI.point.y := pt.y;
  2280.         //  get the header's hit-test info
  2281.         SendMessage(HeaderHandle, HDM_HITTEST, LongInt(0),LongInt(@HTI));
  2282.         if (HTI.Item >=0) and (HTI.Item < ColumnsFormat.Count) then
  2283.           ExtColumn := ColumnsFormat[HTI.Item] // get the extended format
  2284.         else
  2285.           ExtColumn := NIL;
  2286.         if Assigned(ExtColumn) then // found one?
  2287.           if not ExtColumn.AllowResize then
  2288.           begin
  2289.             CallInherited := FALSE; // Do not pass this msg
  2290.             Message.Result := 1;  // Message stopped, do not handle the resize event
  2291.           end;
  2292.       end;
  2293.     end;
  2294.  
  2295. {$IFDEF DFS_COMPILER_4_UP}
  2296.     // Delphi 4 re-orders column information on this notification to adjust for
  2297.     // column headers that have been moved to new locations.  That breaks this
  2298.     // component since it already adjusts for that, but in a different way.
  2299.     // Since this is a notification message, we don't need to pass it on to
  2300.     // inherited unless it needs it for something specific.  In this case, the
  2301.     // only thing this notification is used for is to kick off the order
  2302.     // adjustment, so we'll just eat the message.
  2303.     HDN_ENDDRAG:
  2304.       begin
  2305.         CallInherited := FALSE; // Don't pass it on!
  2306.         // Since we aren't letting the default handler have it, we must
  2307.         // invalidate the area our self so the items get redrawn with the new
  2308.         // column order applied.
  2309.         Invalidate;
  2310.       end;
  2311. {$ENDIF}
  2312.   end;
  2313.  
  2314.   if CallInherited then
  2315.     inherited;
  2316. end;
  2317.  
  2318.  
  2319. function TCustomExtListView.MarqueeBegin: boolean;
  2320. begin
  2321.   Result := TRUE;
  2322.   if assigned(FOnMarqueeBegin) then
  2323.     FOnMarqueeBegin(Self, Result);
  2324. end;
  2325.  
  2326. procedure TCustomExtListView.ItemActivate;
  2327. begin
  2328.   if assigned(FOnItemActivate) then
  2329.     FOnItemActivate(Self);
  2330. end;
  2331.  
  2332. function TCustomExtListView.HotTrack(var Item: TNMListView): boolean;
  2333. begin
  2334.   Result := TRUE;
  2335.   if assigned(FOnHotTrack) then
  2336.     FOnHotTrack(Self, Item.iItem, Item.iSubItem, Item.ptAction, Result);
  2337. end;
  2338.  
  2339. procedure TCustomExtListView.GetInfoTip(InfoTip: PNMLVGetInfoTip);
  2340. var
  2341.   Current,
  2342.   Additional: string;
  2343. begin
  2344.   if assigned(InfoTip) then
  2345.   begin
  2346.     if assigned(FOnInfoTip) then
  2347.     begin
  2348.       if InfoTip^.dwFlags = LVGIT_UNFOLDED then
  2349.         Current := string(InfoTip^.pszText)
  2350.       else
  2351.         Current := '';
  2352.       FOnInfoTip(Self, InfoTip^.iItem, InfoTip^.iSubItem, Current, Additional);
  2353.       if Additional <> '' then
  2354.       begin
  2355.         if InfoTip^.dwFlags = LVGIT_UNFOLDED then
  2356.           StrLCat(InfoTip^.pszText, PChar(Additional), InfoTip^.cchTextMax)
  2357.         else
  2358.           StrLCopy(InfoTip^.pszText, PChar(Additional), InfoTip^.cchTextMax);
  2359.       end;
  2360.     end
  2361.     else if not VirtualMode then
  2362.     begin
  2363.       if InfoTip^.dwFlags = LVGIT_UNFOLDED then
  2364.         StrLCat(InfoTip^.pszText, PChar(Items[InfoTip^.iItem].Caption),
  2365.           InfoTip^.cchTextMax)
  2366.       else
  2367.         StrLCopy(InfoTip^.pszText, PChar(Items[InfoTip^.iItem].Caption),
  2368.           InfoTip^.cchTextMax);
  2369.     end;
  2370.   end;
  2371. end;
  2372.  
  2373. procedure TCustomExtListView.VMGetDispInfo(var ItemInfo: TLVItemEx);
  2374.   function MaskFlagsToSet(Mask: UINT): TLVVMMaskItems;
  2375.   begin
  2376.     Result := [];
  2377.     if (Mask and LVIF_TEXT) = LVIF_TEXT then
  2378.       Include(Result, lvifText);
  2379.     if (Mask and LVIF_IMAGE) = LVIF_IMAGE then
  2380.       Include(Result, lvifImage);
  2381.     if (Mask and LVIF_PARAM) = LVIF_PARAM then
  2382.       Include(Result, lvifParam);
  2383.     if (Mask and LVIF_STATE) = LVIF_STATE then
  2384.       Include(Result, lvifState);
  2385.     if (Mask and LVIF_INDENT) = LVIF_INDENT then
  2386.       Include(Result, lvifIndent);
  2387.   end;
  2388.   function SetToMaskFlags(Mask: TLVVMMaskItems): UINT;
  2389.   begin
  2390.     Result := 0;
  2391.     if lvifText in Mask then
  2392.       Result := Result or LVIF_TEXT;
  2393.     if lvifImage in Mask then
  2394.       Result := Result or LVIF_IMAGE;
  2395.     if lvifParam in Mask then
  2396.       Result := Result or LVIF_PARAM;
  2397.     if lvifState in Mask then
  2398.       Result := Result or LVIF_STATE;
  2399.     if lvifIndent in Mask then
  2400.       Result := Result or LVIF_INDENT;
  2401.   end;
  2402. (*  function StateMaskFlagsToSet(Mask: UINT): TLVVMStateMaskItems;
  2403.   begin
  2404.     Result := [];
  2405.     if (Mask and LVIS_CUT) = LVIS_CUT then
  2406.       Include(Result, lvisCut);
  2407.     if (Mask and LVIS_DROPHILITED) = LVIS_DROPHILITED then
  2408.       Include(Result, lvisDropHighlighted);
  2409.     if (Mask and LVIS_FOCUSED) = LVIS_FOCUSED then
  2410.       Include(Result, lvisFocused);
  2411.     if (Mask and LVIS_SELECTED) = LVIS_SELECTED then
  2412.       Include(Result, lvisSelected);
  2413.     if (Mask and LVIS_OVERLAYMASK) = LVIS_OVERLAYMASK then
  2414.       Include(Result, lvisOverlayMask);
  2415.   end;*)
  2416. var
  2417.   Text: string;
  2418.   NewState: UINT;
  2419.   NewStateMask: UINT;
  2420.   GetMask: TLVVMMaskItems;
  2421.   OverlayImage, StateImage: word;
  2422. begin
  2423.   if ItemInfo.iItem = -1 then exit;  // No way.
  2424.   Text := '';
  2425.   NewState := ItemInfo.State;
  2426.   NewStateMask := ItemInfo.StateMask;
  2427.   GetMask := MaskFlagsToSet(ItemInfo.Mask);
  2428.  
  2429.   if assigned(FOnVMGetItemInfo) then
  2430.   begin
  2431.     OverlayImage := 0;
  2432.     StateImage := 0;
  2433.     with ItemInfo do
  2434.       FOnVMGetItemInfo(Self, iItem, iSubItem, GetMask,
  2435.        iImage, OverlayImage, StateImage, lParam, NewState, NewStateMask,
  2436.        iIndent, Text);
  2437.     if (ItemInfo.mask and LVIF_TEXT) = LVIF_TEXT then
  2438.       StrLCopy(ItemInfo.pszText, PChar(Text), ItemInfo.cchTextMax);
  2439.     ItemInfo.State := NewState;
  2440.     ItemInfo.State := ItemInfo.State and not UINT(IndexToOverlayMask($FFFF));
  2441.     ItemInfo.State := ItemInfo.State or UINT(IndexToOverlayMask(OverlayImage));
  2442.     ItemInfo.State := ItemInfo.State and not UINT(IndexToStateImageMask($FFFF));
  2443.     ItemInfo.State := ItemInfo.State or UINT(IndexToStateImageMask(StateImage));
  2444.     ItemInfo.Mask := SetToMaskFlags(GetMask);
  2445.     ItemInfo.StateMask := NewStateMask;
  2446.   end;
  2447. end;
  2448.  
  2449. procedure TCustomExtListView.VMCacheHint(var HintInfo: TNMCacheHint);
  2450. begin
  2451.   if assigned(FOnVMCacheHint) then
  2452.     FOnVMCacheHint(Self, HintInfo);
  2453. end;
  2454.  
  2455. function TCustomExtListView.VMFindItem(var FindInfo: TNMFindItem): integer;
  2456. begin
  2457.   Result := -1;
  2458.   if assigned(FOnVMFindItem) then
  2459.     FOnVMFindItem(Self, FindInfo, Result);
  2460. end;
  2461.  
  2462. procedure TCustomExtListView.VMStateChanged(var StateInfo: TNMODStateChange);
  2463. begin
  2464.   if assigned(FOnVMStateChanged) then
  2465.     FOnVMStateChanged(Self, StateInfo);
  2466. end;
  2467.  
  2468. procedure TCustomExtListView.VMCaptionEdited(Item: integer; Canceled: boolean;
  2469.   const Text: string);
  2470. begin
  2471.   if assigned(FOnVMCaptionEdited) then
  2472.     FOnVMCaptionEdited(Self, Item, Canceled, Text);
  2473. end;
  2474.  
  2475. function TCustomExtListView.WriteSettings: boolean;
  2476. var
  2477.   x,
  2478.   ColCount: integer;
  2479.   ColArray: PIntArray;
  2480. begin
  2481.   Result := TRUE;
  2482.   ColCount := Columns.Count;
  2483.   if (FSaveSettings.SaveColumnOrder or FSaveSettings.SaveColumnSizes) and
  2484.      (ColCount > 0) then
  2485.   begin
  2486.     GetMem(ColArray, SizeOf(Integer)*ColCount);
  2487.     try
  2488.       if FSaveSettings.SaveColumnOrder then
  2489.       begin
  2490.         GetColumnOrder(ColCount, ColArray^);
  2491.         FSaveSettings.StoreColumnOrder(ColCount, ColArray^);
  2492.       end;
  2493.       if FSaveSettings.SaveColumnSizes then
  2494.       begin
  2495.         for x := 0 to ColCount-1 do
  2496.           ColArray[x] := ActualColumn[x].Width;
  2497.         FSaveSettings.StoreColumnSizes(ColCount, ColArray^);
  2498.       end;
  2499.     finally
  2500.       FreeMem(ColArray);
  2501.     end;
  2502.   end;
  2503.   if FSaveSettings.SaveCurrentSort then
  2504.     FSaveSettings.StoreCurrentSort(CurrentSortAscending, LastColumnClicked);
  2505.   if FSaveSettings.SaveViewStyle then
  2506.     FSaveSettings.StoreViewStyle(ViewStyle);
  2507. end;
  2508.  
  2509. function TCustomExtListView.StoreSettings: boolean;
  2510. begin
  2511.   // DON'T CALL INHERITED!!!!  It has caused me no end of trouble, so I
  2512.   // just resave the width stuff if I need to rather than call inherited.
  2513.  
  2514.   if FSaveSettings.AutoSave and
  2515.      ((([csDesigning, csLoading, csReading] * ComponentState) = []) or
  2516.      (csDestroying in ComponentState)) then
  2517.     Result := WriteSettings
  2518.   else
  2519.     Result := FALSE;
  2520. end;
  2521.  
  2522. function TCustomExtListView.ReadSettings: boolean;
  2523. var
  2524.   x,
  2525.   ColCount: integer;
  2526.   ColArray: PIntArray;
  2527.   SortCol: integer;
  2528.   SortAscending: boolean;
  2529. begin
  2530.   Result := TRUE;
  2531.   ColCount := Columns.Count;
  2532.   if (FSaveSettings.SaveColumnOrder or FSaveSettings.SaveColumnSizes) and
  2533.      (ColCount > 0) then
  2534.   begin
  2535.     GetMem(ColArray, SizeOf(Integer)*ColCount);
  2536.     try
  2537.       if FSaveSettings.SaveColumnOrder then
  2538.       begin
  2539.         FSaveSettings.ReadColumnOrder(ColCount, ColArray^);
  2540.         SetColumnOrder(ColCount, ColArray^);
  2541.       end;
  2542.  
  2543.       if FSaveSettings.SaveColumnSizes then
  2544.       begin
  2545.         for x := 0 to ColCount-1 do
  2546.           ColArray[x] := ActualColumn[x].Width;
  2547.         FSaveSettings.ReadColumnSizes(ColCount, ColArray^);
  2548.         if ColArray[0] <> -1 then
  2549.           for x := 0 to ColCount-1 do
  2550.             ActualColumn[x].Width := ColArray[x];
  2551.       end;
  2552.     finally
  2553.       FreeMem(ColArray);
  2554.     end;
  2555.   end;
  2556.  
  2557.   if FSaveSettings.SaveCurrentSort then
  2558.   begin
  2559.     FSaveSettings.ReadCurrentSort(SortAscending, SortCol);
  2560.     if SortCol >= Columns.Count then
  2561.       SortCol := Columns.Count-1;
  2562.     if SortCol < 0 then
  2563.       SortCol := 0;
  2564.     BeginUpdate;
  2565.     try
  2566.       CurrentSortAscending := SortAscending;
  2567.       LastColumnClicked := SortCol;
  2568.       Resort;
  2569.     finally
  2570.       EndUpdate;
  2571.     end;
  2572.   end;
  2573.   
  2574.   if FSaveSettings.SaveViewStyle then
  2575.     ViewStyle := FSaveSettings.ReadViewStyle(ViewStyle);
  2576. end;
  2577.  
  2578. function TCustomExtListView.LoadSettings: boolean;
  2579. begin
  2580.   if FSaveSettings.AutoSave and (not(csDesigning in ComponentState)) then
  2581.     Result := ReadSettings
  2582.   else
  2583.     Result := FALSE;
  2584. end;
  2585.  
  2586.  
  2587. function TCustomExtListView.ELV_GetNextItem(StartItem: integer;
  2588.    Direction: TSearchDirection; States: TItemStates): integer;
  2589. var
  2590.   Flags: Integer;
  2591. begin
  2592.   Result := -1;
  2593.   if HandleAllocated then
  2594.   begin
  2595.     Flags := 0;
  2596.     case Direction of
  2597.       sdAbove: Flags := LVNI_ABOVE;
  2598.       sdBelow: Flags := LVNI_BELOW;
  2599.       sdLeft: Flags := LVNI_TOLEFT;
  2600.       sdRight: Flags := LVNI_TORIGHT;
  2601.       sdAll: Flags := LVNI_ALL;
  2602.     end;
  2603.     if isCut in States then Flags := Flags or LVNI_CUT;
  2604.     if isDropHilited in States then Flags := Flags or LVNI_DROPHILITED;
  2605.     if isFocused in States then Flags := Flags or LVNI_FOCUSED;
  2606.     if isSelected in States then Flags := Flags or LVNI_SELECTED;
  2607.     Result := ListView_GetNextItem(Handle, StartItem, Flags);
  2608.   end;
  2609. end;
  2610.  
  2611. procedure TCustomExtListView.ELV_SetItemState(Index: integer;
  2612.    States: TItemStates; Setting: boolean);
  2613. var
  2614.   NewState,
  2615.   Flags: UINT;
  2616. begin
  2617.   if HandleAllocated then
  2618.   begin
  2619.     Flags := 0;
  2620.     if isCut in States then Flags := Flags or LVIS_CUT;
  2621.     if isDropHilited in States then Flags := Flags or LVIS_DROPHILITED;
  2622.     if isFocused in States then Flags := Flags or LVIS_FOCUSED;
  2623.     if isSelected in States then Flags := Flags or LVIS_SELECTED;
  2624.     {$IFDEF DFS_COMPILER_4}
  2625.     if isActivating in States then Flags := Flags or LVIS_ACTIVATING;
  2626.     {$ENDIF}
  2627.     if Setting then
  2628.       NewState := Flags
  2629.     else
  2630.       NewState := 0;
  2631.     ListView_SetItemState(Handle, Index, NewState, Flags);
  2632.   end;
  2633. end;
  2634.  
  2635. procedure TCustomExtListView.ELV_EditCaption(Item: integer);
  2636. begin
  2637.   if HandleAllocated then
  2638.     ListView_EditLabel(Handle, Item);
  2639. end;
  2640.  
  2641. procedure TCustomExtListView.ColumnHeaderImagesChange(Sender: TObject);
  2642. begin
  2643.   UpdateColumnsImages; { Images changed }
  2644. end;
  2645.  
  2646.  
  2647. procedure TCustomExtListView.SetColumnsFormat(Value: TdfsExtListColumns);
  2648. begin
  2649.   FColumnsFormat.Assign(Value);
  2650. end;
  2651.  
  2652. {$IFDEF DFS_TRY_BACKGROUND_IMAGE}
  2653. procedure TCustomExtListView.SetBackgroundImage(Value: TELVBackgroundImage);
  2654. begin
  2655.   FBackgroundImage.Assign(Value);
  2656. end;
  2657. {$ENDIF}
  2658.  
  2659. function TCustomExtListView.GetSubItemImageIndex(Item, SubItem: integer): integer;
  2660. var
  2661.   APIItem: TLVItem;
  2662. begin
  2663.   HandleNeeded;
  2664.  
  2665.   Result := -1; // Assume the worst
  2666.  
  2667.   { Which item do they want? }
  2668.   APIItem.iItem := Item;
  2669.   { Subitem index, this is one-based, zero is the caption item }
  2670.   APIItem.iSubItem := SubItem+1;
  2671.   { Tell it that only the iImage value is to be set for the item so it }
  2672.   { leaves the rest of the stuff alone }
  2673.   APIItem.mask := LVIF_IMAGE;
  2674.   { Get it. }
  2675.   if ListView_GetItem(Handle, APIItem) then
  2676.     Result := APIItem.iImage;
  2677. end;
  2678.  
  2679. procedure TCustomExtListView.SetSubItemImageIndex(Item, SubItem, Value: integer);
  2680. var
  2681.   APIItem: TLVItem;
  2682. begin
  2683.   HandleNeeded;
  2684.  
  2685.   { Which item is it? }
  2686.   APIItem.iItem := Item;
  2687.   { Subitem index, this is one-based, zero is the caption item }
  2688.   APIItem.iSubItem := SubItem+1;
  2689.   { Tell it what image list index to use }
  2690.   APIItem.iImage := Value;
  2691.   { Tell it that only the iImage value is to be set for the item so it }
  2692.   { leaves the rest of the stuff in the item alone }
  2693.   APIItem.mask := LVIF_IMAGE;
  2694.   { Set it. }
  2695.   ListView_SetItem(Handle, APIItem);
  2696. end;
  2697.  
  2698. function TCustomExtListView.GetStateImages: {$IFDEF DFS_COMPILER_4_UP} TCustomImageList; {$ELSE} TImageList; {$ENDIF}
  2699. begin
  2700.   // Nothing, just get it
  2701.   Result := inherited StateImages;
  2702. end;
  2703.  
  2704. procedure TCustomExtListView.SetStateImages(Value: {$IFDEF DFS_COMPILER_4_UP} TCustomImageList {$ELSE} TImageList {$ENDIF});
  2705. begin
  2706.   SaveChecks;
  2707.   inherited StateImages := Value;
  2708.   if StateImages <> NIL then
  2709.     ListView_SetCallbackMask(Handle, ListView_GetCallbackMask(Handle) or
  2710.       LVIS_STATEIMAGEMASK)
  2711.   else
  2712.     ListView_SetCallbackMask(Handle, ListView_GetCallbackMask(Handle) and not
  2713.       LVIS_STATEIMAGEMASK);
  2714.   RestoreChecks;
  2715. end;
  2716.  
  2717. function TCustomExtListView.GetSmallImages: {$IFDEF DFS_COMPILER_4_UP} TCustomImageList; {$ELSE} TImageList; {$ENDIF}
  2718. begin
  2719.   // Nothing, just get it
  2720.   Result := inherited SmallImages;
  2721. end;
  2722.  
  2723. procedure TCustomExtListView.SetSmallImages(Value: {$IFDEF DFS_COMPILER_4_UP} TCustomImageList {$ELSE} TImageList {$ENDIF});
  2724. begin
  2725.   // Unlink ourself from old value
  2726.   if SmallImages <> NIL then
  2727.     SmallImages.UnregisterChanges(FColumnsFormatChangeLink);
  2728.  
  2729.   inherited SmallImages := Value;
  2730.  
  2731.   // Re-link to the new value.
  2732.   if SmallImages <> NIL then
  2733.     SmallImages.RegisterChanges(FColumnsFormatChangeLink);
  2734.  
  2735.   // Force the header to redraw
  2736.   SetColumnsOwnerDrawFlag(assigned(OnDrawHeader) or ShowSortArrows);
  2737. end;
  2738.  
  2739. function TCustomExtListView.GetSelectionMark: integer;
  2740. begin
  2741.   if HandleAllocated then
  2742.     FSelectionMark := ListView_GetSelectionMark(Handle);
  2743.   Result := FSelectionMark;
  2744. end;
  2745.  
  2746. procedure TCustomExtListView.SetSelectionMark(Val: integer);
  2747. begin
  2748.   if Val <> FSelectionMark then
  2749.     FSelectionMark := Val;
  2750.   // Call even if not changed because handle may not have been allocated
  2751.   if HandleAllocated then
  2752.     ListView_SetSelectionMark(Handle, Val);
  2753. end;
  2754.  
  2755. function TCustomExtListView.GetHoverTime: Longint;
  2756. begin
  2757.   if HandleAllocated then
  2758.     FHoverTime := Longint(ListView_GetHoverTime(Handle));
  2759.   Result := FHoverTime;
  2760. end;
  2761.  
  2762. procedure TCustomExtListView.SetHoverTime(Val: Longint);
  2763. begin
  2764.   if Val <> FHoverTime then
  2765.     FHoverTime := Val;
  2766.   // Call even if not changed because handle may not have been allocated last time
  2767.   if HandleAllocated then
  2768.     ListView_SetHoverTime(Handle, DWORD(Val));
  2769. end;
  2770.  
  2771. procedure TCustomExtListView.SetRequireComCtlUpdate(Value: boolean);
  2772. begin
  2773.   FRequireComCtlUpdate := Value;
  2774.   if FRequireComCtlUpdate and (not (csDesigning in ComponentState)) then
  2775.   begin
  2776.     if not CheckComCtlVersion(4, 70, 0, 0) then
  2777.       raise EELVOldComCtl.Create('COMCTL32.DLL is older than required version');
  2778.   end;
  2779. end;
  2780.  
  2781. procedure TCustomExtListView.UpdateColumnsImages;
  2782. var
  2783.   i: Integer;
  2784. begin
  2785.   if not (assigned(OnDrawHeader) or ShowSortArrows) then
  2786.     if HandleAllocated then
  2787.       for i := 0 to Columns.Count - 1 do UpdateColumnImage(i);
  2788. end;
  2789.  
  2790. procedure TCustomExtListView.UpdateColumnImage(Index: integer);
  2791.   function ValidImages: boolean;
  2792.   begin
  2793.     Result := assigned(SmallImages) and (SmallImages.Count > 0);
  2794.   end;
  2795. var
  2796.   Column: TLVColumnEx;
  2797. begin { UpdateColumnImage }
  2798.   if assigned(OnDrawHeader) or ShowSortArrows then
  2799.     exit;
  2800.  
  2801.   if HandleAllocated and (Index > -1) and (Index < FColumnsFormat.Count) and
  2802.      ValidImages then
  2803.   begin
  2804.     FillChar(Column, SizeOf(Column), #0);
  2805.     ListView_GetColumnEx(Handle, Index, Column);
  2806.     with Column, FColumnsFormat[Index] do
  2807.     begin
  2808.       if (ImageIndex <> -1) then
  2809.       begin
  2810.         iImage := ImageIndex;
  2811.         // Add LVCF_FMT Just to make sure...
  2812.         mask := mask or LVCF_IMAGE or LVCF_FMT;
  2813.         fmt  := fmt or LVCFMT_IMAGE;
  2814.         if ImageAlignment = ciaRightOfText then
  2815.           fmt := fmt or LVCFMT_BITMAP_ON_RIGHT;
  2816.       end else begin
  2817.         mask := LVCF_FMT;
  2818.         fmt  := fmt and not LVCFMT_IMAGE and not LVCFMT_BITMAP_ON_RIGHT;
  2819.       end;
  2820.       case Columns.Items[Index].Alignment of
  2821.         taLeftJustify: fmt := fmt or LVCFMT_LEFT;
  2822.         taCenter: fmt := fmt or LVCFMT_CENTER;
  2823.         taRightJustify: fmt := fmt or LVCFMT_RIGHT;
  2824.       end;
  2825.     end;
  2826.     ListView_SetColumnEx(Handle, Index, Column);
  2827.   end;
  2828. end;
  2829.  
  2830. function TCustomExtListView.CheckComCtlVersion(MajorHi, MajorLo,
  2831.    MinorHi, MinorLo: word): boolean;
  2832. begin
  2833.   Result := CheckDLLVersion('COMCTL32.DLL', MajorHi, MajorLo, MinorHi, MinorLo);
  2834. end;
  2835.  
  2836. function TCustomExtListView.GetShowSortArrows: boolean;
  2837. begin
  2838.   Result := inherited ShowSortArrows;
  2839. end;
  2840.  
  2841. procedure TCustomExtListView.SetShowSortArrows(Value: boolean);
  2842. begin
  2843.   inherited ShowSortArrows := Value;
  2844.   UpdateColumnsImages;
  2845. end;
  2846.  
  2847. function TCustomExtListView.ActualColumnIndex(Index: integer): integer;
  2848. var
  2849.   x,
  2850.   ColCount: integer;
  2851.   ColArray: PIntArray;
  2852. begin
  2853.   // account for modified column order
  2854.  
  2855.   // Delphi 2 and C++B 1 have a bug in TListColumn.GetWidth.  It returns zero
  2856.   // for the width if the handle hasn't been allocated yet instead of returning
  2857.   // the value of the internal storage variable like Delphi 3 does.  I've also
  2858.   // had some problems similar under Delphi 3, so I'm just always requiring the
  2859.   // handle to be valid.
  2860.   HandleNeeded;
  2861.  
  2862.   Result := 0;
  2863.   ColCount := Columns.Count;
  2864.   if Index >= ColCount then
  2865.     exit;
  2866.  
  2867.   GetMem(ColArray, SizeOf(Integer)*ColCount);
  2868.   try
  2869.     GetColumnOrder(ColCount, ColArray^);
  2870.     for x := 0 to ColCount-1 do
  2871.       if ColArray[x] = Index then
  2872.       begin
  2873.         Result := x;
  2874.         exit;
  2875.       end;
  2876.   finally
  2877.     FreeMem(ColArray);
  2878.   end;
  2879. end;
  2880.  
  2881. function TCustomExtListView.GetVersion: string;
  2882. begin
  2883.   Result := DFS_COMPONENT_VERSION;
  2884. end;
  2885.  
  2886. procedure TCustomExtListView.DefaultDrawSubItem(Index, SubItem: Integer;
  2887.    Rect: TRect; State: TOwnerDrawState);
  2888. var
  2889.   Dummy: boolean;
  2890.   SavedDC: integer;
  2891. begin
  2892.   if VirtualMode then
  2893.   begin
  2894.     SavedDC := SaveDC(FCanvas.Handle);
  2895.     try
  2896.       if not (csDesigning in ComponentState) then
  2897.         DrawSubItem(Index, SubItem, Rect, State, Dummy)
  2898.       else if Index = -1 then
  2899.         DrawTextEx(FCanvas.Handle, 'Virtual mode', -1, Rect, DRAWTEXTEX_FLAGS or
  2900.            DRAWTEXTEX_ALIGNMENT[ActualColumn[SubItem+1].Alignment], NIL);
  2901.     finally
  2902.       RestoreDC(FCanvas.Handle, SavedDC);
  2903.     end;
  2904.   end else
  2905.     inherited DefaultDrawSubItem(Index, SubItem, Rect, State);
  2906. end;
  2907.  
  2908. procedure TCustomExtListView.DefaultDrawItem(Index: Integer; Rect: TRect;
  2909.    State: TOwnerDrawState; FullRowSelect: boolean);
  2910. var
  2911.   Count: Integer;
  2912.   SubRect: TRect;
  2913. begin
  2914.   if VirtualMode then
  2915.   begin
  2916.     if Columns.Count > 0 then
  2917.     begin
  2918.       if (odSelected in State) then
  2919.       begin
  2920.         if Focused then
  2921.         begin
  2922.           FCanvas.Brush.Color := clHighlight;
  2923.           FCanvas.Font.Color := clHighlightText;
  2924.         end else begin
  2925.           if not HideSelection then
  2926.           begin
  2927.             FCanvas.Brush.Color := clBtnFace;
  2928.             FCanvas.Font.Color := clBtnText;
  2929.           end;
  2930.         end;
  2931.       end;
  2932.       SubRect := Rect;
  2933.       SubRect.Right := Rect.Left + CurrentColumnWidth[0] - 2;
  2934.       DefaultDrawSubItem(Index, -1, SubRect, State);
  2935.  
  2936.       // Already done column 0, start at 1.
  2937.       for Count := 1 to Columns.Count-1 do
  2938.       begin
  2939.         { Restore this through each iteration since they may screw with it in
  2940.           the OnDrawSubItem event. }
  2941.         if not FullRowSelect then
  2942.         begin
  2943.           FCanvas.Brush.Color := clWindow;
  2944.           FCanvas.Font.Color := clWindowText;
  2945.         end;
  2946.  
  2947.         if ActualColumn[Count].Alignment = taLeftJustify then
  2948.         begin
  2949.           SubRect.Left := SubRect.Right;
  2950.           SubRect.Right := SubRect.Left + CurrentColumnWidth[Count];
  2951.           Inc(SubRect.Left, DefDraw_TextOffset)
  2952.         end else begin
  2953.           SubRect.Left := SubRect.Right + DefDraw_TextOffset;
  2954.           SubRect.Right := SubRect.Left + CurrentColumnWidth[Count];
  2955.           Dec(SubRect.Right, DefDraw_TextOffset);
  2956.         end;
  2957.         DefaultDrawSubItem(Index, Count-1, SubRect, State);
  2958.       end;
  2959.     end;
  2960.   end else
  2961.     inherited DefaultDrawItem(Index, Rect, State, FullRowSelect);
  2962. end;
  2963.  
  2964. procedure TCustomExtListView.RestoreChecks;
  2965. var
  2966.   i, q: Integer;
  2967.   Value: Boolean;
  2968.   SubItem: integer;
  2969. begin
  2970.   for i := 0 to Items.Count - 1 do
  2971.   begin
  2972.     if FRecreateStream <> nil then
  2973.     begin
  2974.       FRecreateStream.Read(Value, SizeOf(Value));
  2975.       IsChecked[i] := Value;
  2976.       for q := 0 to Columns.Count - 2 do
  2977.       begin
  2978.         FRecreateStream.Read(SubItem, SizeOf(SubItem));
  2979.         SubItem_ImageIndex[i, q] := SubItem;
  2980.       end;
  2981.     end
  2982.     else
  2983.     begin
  2984.       IsChecked[i] := False;
  2985.       for q := 0 to Columns.Count - 2 do
  2986.         SubItem_ImageIndex[i, q] := ELV_NO_SUBITEM_IMAGE;
  2987.     end;
  2988.   end;
  2989.   FRecreateStream.Free;
  2990.   FRecreateStream := nil;
  2991. end;
  2992.  
  2993. procedure TCustomExtListView.SaveChecks;
  2994. var
  2995.   i, q: Integer;
  2996.   Value: Boolean;
  2997.   SubItem: integer;
  2998. begin
  2999.   if FRecreateStream = nil then
  3000.     FRecreateStream := TMemoryStream.Create
  3001.   else
  3002.     {$IFDEF DFS_COMPILER_2}
  3003.     FRecreateStream.Clear;
  3004.     {$ELSE}
  3005.     FRecreateStream.Size := 0;
  3006.     {$ENDIF}
  3007.   for i := 0 to Items.Count - 1 do
  3008.   begin
  3009.     Value := IsChecked[i];
  3010.     FRecreateStream.Write(Value, SizeOf(Value));
  3011.     for q := 0 to Columns.Count - 2 do
  3012.     begin
  3013.       SubItem := SubItem_ImageIndex[i, q];
  3014.       FRecreateStream.Write(SubItem, SizeOf(SubItem));
  3015.     end;
  3016.   end;
  3017.   FRecreateStream.Position := 0;
  3018. end;
  3019.  
  3020. procedure TCustomExtListView.DestroyWnd;
  3021. begin
  3022.   SaveChecks;
  3023.   inherited;
  3024. end;
  3025.  
  3026. {$IFDEF DFS_COMPILER_4_UP}
  3027. procedure TCustomExtListView.FeedOwnerDataMode(Sender: TObject; Item: TListItem);
  3028. var
  3029.   ItemData: TLVItemEx;
  3030.   x: integer;
  3031. begin
  3032.   if not FInhibitFeedData then // Try to prevent unnecessary calls
  3033.   begin
  3034.     ItemData.iItem := Item.Index;
  3035.     ItemData.iSubItem := 0;
  3036.     ItemData.mask := LVIF_TEXT or LVIF_IMAGE or LVIF_PARAM or LVIF_STATE or
  3037.       LVIF_INDENT;
  3038.     GetMem(ItemData.pszText, 1024);
  3039.     try
  3040.       VMGetDispInfo(ItemData);
  3041.       Item.Caption := ItemData.pszText;
  3042.       Item.ImageIndex := ItemData.iImage;
  3043.       Item.Data := pointer(ItemData.lParam);
  3044.       Item.Indent := ItemData.iIndent;
  3045.       ItemData.mask := LVIF_TEXT;
  3046.       for x := 1 to Columns.Count - 1 do
  3047.       begin
  3048.         VMGetDispInfo(ItemData);
  3049.         Item.SubItems.Add(ItemData.pszText);
  3050.       end;
  3051.     finally
  3052.       FreeMem(ItemData.pszText);
  3053.     end;
  3054.   end;
  3055. end;
  3056. {$ENDIF}
  3057.  
  3058.  
  3059. { TdfsExtListColumn }
  3060.  
  3061. constructor TdfsExtListColumn.Create(Collection: TCollection);
  3062. begin
  3063.   inherited Create(Collection);
  3064.   FSmallImageIndex := -1;
  3065.   FImageAlignment := ciaRightOfText;
  3066.   FAllowResize := TRUE;
  3067. end;
  3068.  
  3069. destructor TdfsExtListColumn.Destroy;
  3070. begin
  3071.   FSmallImageIndex := -1;
  3072.   FImageAlignment := ciaRightOfText;
  3073.  
  3074.   inherited Destroy;
  3075. end;
  3076.  
  3077. procedure TdfsExtListColumn.DoChange;
  3078. var
  3079.   i: Integer;
  3080. begin
  3081.   for i := 0 to Collection.Count-1 do
  3082.     Changed(i <> Collection.Count);
  3083. end;
  3084.  
  3085. procedure TdfsExtListColumn.SetSmallImageIndex(Value: Integer);
  3086. begin
  3087.   if FSmallImageIndex <> Value then
  3088.   begin
  3089.     FSmallImageIndex := Value;
  3090.     DoChange;
  3091.   end;
  3092. end;
  3093.  
  3094. procedure TdfsExtListColumn.SetImageAlignment(Value: TColumnImageAlign);
  3095. begin
  3096.   if FImageAlignment <> Value then
  3097.   begin
  3098.     FImageAlignment := Value;
  3099.     DoChange;
  3100.   end;
  3101. end;
  3102.  
  3103. procedure TdfsExtListColumn.Assign(Source: TPersistent);
  3104. var
  3105.   Column: TdfsExtListColumn;
  3106. begin
  3107.   if Source is TdfsExtListColumn then
  3108.   begin
  3109.     Column := TdfsExtListColumn(Source);
  3110.     ImageIndex := Column.ImageIndex;
  3111.     ImageAlignment  := Column.ImageAlignment;
  3112.   end else
  3113.     inherited Assign(Source);
  3114. end;
  3115.  
  3116. constructor TdfsExtListColumns.Create(AListView: TCustomExtListView);
  3117. begin
  3118.   inherited Create(TdfsExtListColumn);
  3119.   FListView := AListView;
  3120. end;
  3121.  
  3122. function TdfsExtListColumns.GetItem(Index: Integer): TdfsExtListColumn;
  3123. begin
  3124.   Result := TdfsExtListColumn(inherited GetItem(Index));
  3125. end;
  3126.  
  3127. procedure TdfsExtListColumns.SetItem(Index: Integer; Value: TdfsExtListColumn);
  3128. begin
  3129.   inherited SetItem(Index, Value);
  3130. end;
  3131.  
  3132. function TdfsExtListColumns.Add: TdfsExtListColumn;
  3133. begin
  3134.   Result := TdfsExtListColumn(inherited Add);
  3135. end;
  3136.  
  3137. function TdfsExtListColumns.GetOwner: TPersistent;
  3138. begin
  3139.   Result := FListView;
  3140. end;
  3141.  
  3142. procedure TdfsExtListColumns.Update(Item: TCollectionItem);
  3143. begin
  3144.   if ListView <> NIL then
  3145.   begin
  3146.     if Item <> NIL then
  3147.       ListView.UpdateColumnImage(Item.Index)
  3148.     else
  3149.       ListView.UpdateColumnsImages;
  3150.   end;
  3151. end;
  3152.  
  3153. procedure TdfsExtListColumns.Refresh;
  3154. begin
  3155.   if ListView <> NIL then
  3156.     ListView.UpdateColumnsImages;
  3157. end;
  3158.  
  3159. procedure TdfsExtListColumns.Assign(Source: TPersistent);
  3160. begin
  3161.   Clear;
  3162.   inherited Assign(Source);
  3163. end;
  3164.  
  3165. function CheckDLLVersion(const DLLName: string; MajorHi, MajorLo,
  3166.    MinorHi, MinorLo: word): boolean;
  3167. var
  3168.   VerInfoSize: DWORD;
  3169.   VerInfo: Pointer;
  3170.   VerValueSize: DWORD;
  3171.   VerValue: PVSFixedFileInfo;
  3172.   Dummy: DWORD;
  3173.   V1, V2, V3, V4: word;
  3174. begin
  3175.   Result := FALSE;
  3176.   VerInfoSize := GetFileVersionInfoSize(PChar(DLLName), Dummy);
  3177.   if VerInfoSize = 0 then
  3178.     exit;
  3179.   GetMem(VerInfo, VerInfoSize);
  3180.   if not assigned(VerInfo) then
  3181.     exit;
  3182.   try
  3183.     if GetFileVersionInfo(PChar(DLLName), 0, VerInfoSize, VerInfo) then
  3184.     begin
  3185.       if VerQueryValue(VerInfo, '\', Pointer(VerValue), VerValueSize) then
  3186.       begin
  3187.         with VerValue^ do
  3188.         begin
  3189.           V1 := dwFileVersionMS shr 16;
  3190.           V2 := dwFileVersionMS and $FFFF;
  3191.           V3 := dwFileVersionLS shr 16;
  3192.           V4 := dwFileVersionLS and $FFFF;
  3193.         end;
  3194.         { This would be SO much easier with D4's int64 type... }
  3195.         if V1 < MajorHi then
  3196.           Result := FALSE
  3197.         else if V1 > MajorHi then
  3198.           Result := TRUE
  3199.         else begin
  3200.           if V2 < MajorLo then
  3201.             Result := FALSE
  3202.           else if V2 > MajorLo then
  3203.             Result := TRUE
  3204.           else begin
  3205.             if V3 < MinorHi then
  3206.               Result := FALSE
  3207.             else if V3 > MinorHi then
  3208.               Result := TRUE
  3209.             else begin
  3210.               if V4 < MinorLo then
  3211.                 Result := FALSE
  3212.               else if V4 > MinorLo then
  3213.                 Result := TRUE;
  3214.             end;
  3215.           end;
  3216.         end;
  3217.       end;
  3218.     end;
  3219.   finally
  3220.     FreeMem(VerInfo, VerInfoSize);
  3221.   end;
  3222. end;
  3223.  
  3224.  
  3225. initialization
  3226. {$IFDEF DFS_TRY_BACKGROUND_IMAGE}
  3227. //  OleInitialize(NIL);
  3228.   CoInitialize(NIL);
  3229. {$ENDIF}
  3230. finalization
  3231. {$IFDEF DFS_TRY_BACKGROUND_IMAGE}
  3232. //  OleUninitialize;
  3233.   CoUninitialize;
  3234. {$ENDIF}
  3235. end.
  3236.  
  3237.