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