DropURL.pas 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. unit DropURL;
  2. interface
  3. {$include DragDrop.inc}
  4. uses
  5. {$ifdef VER12_PLUS}
  6. ImgList,
  7. {$endif}
  8. DragDrop,
  9. DropSource,
  10. DropTarget,
  11. DragDropGraphics,
  12. DragDropInternet,
  13. Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  14. StdCtrls, ComCtrls, ExtCtrls, ActiveX, CommCtrl, Menus;
  15. type
  16. TFormURL = class(TForm)
  17. Panel1: TPanel;
  18. ButtonClose: TButton;
  19. StatusBar1: TStatusBar;
  20. Memo2: TMemo;
  21. DropURLTarget1: TDropURLTarget;
  22. DropURLSource1: TDropURLSource;
  23. DropBMPSource1: TDropBMPSource;
  24. DropBMPTarget1: TDropBMPTarget;
  25. PanelImageTarget: TPanel;
  26. ImageTarget: TImage;
  27. Panel3: TPanel;
  28. Memo1: TMemo;
  29. PanelImageSource2: TPanel;
  30. ImageSource2: TImage;
  31. LabelURL: TLabel;
  32. ImageList1: TImageList;
  33. PanelImageSource1: TPanel;
  34. ImageSource1: TImage;
  35. DropDummy1: TDropDummy;
  36. PopupMenu1: TPopupMenu;
  37. MenuCopy: TMenuItem;
  38. MenuCut: TMenuItem;
  39. N1: TMenuItem;
  40. MenuPaste: TMenuItem;
  41. PanelURL: TPanel;
  42. procedure ButtonCloseClick(Sender: TObject);
  43. procedure FormCreate(Sender: TObject);
  44. procedure FormDestroy(Sender: TObject);
  45. procedure URLMouseDown(Sender: TObject; Button: TMouseButton;
  46. Shift: TShiftState; X, Y: Integer);
  47. procedure ImageMouseDown(Sender: TObject; Button: TMouseButton;
  48. Shift: TShiftState; X, Y: Integer);
  49. procedure DropURLTarget1Drop(Sender: TObject; ShiftState: TShiftState;
  50. Point: TPoint; var Effect: Integer);
  51. procedure DropBMPTarget1Drop(Sender: TObject; ShiftState: TShiftState;
  52. Point: TPoint; var Effect: Integer);
  53. procedure MenuCutOrCopyClick(Sender: TObject);
  54. procedure MenuPasteClick(Sender: TObject);
  55. procedure PopupMenu1Popup(Sender: TObject);
  56. procedure DropBMPSource1Paste(Sender: TObject; Action: TDragResult;
  57. DeleteOnPaste: Boolean);
  58. private
  59. PasteImage: TImage; // Remembers which TImage is the source of a copy/paste
  60. public
  61. end;
  62. var
  63. FormURL: TFormURL;
  64. implementation
  65. {$R *.DFM}
  66. uses
  67. ComObj;
  68. function GetTransparentColor(const bmp: TBitmap): TColor;
  69. begin
  70. if (bmp = nil) or (bmp.empty) then
  71. Result := clWhite
  72. else
  73. Result := bmp.TransparentColor;
  74. end;
  75. procedure TFormURL.FormCreate(Sender: TObject);
  76. begin
  77. // Note: This is an example of "manual" target registration. We could just
  78. // as well have assigned the TDropTarget.Target property at design-time to
  79. // register the drop targets.
  80. // Register the URL and BMP DropTarget controls.
  81. DropURLTarget1.Register(PanelURL);
  82. DropBMPTarget1.Register(PanelImageTarget);
  83. // This enables the dragged image to be visible
  84. // over the whole form, not just the above targets.
  85. DropDummy1.Register(Self);
  86. end;
  87. procedure TFormURL.FormDestroy(Sender: TObject);
  88. begin
  89. // Note: This is an example of "manual" target unregistration. However,
  90. // Since the targets are automatically unregistered when they are destroyed,
  91. // it is not nescessary to do it manually.
  92. // UnRegister the DropTarget windows.
  93. DropURLTarget1.UnRegister;
  94. DropBMPTarget1.UnRegister;
  95. DropDummy1.UnRegister;
  96. end;
  97. procedure TFormURL.ButtonCloseClick(Sender: TObject);
  98. begin
  99. Close;
  100. end;
  101. //------------------------------------------------------------------------------
  102. // URL stuff ...
  103. //------------------------------------------------------------------------------
  104. type
  105. // TWinControlCracker is used to gain access to the protected memebers of
  106. // TWinControl.
  107. TWinControlCracker = class(TWinControl);
  108. procedure TFormURL.URLMouseDown(Sender: TObject; Button: TMouseButton;
  109. Shift: TShiftState; X, Y: Integer);
  110. var
  111. DragImage: TBitmap;
  112. begin
  113. // Wait for user to move cursor before we start the drag/drop.
  114. if (DragDetectPlus(TWincontrol(Sender).Handle, Point(X,Y))) then
  115. begin
  116. // This demonstrates how to create a drag image based on the source control.
  117. // Note: DropURLSource1.Images = ImageList1
  118. DragImage := TBitmap.Create;
  119. try
  120. DragImage.Width := TWinControl(Sender).Width;
  121. DragImage.Height := TWinControl(Sender).Height;
  122. TWinControl(Sender).PaintTo(DragImage.Canvas.Handle, 0, 0);
  123. ImageList1.Width := DragImage.Width;
  124. ImageList1.Height := DragImage.Height;
  125. ImageList1.Add(DragImage, nil);
  126. finally
  127. DragImage.Free;
  128. end;
  129. DropURLSource1.ImageHotSpotX := X;
  130. DropURLSource1.ImageHotSpotY := Y;
  131. DropURLSource1.ImageIndex := 0;
  132. try
  133. // Copy the data into the drop source.
  134. DropURLSource1.Title := PanelURL.Caption;
  135. DropURLSource1.URL := LabelURL.Caption;
  136. // Temporarily disable Edit1 as a drop target.
  137. DropURLTarget1.DragTypes := [];
  138. try
  139. DropURLSource1.Execute;
  140. finally
  141. // Enable Edit1 as a drop target again.
  142. DropURLTarget1.DragTypes := [dtLink];
  143. end;
  144. finally
  145. // Now that the drag has completed we don't need the image list anymore.
  146. ImageList1.Clear;
  147. end;
  148. end;
  149. end;
  150. procedure TFormURL.DropURLTarget1Drop(Sender: TObject;
  151. ShiftState: TShiftState; Point: TPoint; var Effect: Integer);
  152. begin
  153. // An URL has been dropped - Copy the URL and title from the drop target.
  154. PanelURL.Caption := DropURLTarget1.Title;
  155. LabelURL.Caption := DropURLTarget1.URL;
  156. end;
  157. //------------------------------------------------------------------------------
  158. // Bitmap stuff ...
  159. //------------------------------------------------------------------------------
  160. procedure TFormURL.ImageMouseDown(Sender: TObject; Button: TMouseButton;
  161. Shift: TShiftState; X, Y: Integer);
  162. var
  163. p: TPoint;
  164. begin
  165. if (Button = mbRight) or (TImage(Sender).Picture.Graphic = nil) then
  166. exit;
  167. // Since the TImage component hasn't got a window handle, we must
  168. // use the TPanel behind it instead...
  169. // First convert the mouse coordinates from Image relative coordinates
  170. // to screen coordinates...
  171. p := Point(X,Y);
  172. p := TImage(Sender).ClientToScreen(p);
  173. // ...and then back to to TPanel relative ones.
  174. p := TImage(Sender).Parent.ScreenToClient(p);
  175. // Now that the coordinates are relative to the panel, we can use
  176. // the panel's window handle for DragDetectPlus:
  177. if (DragDetectPlus(TImage(Sender).Parent.Handle, Point(X,Y))) then
  178. begin
  179. // Freeze clipboard contents if we have live data on it.
  180. // This is only nescessary because the TGraphic based data formats (such as
  181. // TBitmapDataFormat) doesn't support auto flushing.
  182. if (DropBMPSource1.LiveDataOnClipboard) then
  183. DropBMPSource1.FlushClipboard;
  184. // Copy the data into the drop source.
  185. DropBMPSource1.Bitmap.Assign(TImage(Sender).Picture.Graphic);
  186. // This just demonstrates dynamically allocating a drag image.
  187. // Note: DropBMPSource1.Images = ImageList1
  188. ImageList1.Width := DropBMPSource1.Bitmap.Width;
  189. ImageList1.Height := DropBMPSource1.Bitmap.Height;
  190. ImageList1.AddMasked(DropBMPSource1.Bitmap,
  191. GetTransparentColor(DropBMPSource1.Bitmap));
  192. DropBMPSource1.ImageIndex := 0;
  193. try
  194. // Perform the drag.
  195. if (DropBMPSource1.Execute = drDropMove) then
  196. // Clear the source image if image were drag-moved.
  197. TImage(Sender).Picture.Graphic := nil;
  198. finally
  199. // Now that the drag has completed we don't need the image list anymore.
  200. ImageList1.Clear;
  201. end;
  202. end;
  203. end;
  204. procedure TFormURL.PopupMenu1Popup(Sender: TObject);
  205. var
  206. PopupSource: TComponent;
  207. DataObject: IDataObject;
  208. begin
  209. PopupSource := TPopupMenu(Sender).PopupComponent;
  210. // Enable cut and copy for source image unless it is empty.
  211. if (PopupSource = ImageSource1) or (PopupSource = ImageSource2) then
  212. begin
  213. MenuCopy.Enabled := (TImage(PopupSource).Picture.Graphic <> nil);
  214. MenuCut.Enabled := MenuCopy.Enabled;
  215. MenuPaste.Enabled := False;
  216. end else
  217. // Enable paste for target image if the clipboard contains a bitmap.
  218. if (PopupSource = ImageTarget) then
  219. begin
  220. MenuCopy.Enabled := False;
  221. MenuCut.Enabled := False;
  222. // Open the clipboard as an IDataObject
  223. OleCheck(OleGetClipboard(DataObject));
  224. try
  225. // Enable paste menu if the clipboard contains data in any of
  226. // the supported formats.
  227. MenuPaste.Enabled := DropBMPTarget1.HasValidFormats(DataObject);
  228. finally
  229. DataObject := nil;
  230. end;
  231. end;
  232. end;
  233. procedure TFormURL.MenuCutOrCopyClick(Sender: TObject);
  234. begin
  235. // Clear the current content of the clipboard.
  236. // This isn't strictly nescessary, but can improve performance; If the drop
  237. // source has live data on the clipboard and the drop source data is modified,
  238. // the drop source will copy all its current data to the clipboard and then
  239. // disconnect itself from it. It does this in order to preserve the clipboard
  240. // data in the state it was in when the data were copied to the clipboard.
  241. // Since we are about to copy new data to the clipboard, we might as well save
  242. // the drop source all this unnescessary work.
  243. DropBMPSource1.EmptyClipboard;
  244. // Remember which TImage component the data originated from. This is used so
  245. // we can clear the image if a "delete on paste" is performed.
  246. PasteImage := TImage(TPopupMenu(TMenuItem(Sender).GetParentMenu).PopupComponent);
  247. DropBMPSource1.Bitmap.Assign(PasteImage.Picture.Graphic);
  248. if (Sender = MenuCut) then
  249. DropBMPSource1.CutToClipboard
  250. else
  251. DropBMPSource1.CopyToClipboard;
  252. StatusBar1.SimpleText := 'Bitmap copied to clipboard';
  253. end;
  254. procedure TFormURL.DropBMPSource1Paste(Sender: TObject;
  255. Action: TDragResult; DeleteOnPaste: Boolean);
  256. begin
  257. // When the target signals that it has pasted the image (after a
  258. // CutToClipboard operation), we can safely delete the source image.
  259. // This is an example of a "Delete on paste" operation.
  260. if (DeleteOnPaste) then
  261. PasteImage.Picture.Assign(nil);
  262. StatusBar1.SimpleText := 'Bitmap pasted from clipboard';
  263. end;
  264. procedure TFormURL.MenuPasteClick(Sender: TObject);
  265. begin
  266. // PasteFromClipboard fires an OnDrop event, so we don't need to do
  267. // anything special here.
  268. DropBMPTarget1.PasteFromClipboard;
  269. StatusBar1.SimpleText := 'Bitmap pasted from clipboard';
  270. end;
  271. procedure TFormURL.DropBMPTarget1Drop(Sender: TObject;
  272. ShiftState: TShiftState; Point: TPoint; var Effect: Integer);
  273. begin
  274. // An image has just been dropped on the target - Copy it to
  275. // our TImage component
  276. ImageTarget.Picture.Assign(DropBMPTarget1.Bitmap);
  277. end;
  278. end.