From: tnomad@digital.net Subject: Drag/Drop and Delphi Information Date: 28 Jun 1995 12:43:55 GMT Hey all, I though you would be interested in a recent discovery I made regarding Drag and Drop in Delphi. My requirement was to implement a similar interface to Dragging and Dropping as is found in File Manager, with respect to using the CTRL key to specify copying. My first (and very unsuccessful) pass was to use GetKeyboardState to examine the keyboard state and see if the CTRL key was depressed. There were two problems with this approach: 1) This function does not seem to return consistent values. 2) When dragging and dropping, mouse capture is set on the control. The OnKeyDown/OnKeyUp methods are not triggered during dragging. My second approach was to come up with a way to intercept the Windows message when the dragging was taking place. The only way to do this is to subclass the control, and override the WndProc method. I created a new property (WndProcFunction), that will be called when the property is assigned. In my subclass, I override the WndProc, call WndProcFunction if it is assigned, then call the inherited version: type TMessageEvent = procedure(Sender: TObject; Message: TMessage) of object; ... MyControl = class(subcontrol) private FWndProcFunction: TMessageEvent; ... published property WndProcFunction: TMessageEvent read FWndProcFunction write FWndProcFunction; ... public procedure WndProc(var Message: TMessage); override; end ... procedure MyControl.WndProc(var Message: TMessage); begin if Assigned(FWndProcFunction) then WndProcFunction(self, Message); inherited WndProc(Message); end; In my application (where I implement this class), I use the object browser to create the following function: procedure TViewRetrieval.ViewGridWndProcFunction(Sender: TObject; Message: TMessage); begin case Message.Msg of WM_KEYDOWN, WM_KEYUP: DoProcessKey(Sender, TWMKey(Message)); end; end; I then created DoProcessKey as follows (note: crDragCopy is my own cursor): procedure TViewRetrieval.DoProcessKey(Sender: TObject; var Message: TWMKey); var ShiftState: TShiftState; pt: TPoint; begin ShiftState := KeyDataToShiftState(Message.KeyData); if (ShiftState = [ssCtrl]) then ViewGrid.DragCursor := crDragCopy else ViewGrid.DragCursor := crDrag; if ViewGrid.Dragging then begin GetCursorPos(pt); SetCursorPos(pt.x, pt.y); {Causes the cursor to be redrawn} end; end; ************************************ * The Nomad * * tnomad@digital.net * ************************************ ------------------------------------------------------------------------------- From: mduncan@wpo.borland.com (Mark Duncan) Subject: Re: Drag/Drop and Delphi Information Date: 28 Jun 1995 21:01:31 GMT Here's how I would do it: Initiate the drag (call BeginDrag method of the dragged control) in that control's OnMouseDown event, which passes in information about the button and keyboard states. Procedure TForm1.SourceFileListBoxMouseDown(Sender: TObject; Button: tMouseButton; Shift : TShiftState; X, Y: Integer); begin if (Button = mbLeft) and (ssCtrl in Shift) then with (Sender as TWinControl) do begin BeginDrag(True); ....... {init information about what files are selected, etc} FCopying := True; {a global boolean you declare to keep track of what kind of end; dragging is going on} then in the OnDragDrop of the accepting control you would have something like: TForm1.DestFileListBoxDragDrop(Sender, Source : TObject; X, Y : integer); begin if (Source = SourceFileListBox) and (FCopying = True) then ...... {do the copy} end; Mark