home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 September / Chip_2001-09_cd1.bin / zkuste / delphi / kolekce / d123456 / DFS.ZIP / pidlhelp.pas < prev    next >
Pascal/Delphi Source File  |  1999-02-23  |  15KB  |  408 lines

  1. {$I DFS.INC}        { Standard defines for all Delphi Free Stuff components }
  2.  
  3. { -----------------------------------------------------------------------------}
  4. { PidlHelp Unit v1.00                                                          }
  5. { -----------------------------------------------------------------------------}
  6. { System Control Pack helper unit.  Lots of utility functions for working with }
  7. { PItemIDList variables.                                                       }
  8. {                                                                              }
  9. { Copyright 1999, Brad Stowers.  All Rights Reserved.                          }
  10. {                                                                              }
  11. { Copyright:                                                                   }
  12. { All Delphi Free Stuff (hereafter "DFS") source code is copyrighted by        }
  13. { Bradley D. Stowers (hereafter "author"), and shall remain the exclusive      }
  14. { property of the author.                                                      }
  15. {                                                                              }
  16. { Distribution Rights:                                                         }
  17. { You are granted a non-exlusive, royalty-free right to produce and distribute }
  18. { compiled binary files (executables, DLLs, etc.) that are built with any of   }
  19. { the DFS source code unless specifically stated otherwise.                    }
  20. { You are further granted permission to redistribute any of the DFS source     }
  21. { code in source code form, provided that the original archive as found on the }
  22. { DFS web site (http://www.delphifreestuff.com) is distributed unmodified. For }
  23. { example, if you create a descendant of TDFSColorButton, you must include in  }
  24. { the distribution package the colorbtn.zip file in the exact form that you    }
  25. { downloaded it from http://www.delphifreestuff.com/mine/files/colorbtn.zip.   }
  26. {                                                                              }
  27. { Restrictions:                                                                }
  28. { Without the express written consent of the author, you may not:              }
  29. {   * Distribute modified versions of any DFS source code by itself. You must  }
  30. {     include the original archive as you found it at the DFS site.            }
  31. {   * Sell or lease any portion of DFS source code. You are, of course, free   }
  32. {     to sell any of your own original code that works with, enhances, etc.    }
  33. {     DFS source code.                                                         }
  34. {   * Distribute DFS source code for profit.                                   }
  35. {                                                                              }
  36. { Warranty:                                                                    }
  37. { There is absolutely no warranty of any kind whatsoever with any of the DFS   }
  38. { source code (hereafter "software"). The software is provided to you "AS-IS", }
  39. { and all risks and losses associated with it's use are assumed by you. In no  }
  40. { event shall the author of the softare, Bradley D. Stowers, be held           }
  41. { accountable for any damages or losses that may occur from use or misuse of   }
  42. { the software.                                                                }
  43. {                                                                              }
  44. { Support:                                                                     }
  45. { All DFS source code is provided free of charge. As such, I can not guarantee }
  46. { any support whatsoever. While I do try to answer all questions that I        }
  47. { receive, and address all problems that are reported to me, you must          }
  48. { understand that I simply can not guarantee that this will always be so.      }
  49. {                                                                              }
  50. { Clarifications:                                                              }
  51. { If you need any further information, please feel free to contact me directly.}
  52. { This agreement can be found online at my site in the "Miscellaneous" section.}
  53. {------------------------------------------------------------------------------}
  54. { Feel free to contact me if you have any questions, comments or suggestions   }
  55. { at bstowers@pobox.com.                                                       }
  56. { The lateset version of my components are always available on the web at:     }
  57. {   http://www.delphifreestuff.com/                                            }
  58. { See SCP.txt for notes, known issues, and revision history.                   }
  59. { -----------------------------------------------------------------------------}
  60. { Date last modified:  February 23, 1999                                       }
  61. { -----------------------------------------------------------------------------}
  62.  
  63. unit PidlHelp;
  64.  
  65. interface
  66.  
  67. uses
  68.   {$IFDEF DFS_COMPILER_3_UP}
  69.   ShlObj, ActiveX,
  70.   {$ELSE}
  71.   MyShlObj, OLE2,
  72.   {$ENDIF}
  73.   Windows;
  74.  
  75. type
  76.   // These map to the SHGDN_xxx constants.  uses in GetDisplayName function.
  77.   TDisplayNameType = (dntNormal, dntInFolder, dntForParsing);
  78.  
  79. // Create a new, empty PIDL of the given size.  Mostly useful only for the other
  80. // helpers like CopyPIDL and ConcatPIDLs.  Result must be released with FreePIDL
  81. function CreatePIDL(Size: UINT): PItemIDList;
  82.  
  83. // Release the system memory associated with the PIDL.  Checks for NIL first.
  84. procedure FreePIDL(var AnID: PItemIDList);
  85.  
  86. // Returns how much memory the PIDL uses.
  87. function GetPidlSize(pidl: PItemIDList): integer;
  88.  
  89. // Create a new PIDL by adding ID2 onto the end of ID1. Result must be Free
  90. // with FreePIDL.
  91. function ConcatPIDLs(ID1, ID2: PItemIDList): PItemIDList;
  92.  
  93. // Create a new PItemIDList from an existing one. Result must be released with
  94. // FreePIDL.
  95. function CopyPIDL(AnID: PItemIDList): PItemIDList;
  96.  
  97. // Compare two PIDLs to see if they are the same.
  98. function ComparePIDLs(ID1, ID2: PItemIDList): boolean;
  99.  
  100. // Returns to the next ID in the given list of IDs.  The return value is only a
  101. // pointer into the real PIDL, so don't free it or rely on it if the list is
  102. // released.
  103. function NextPIDL(PIDL: PItemIDList): PItemIDList;
  104.  
  105. // Returns the number of IDs in the ID list.
  106. function PIDLCount(PIDL: PItemIDList): integer;
  107.  
  108. // Create copy of the current (first) ID from the ID list.  This is used to
  109. // create a relative PIDL from part of a fully qualified PIDL.  The result must
  110. // be released with FreePIDL.
  111. function CopyFirstID(AnID: PItemIDList): PItemIDList;
  112.  
  113. // Create a copy of the last ID in the ID list.  This is used to create a
  114. // relative PIDL from part of a fully qualified PIDL.  The result must be
  115. // released with FreePIDL.
  116. function CopyLastID(IDList: PItemIDList): PItemIDList;
  117.  
  118. // Create a new PIDL that contains all IDs except for the last. The result must
  119. // be released with FreePIDL.
  120. function CopyParentPIDL(var IDList: PItemIDList): PItemIDList;
  121.  
  122. // Return the "display name" for a PIDL.  This is the string that Explorer shows
  123. // to the user, and it changes based on user settings.  For example, for a file
  124. // name the extension may or may not be shown based on the user's preferences.
  125. function GetDisplayName(const ShellFolder: IShellFolder; IDList: PItemIDList;
  126.    NameType: TDisplayNameType): string;
  127.  
  128. // Get a PItemIDList that represents the given pathname.  The var ID parameter
  129. // must be released with FreePIDL.
  130. function GetPIDLFromPath(Handle: HWND; const ShellFolder: IShellFolder;
  131.    const APath: string; var ID: PItemIDList): boolean;
  132.  
  133. // Get the image index of the PIDL in the system image list.  Use this only for
  134. // fully qualified PIDLs.  Relative won't work.
  135. function GetIconIndex(IDList: PItemIDList; Flags: UINT): integer;
  136.  
  137. // Get the image index of the PIDL in the system image list for normal and
  138. // selected icons.  Use this only for fully qualified PIDLs.  Relative won't
  139. // work.
  140. procedure GetNormalAndSelectedIcons(IDList: PItemIDList; var Normal,
  141.    Selected: integer);
  142.  
  143.  
  144. var
  145.   // Used throught this unit.  It's a shared thing provided by the system, so
  146.   // this variable can be used whereever you might need it.  It's created in
  147.   // the unit initialization and released in finalization.
  148.   ShellMalloc: IMalloc;
  149.  
  150.  
  151. implementation
  152.  
  153.  
  154. uses
  155.   ShellAPI;
  156.  
  157.  
  158. function GetPidlSize(pidl: PItemIDList): integer;
  159. begin
  160.   Result := 0;
  161.   if pidl <> NIL then
  162.   begin
  163.     Inc(Result, SizeOf(pidl^.mkid.cb));
  164.     while pidl^.mkid.cb <> 0 do
  165.     begin
  166.       Inc(Result, pidl^.mkid.cb);
  167.       Inc(longint(pidl), pidl^.mkid.cb);
  168.     end;
  169.   end;
  170. end;
  171.  
  172. function CreatePIDL(Size: UINT): PItemIDList;
  173. begin
  174.   Result := ShellMalloc.Alloc(Size);
  175.   if Result <> NIL then
  176.     FillChar(Result^, Size, #0);
  177. end;
  178.  
  179. procedure FreePIDL(var AnID: PItemIDList);
  180. begin
  181.   if AnID <> NIL then
  182.   begin
  183.     ShellMalloc.Free(AnID);
  184.     AnID := NIL;
  185.   end;
  186. end;
  187.  
  188. function ConcatPIDLs(ID1, ID2: PItemIDList): PItemIDList;
  189. var
  190.   S1, S2: UINT;
  191. begin
  192.   if (ID1 <> NIL) then
  193.     S1 := GetPIDLSize(ID1) - SizeOf(ID1.mkid.cb)
  194.   else
  195.     S1 := 0;
  196.   S2 := GetPIDLSize(ID2);
  197.  
  198.   Result := CreatePIDL(S1 + S2);
  199.   if Result <> NIL then
  200.   begin
  201.     if (ID1 <> NIL) then
  202.       Move(ID1^, Result^, S1);
  203.     Move(ID2^, PChar(Result)[S1], S2);
  204.   end;
  205. end;
  206.  
  207. // Create a new PItemIDList from existing.  Call responsible for freeing it.
  208. function CopyPIDL(AnID: PItemIDList): PItemIDList;
  209. var
  210.   Size: integer;
  211. begin
  212.   Size := GetPidlSize(AnID);
  213.   if Size > 0 then
  214.   begin
  215.     Result := ShellMalloc.Alloc(Size); // Create the memory
  216.     FillChar(Result^, Size, #0); // Initialize the memory to zero
  217.     Move(AnID^, Result^, Size); // Copy the current ID
  218.   end else
  219.     Result := NIL;
  220. end;
  221.  
  222. function ComparePIDLs(ID1, ID2: PItemIDList): boolean;
  223. var
  224.   S1, S2, x: UINT;
  225. begin
  226.   Result := FALSE;
  227.   if (ID1 = NIL) and (ID2 = NIL) then
  228.   begin
  229.     Result := TRUE;
  230.     exit;
  231.   end;
  232.   if (ID1 = NIL) or (ID2 = NIL) then exit;
  233.  
  234.   S1 := GetPIDLSize(ID1);
  235.   S2 := GetPIDLSize(ID2);
  236.   if S1 <> S2 then exit;
  237.  
  238.   Result := TRUE;
  239.   for x := 0 to pred(S1) do
  240.   begin
  241.     if PChar(ID1)[x] <> PChar(ID2)[x] then
  242.     begin
  243.       Result := FALSE;
  244.       exit;
  245.     end;
  246.   end;
  247. end;
  248.  
  249. // Returns to the next ID in the given list of IDs
  250. function NextPIDL(PIDL: PItemIDList): PItemIDList;
  251. begin
  252.   if PIDL.mkid.cb > 0 then
  253.     Result := PItemIDList(Longint(PIDL) + PIDL.mkid.cb)
  254.   else // At end of list.
  255.     Result := NIL;
  256. end;
  257.  
  258. // Returns the number of IDs in the ID list.
  259. function PIDLCount(PIDL: PItemIDList): integer;
  260. begin
  261.   Result := 0;
  262.   if PIDL <> NIL then
  263.   begin
  264.     while PIDL.mkid.cb > 0 do
  265.     begin
  266.       PIDL := NextPIDL(PIDL);
  267.       inc(Result);
  268.     end;
  269.   end;
  270. end;
  271.  
  272. // Create copy of the current ID from the ID list.  This is used to create a
  273. // relative PIDL from part of a fully qualified PIDL.
  274. function CopyFirstID(AnID: PItemIDList): PItemIDList;
  275. var
  276.   Size: integer;
  277. begin
  278.   // How much memory do we need?  Note that this allocates enough memory for
  279.   // the current ID, plus enough for the mkid.cb member of another one.  The
  280.   // extra is used as the "termintor" of the PIDL.  It is set to zero in the
  281.   // FillChar below.
  282.   Size := AnID.mkid.cb + SizeOf(AnID.mkid.cb);
  283.   Result := ShellMalloc.Alloc(Size); // Create the memory
  284.   if Result = NIL then exit; // If the shell couldn't allocate memory, get out
  285.   FillChar(Result^, Size, #0); // Initialize the memory to zero
  286.   Move(AnID^, Result^, AnID.mkid.cb); // Copy the current ID
  287. end;
  288.  
  289. function CopyLastID(IDList: PItemIDList): PItemIDList;
  290. var
  291.   MarkerID: PItemIDList;
  292. begin
  293.   Result := NIL;
  294.   MarkerID := IDList;
  295.   if IDList <> NIL then
  296.   begin
  297.     while IDList.mkid.cb <> 0 do
  298.     begin
  299.       MarkerID := IDList;
  300.       IDList := NextPIDL(IDList);
  301.     end;
  302.     Result := CopyPIDL(MarkerID);
  303.   end;
  304. end;
  305.  
  306. function CopyParentPIDL(var IDList: PItemIDList): PItemIDList;
  307. var
  308.   Last, Size: integer;
  309.   Source: PItemIDList;
  310. begin
  311.   Size := 0;
  312.   Last := 0;
  313.   if IDList <> NIL then
  314.   begin
  315.     Source := IDList;
  316.     Inc(Size, SizeOf(Source^.mkid.cb));
  317.     while Source^.mkid.cb <> 0 do
  318.     begin
  319.       Last := Source^.mkid.cb;
  320.       Inc(Size, Source^.mkid.cb);
  321.       Inc(Longint(Source), Source^.mkid.cb);
  322.     end;
  323.     Dec(Size, Last);
  324.   end;
  325.  
  326.   if Size > 0 then
  327.   begin
  328.     Result := ShellMalloc.Alloc(Size); // Create the memory
  329.     FillChar(Result^, Size, #0); // Initialize the memory to zero
  330.     Move(IDList^, Result^, Size - SizeOf(Source^.mkid.cb)); // Copy the current ID
  331.   end else
  332.     Result := NIL;
  333. end;
  334.  
  335. function GetDisplayName(const ShellFolder: IShellFolder; IDList: PItemIDList;
  336.    NameType: TDisplayNameType): string;
  337. const
  338.   NAMETYPEAPI: array[TDisplayNameType] of DWORD = (SHGDN_NORMAL, SHGDN_INFOLDER,
  339.      SHGDN_FORPARSING);
  340. var
  341.   Str: TStrRet;
  342. begin
  343.   if ShellFolder.GetDisplayNameOf(IDList, NAMETYPEAPI[NameType],
  344.      Str) = NOERROR then
  345.   begin
  346.     case Str.uType of
  347.       STRRET_WSTR:   Result := WideCharToString(Str.pOleStr);
  348.       STRRET_OFFSET: Result := PChar(UINT(IDList) + Str.uOffset);
  349.       STRRET_CSTR:   Result := Str.cStr;
  350.     else
  351.       Result := '';
  352.     end;
  353.   end else
  354.     Result := '';
  355. end;
  356.  
  357. function GetPIDLFromPath(Handle: HWND; const ShellFolder: IShellFolder;
  358.    const APath: string; var ID: PItemIDList): boolean;
  359. var
  360.   OLEStr: array[0..MAX_PATH] of TOLEChar;
  361.   Eaten: ULONG;
  362.   Attr: ULONG;
  363. begin
  364.   try
  365.     Result := Succeeded(ShellFolder.ParseDisplayName(Handle, NIL,
  366.        StringToWideChar(APath, OLEStr, MAX_PATH), Eaten, ID, Attr));
  367.   except
  368.     Result := FALSE;
  369.   end;
  370. end;
  371.  
  372.  
  373. // Use this only for fully qualified PIDLs.  Relative won't work.
  374. function GetIconIndex(IDList: PItemIDList; Flags: UINT): integer;
  375. var
  376.   SFI: TSHFileInfo;
  377. begin
  378.   if SHGetFileInfo(PChar(IDList), 0, SFI, SizeOf(TSHFileInfo), Flags) = 0 then
  379.     Result := -1
  380.   else
  381.     Result := SFI.iIcon;
  382. end;
  383.  
  384. // Use this only for fully qualified PIDLs.  Relative won't work.
  385. procedure GetNormalAndSelectedIcons(IDList: PItemIDList; var Normal,
  386.    Selected: integer);
  387. begin
  388.   Normal := GetIconIndex(IDList, SHGFI_PIDL or SHGFI_SYSICONINDEX or
  389.      SHGFI_SMALLICON);
  390.   Selected := GetIconIndex(IDList, SHGFI_PIDL or SHGFI_SYSICONINDEX or
  391.      SHGFI_SMALLICON or SHGFI_OPENICON);
  392. end;
  393.  
  394.  
  395. initialization
  396.   // Get the shell memory allocation interface that everyone uses.
  397.   SHGetMalloc(ShellMalloc);
  398.  
  399. finalization
  400.   // Release the shell memory allocation interface.
  401. {$IFDEF DFS_COMPILER_2}
  402.   ShellMalloc.Release;
  403. {$ENDIF}
  404.  
  405. end.
  406.  
  407.  
  408.