DropText.pas 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. unit DropText;
  2. interface
  3. uses
  4. DragDrop,
  5. DropSource,
  6. DropTarget,
  7. DragDropText,
  8. Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  9. StdCtrls, Buttons, ExtCtrls, ComCtrls, ActiveX;
  10. type
  11. TFormText = class(TForm)
  12. Memo1: TMemo;
  13. DropSource1: TDropTextSource;
  14. ButtonClose: TButton;
  15. Edit2: TEdit;
  16. StatusBar1: TStatusBar;
  17. Memo2: TMemo;
  18. Edit1: TEdit;
  19. ButtonClipboard: TButton;
  20. Panel1: TPanel;
  21. DropTextTarget1: TDropTextTarget;
  22. DropTextTarget2: TDropTextTarget;
  23. DropDummy1: TDropDummy;
  24. procedure ButtonCloseClick(Sender: TObject);
  25. procedure FormCreate(Sender: TObject);
  26. procedure FormDestroy(Sender: TObject);
  27. procedure Edit1MouseDown(Sender: TObject; Button: TMouseButton;
  28. Shift: TShiftState; X, Y: Integer);
  29. procedure ButtonClipboardClick(Sender: TObject);
  30. procedure Edit2MouseMove(Sender: TObject; Shift: TShiftState; X,
  31. Y: Integer);
  32. procedure DropTextTarget1Drop(Sender: TObject; ShiftState: TShiftState;
  33. Point: TPoint; var Effect: Integer);
  34. procedure DropTextTarget2Drop(Sender: TObject; ShiftState: TShiftState;
  35. Point: TPoint; var Effect: Integer);
  36. procedure DropSourceFeedback(Sender: TObject; Effect: Integer;
  37. var UseDefaultCursors: Boolean);
  38. private
  39. //used by bottom example
  40. OldEdit2WindowProc: TWndMethod;
  41. procedure NewEdit2WindowProc(var Msg : TMessage);
  42. function MouseIsOverEdit2Selection(XPos: integer): boolean;
  43. procedure StartEdit2Drag;
  44. public
  45. { Public declarations }
  46. end;
  47. var
  48. FormText: TFormText;
  49. implementation
  50. {$R *.DFM}
  51. // Custom Cursors defined in Cursors.Res (included in DropFile.pas):
  52. const
  53. crTextCopy = 107;
  54. crTextMove = 108;
  55. crTextNoAccept = 109;
  56. //----------------------------------------------------------------------------
  57. // TFormText methods
  58. //----------------------------------------------------------------------------
  59. procedure TFormText.FormCreate(Sender: TObject);
  60. begin
  61. // Used for Bottom Text Drag example...
  62. // Hook edit window so we can intercept WM_LBUTTONDOWN messages!
  63. OldEdit2WindowProc := Edit2.WindowProc;
  64. Edit2.WindowProc := NewEdit2WindowProc;
  65. // Load custom cursors.
  66. Screen.cursors[crTextCopy] := LoadCursor(hinstance, 'CUR_DRAG_COPY_TEXT');
  67. Screen.cursors[crTextMove] := LoadCursor(hinstance, 'CUR_DRAG_MOVE_TEXT');
  68. Screen.cursors[crTextNoAccept] := LoadCursor(hinstance, 'CUR_DRAG_NOACCEPT_TEXT');
  69. end;
  70. procedure TFormText.FormDestroy(Sender: TObject);
  71. begin
  72. // Used by Bottom Text Drag example...
  73. // Unhook edit window...
  74. Edit2.WindowProc := OldEdit2WindowProc;
  75. end;
  76. procedure TFormText.ButtonCloseClick(Sender: TObject);
  77. begin
  78. Close;
  79. end;
  80. //----------------------------------------------------------------------------
  81. // The following 4 methods are all that's needed
  82. // for the TOP Text Drop source and target examples.
  83. //----------------------------------------------------------------------------
  84. procedure TFormText.Edit1MouseDown(Sender: TObject; Button: TMouseButton;
  85. Shift: TShiftState; X, Y: Integer);
  86. var
  87. Res: TDragResult;
  88. begin
  89. if (Edit1.Text = '') then
  90. exit;
  91. // Wait for user to move cursor before we start the drag/drop.
  92. if (DragDetectPlus(TWinControl(Sender).Handle, Point(X,Y))) then
  93. begin
  94. Statusbar1.SimpleText := '';
  95. Edit1.SelLength := 0;
  96. // Copy the data into the drop source.
  97. DropSource1.Text := Edit1.Text;
  98. // Temporarily disable Edit1 as a target so we can't drop on the same
  99. // control as we are dragging from.
  100. DropTextTarget1.DragTypes := [];
  101. try
  102. // OK, now we are all set to go. Let's start the drag from Edit1...
  103. Res := DropSource1.Execute;
  104. finally
  105. // Enable Edit1 as a drop target again.
  106. DropTextTarget1.DragTypes := [dtCopy];
  107. end;
  108. // Display the result of the drag operation.
  109. case Res of
  110. drDropCopy: Statusbar1.SimpleText := 'Copied successfully';
  111. drDropLink: Statusbar1.SimpleText := 'Scrap file created successfully';
  112. drCancel: Statusbar1.SimpleText := 'Drop cancelled';
  113. drOutMemory: Statusbar1.SimpleText := 'Drop failed - out of memory';
  114. else
  115. Statusbar1.SimpleText := 'Drop failed - reason unknown';
  116. end;
  117. end;
  118. end;
  119. procedure TFormText.DropSourceFeedback(Sender: TObject; Effect: Integer;
  120. var UseDefaultCursors: Boolean);
  121. begin
  122. // Provide custom drop source feedback.
  123. // Note: To use the standard drag/drop cursors, just disable this event
  124. // handler or set UseDefaultCursors to True.
  125. UseDefaultCursors := False; // We want to use our own cursors.
  126. // Ignore the drag scroll flag.
  127. case DWORD(Effect) and not DWORD(DROPEFFECT_SCROLL) of
  128. DROPEFFECT_COPY: Windows.SetCursor(Screen.Cursors[crTextCopy]);
  129. DROPEFFECT_MOVE: Windows.SetCursor(Screen.Cursors[crTextMove]);
  130. else
  131. Windows.SetCursor(Screen.Cursors[crTextNoAccept]);
  132. end;
  133. end;
  134. procedure TFormText.DropTextTarget1Drop(Sender: TObject;
  135. ShiftState: TShiftState; Point: TPoint; var Effect: Integer);
  136. begin
  137. // Text has been dropped onto our drop target. Copy the dropped text into the
  138. // edit control.
  139. Edit1.text := DropTextTarget1.Text;
  140. end;
  141. procedure TFormText.ButtonClipboardClick(Sender: TObject);
  142. begin
  143. if Edit1.Text <> '' then
  144. begin
  145. // Copy data into drop source component and then...
  146. DropSource1.Text := Edit1.Text;
  147. // ...Copy the data to the clipboard.
  148. DropSource1.CopyToClipboard;
  149. StatusBar1.SimpleText := 'Text copied to clipboard.';
  150. end;
  151. end;
  152. //----------------------------------------------------------------------------
  153. // The following methods are used for the BOTTOM Text Drop SOURCE and TARGET examples.
  154. // The DropSource code is almost identical. However, the Edit2 control
  155. // has been hooked to override the default WM_LBUTTONDOWN message handling.
  156. // Using the normal OnMouseDown event method does not work for this example.
  157. //----------------------------------------------------------------------------
  158. // The new WindowProc for Edit2 which intercepts WM_LBUTTONDOWN messages
  159. // before ANY OTHER processing...
  160. procedure TFormText.NewEdit2WindowProc(var Msg : TMessage);
  161. begin
  162. if (TWMMouse(Msg).Msg = WM_LBUTTONDOWN) and
  163. MouseIsOverEdit2Selection(TWMMouse(Msg).XPos) then
  164. begin
  165. StartEdit2Drag; // Just a locally declared procedure.
  166. TWMMouse(Msg).Result := 0;
  167. end else
  168. //Otherwise do everything as before...
  169. OldEdit2WindowProc(Msg);
  170. end;
  171. // Determine if the specified X coordinate is within the edit control's
  172. // text selection.
  173. function TFormText.MouseIsOverEdit2Selection(XPos: integer): boolean;
  174. var
  175. dc: HDC;
  176. SavedFont: HFont;
  177. size1, size2: TSize;
  178. s1, s2: string;
  179. begin
  180. if (Edit2.SelLength > 0) and (Edit2.Focused) then
  181. begin
  182. // Create a Device Context which can be used to retrieve font metrics.
  183. dc := GetDC(0);
  184. try
  185. // Select the edit control's font into our DC.
  186. SavedFont := SelectObject(dc, Edit2.Font.Handle);
  187. try
  188. // Get text before selection.
  189. s1 := Copy(Edit2.Text, 1, Edit2.SelStart);
  190. // Get text up to and including selection.
  191. s2 := s1 + Edit2.SelText;
  192. // Get dimensions of text before selection and up to and including
  193. // selection.
  194. GetTextExtentPoint32(dc, PChar(s1), length(s1), size1);
  195. GetTextExtentPoint32(dc, PChar(s2), length(s2), size2);
  196. finally
  197. SelectObject(dc, SavedFont);
  198. end;
  199. finally
  200. ReleaseDC(0,dc);
  201. end;
  202. Result := (XPos >= size1.cx) and (XPos <= size2.cx);
  203. end else
  204. Result := False;
  205. end;
  206. procedure TFormText.StartEdit2Drag;
  207. var
  208. Res: TDragResult;
  209. begin
  210. Statusbar1.Simpletext := '';
  211. // Copy the data into the drop source and...
  212. DropSource1.Text := Edit2.SelText;
  213. // ...Start the drag/drop.
  214. Res := DropSource1.Execute;
  215. // Display the result of the drag operation.
  216. case Res of
  217. drDropCopy: Statusbar1.SimpleText := 'Copied successfully';
  218. drDropLink: Statusbar1.SimpleText := 'Scrap file created successfully';
  219. drCancel: Statusbar1.SimpleText := 'Drop cancelled';
  220. drOutMemory: Statusbar1.SimpleText := 'Drop failed - out of memory';
  221. else
  222. Statusbar1.SimpleText := 'Drop failed - reason unknown';
  223. end;
  224. end;
  225. procedure TFormText.Edit2MouseMove(Sender: TObject; Shift: TShiftState; X,
  226. Y: Integer);
  227. begin
  228. // This method just changes mouse cursor to crHandPoint if over selected text.
  229. if MouseIsOverEdit2Selection(X) then
  230. Edit2.Cursor := crHandPoint
  231. else
  232. Edit2.Cursor := crDefault;
  233. end;
  234. procedure TFormText.DropTextTarget2Drop(Sender: TObject;
  235. ShiftState: TShiftState; Point: TPoint; var Effect: Integer);
  236. begin
  237. // Text has been dropped onto our drop target. Copy the dropped text into the
  238. // edit control.
  239. Edit2.Text := DropTextTarget2.Text;
  240. end;
  241. end.