DragDropHandler.pas 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. unit DragDropHandler;
  2. // -----------------------------------------------------------------------------
  3. // Project: Drag and Drop Component Suite.
  4. // Module: DragDropHandler
  5. // Description: Implements Drop and Drop Context Menu Shell Extenxions
  6. // (a.k.a. drag-and-drop handlers).
  7. // Version: 4.0
  8. // Date: 18-MAY-2001
  9. // Target: Win32, Delphi 5-6
  10. // Authors: Anders Melander, anders@melander.dk, http://www.melander.dk
  11. // Copyright © 1997-2001 Angus Johnson & Anders Melander
  12. // -----------------------------------------------------------------------------
  13. interface
  14. uses
  15. DragDrop,
  16. DragDropComObj,
  17. DragDropContext,
  18. Menus,
  19. ShlObj,
  20. ActiveX,
  21. Windows,
  22. Classes;
  23. {$include DragDrop.inc}
  24. type
  25. ////////////////////////////////////////////////////////////////////////////////
  26. //
  27. // TDragDropHandler
  28. //
  29. ////////////////////////////////////////////////////////////////////////////////
  30. // A typical drag-and-drop handler session goes like this:
  31. // 1. User right-drags (drags with the right mouse button) and drops one or more
  32. // source files which has a registered drag-and-drop handler.
  33. // 2. The shell loads the drag-and-drop handler module.
  34. // 3. The shell instantiates the registered drag drop handler object as an
  35. // in-process COM server.
  36. // 4. The IShellExtInit.Initialize method is called with the name of the target
  37. // folder and a data object which contains the dragged data.
  38. // The target folder name is stored in the TDragDropHandler.TargetFolder
  39. // property as a string and in the TargetPIDL property as a PIDL.
  40. // 5. The IContextMenu.QueryContextMenu method is called to populate the popup
  41. // menu.
  42. // TDragDropHandler uses the PopupMenu property to populate the drag-and-drop
  43. // context menu.
  44. // 6. If the user chooses one of the context menu items we have supplied, the
  45. // IContextMenu.InvokeCommand method is called.
  46. // TDragDropHandler locates the corresponding TMenuItem and fires the menu
  47. // items OnClick event.
  48. // 7. The shell unloads the drag-and-drop handler module (usually after a few
  49. // seconds).
  50. ////////////////////////////////////////////////////////////////////////////////
  51. TDragDropHandler = class(TDropContextMenu, IShellExtInit, IContextMenu)
  52. private
  53. FFolderPIDL: pItemIDList;
  54. protected
  55. function GetFolder: string;
  56. { IShellExtInit }
  57. function Initialize(pidlFolder: PItemIDList; lpdobj: IDataObject;
  58. hKeyProgID: HKEY): HResult; stdcall;
  59. { IContextMenu }
  60. function QueryContextMenu(Menu: HMENU; indexMenu, idCmdFirst, idCmdLast,
  61. uFlags: UINT): HResult; stdcall;
  62. function InvokeCommand(var lpici: TCMInvokeCommandInfo): HResult; stdcall;
  63. function GetCommandString(idCmd, uType: UINT; pwReserved: PUINT;
  64. pszName: LPSTR; cchMax: UINT): HResult; stdcall;
  65. public
  66. destructor Destroy; override;
  67. function GetFolderPIDL: pItemIDList; // Caller must free PIDL!
  68. property Folder: string read GetFolder;
  69. end;
  70. ////////////////////////////////////////////////////////////////////////////////
  71. //
  72. // TDragDropHandlerFactory
  73. //
  74. ////////////////////////////////////////////////////////////////////////////////
  75. // COM Class factory for TDragDropHandler.
  76. ////////////////////////////////////////////////////////////////////////////////
  77. TDragDropHandlerFactory = class(TDropContextMenuFactory)
  78. protected
  79. function HandlerRegSubKey: string; override;
  80. end;
  81. ////////////////////////////////////////////////////////////////////////////////
  82. //
  83. // Component registration
  84. //
  85. ////////////////////////////////////////////////////////////////////////////////
  86. procedure Register;
  87. ////////////////////////////////////////////////////////////////////////////////
  88. //
  89. // Misc.
  90. //
  91. ////////////////////////////////////////////////////////////////////////////////
  92. ////////////////////////////////////////////////////////////////////////////////
  93. ////////////////////////////////////////////////////////////////////////////////
  94. //
  95. // IMPLEMENTATION
  96. //
  97. ////////////////////////////////////////////////////////////////////////////////
  98. ////////////////////////////////////////////////////////////////////////////////
  99. implementation
  100. uses
  101. DragDropFile,
  102. DragDropPIDL,
  103. Registry,
  104. ComObj,
  105. SysUtils;
  106. ////////////////////////////////////////////////////////////////////////////////
  107. //
  108. // Component registration
  109. //
  110. ////////////////////////////////////////////////////////////////////////////////
  111. procedure Register;
  112. begin
  113. RegisterComponents(DragDropComponentPalettePage, [TDragDropHandler]);
  114. end;
  115. ////////////////////////////////////////////////////////////////////////////////
  116. //
  117. // Utilities
  118. //
  119. ////////////////////////////////////////////////////////////////////////////////
  120. ////////////////////////////////////////////////////////////////////////////////
  121. //
  122. // TDragDropHandler
  123. //
  124. ////////////////////////////////////////////////////////////////////////////////
  125. destructor TDragDropHandler.Destroy;
  126. begin
  127. if (FFolderPIDL <> nil) then
  128. ShellMalloc.Free(FFolderPIDL);
  129. inherited Destroy;
  130. end;
  131. function TDragDropHandler.GetCommandString(idCmd, uType: UINT;
  132. pwReserved: PUINT; pszName: LPSTR; cchMax: UINT): HResult;
  133. begin
  134. Result := inherited GetCommandString(idCmd, uType, pwReserved, pszName, cchMax);
  135. end;
  136. function TDragDropHandler.GetFolder: string;
  137. begin
  138. Result := GetFullPathFromPIDL(FFolderPIDL);
  139. end;
  140. function TDragDropHandler.GetFolderPIDL: pItemIDList;
  141. begin
  142. Result := CopyPIDL(FFolderPIDL);
  143. end;
  144. function TDragDropHandler.InvokeCommand(var lpici: TCMInvokeCommandInfo): HResult;
  145. begin
  146. Result := E_FAIL;
  147. try
  148. Result := inherited InvokeCommand(lpici);
  149. finally
  150. if (Result <> E_FAIL) then
  151. begin
  152. ShellMalloc.Free(FFolderPIDL);
  153. FFolderPIDL := nil;
  154. end;
  155. end;
  156. end;
  157. function TDragDropHandler.QueryContextMenu(Menu: HMENU; indexMenu, idCmdFirst,
  158. idCmdLast, uFlags: UINT): HResult;
  159. begin
  160. Result := inherited QueryContextMenu(Menu, indexMenu, idCmdFirst,
  161. idCmdLast, uFlags);
  162. end;
  163. function TDragDropHandler.Initialize(pidlFolder: PItemIDList;
  164. lpdobj: IDataObject; hKeyProgID: HKEY): HResult;
  165. begin
  166. if (pidlFolder <> nil) then
  167. begin
  168. // Copy target folder PIDL.
  169. FFolderPIDL := CopyPIDL(pidlFolder);
  170. Result := inherited Initialize(pidlFolder, lpdobj, hKeyProgID);
  171. end else
  172. Result := E_INVALIDARG;
  173. end;
  174. ////////////////////////////////////////////////////////////////////////////////
  175. //
  176. // TDragDropHandlerFactory
  177. //
  178. ////////////////////////////////////////////////////////////////////////////////
  179. function TDragDropHandlerFactory.HandlerRegSubKey: string;
  180. begin
  181. Result := 'DragDropHandlers';
  182. end;
  183. end.