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