views:

916

answers:

3

Hi all,

The code below enables a control (a label for instance) to show drag images while the dragging operation.

My problem is that I do not want to show the drag image instanly when the dragging begins, I want the image to be displayed when the mouse is on specific boundaries of the control - eg. in the right half of the label .

So far I haven't been able to find a solution for this - the image just gets displayed instantly (unless I modify the VCL source). I appreciate any tricks at this point to get the desired behaviour before abondoning VCL drag&drop utilities and roll a custom one capturing the mouse.

Here's an example pseudocode to enable drag images for a label..

{ turn on dragging }
Label1.DragMode := dmManual;
Label1.ControlStyle := Label1.ControlStyle + [csDisplayDragImage];

type 
  // VCL needs this for getting drag images..
  TMyDragObject = class(TDragControlObject)
  protected
    function GetDragImages: TDragImageList; override; 
  end;

function TMyDragObject.GetDragImages: TDragImageList;
begin
  Result := Form1.ImageList1;
end;             

procedure TForm1.Label1MouseDown(...);
begin
  { start the dragging manually }
  Label1.BeginDrag(False, 4); // the problem area! image is shown instantly at here!
end;

procedure TForm1.Label1StartDrag(Sender: TObject; var DragObject: TDragObject);
var b : TBitmap;
begin
  ImageList1.Clear;
  DragObject := TMyDragObject.Create(self);

  b := TBitmap.Create;
  try
    b.Width := ImageList1.Width;
    b.Height := ImageList1.Height;
    b.LoadFromFile('/path/to/image');
    ImageList1.Add(b, nil);
  finally
    b.Free;
  end;
end;

procedure TForm1.Label1MouseMove(...);
begin
  if X > Label1.Width div 2 then // right half
    // ??? - do show the drag image
  else
    // ??? - no drage image should be shown
end;
A: 

Label1.DragMode := dmAutomatic;

Have you tried to use dmManual? You should write some more code, but you can change more of the process.

By the way, why do you want to change standard behaviour? Your users probably expect the standard and can become frustrated if the program behaves differently.

Gamecat
Hi, my bad - it should be dmManual.
utku_karatas
The problem is actually much more complicated, I just simplified the matter to demonstrate.
utku_karatas
A: 

As the silence on the topic implies, I suppose what I want is a little bit over the top for the default VCL drag&drop utilities.

Anyway, to get the desired effect - that is to have more control over dragging operation, here's a way that involves capturing the mouse and processing the messages manually:

  SetCapture(Handle);
  try
    while GetCapture = Handle do 
       { Process messages like mouse move, click, etc..
         ie. Change the drag image when the control under cursor changes.. } 
  finally
    if Handle = GetCapture then
      ReleaseCapture;
  end;
utku_karatas
This seems to be wrong somehow - when you enter the while loop the capture is already released, so ReleaseCapture() in the finally shouldn't be called.
mghie
typo: enter should of course be exit...
mghie
@mghie: that's for the case "break" or "exit" called in the loop.
utku_karatas
However checking the captured window in the finally block seems to be a good idea. Thanks for the heads up.
utku_karatas
+1  A: 

Make the TBitmap, named b, a global variable and remove the line

ImageList1.Add(b, nil);

from the Label1StartDrag procedure and place it in an OnDragOverProcedure. This will allow ImageList1 to remain blank until the mouse has moved the four pixels specified in

Label1.BeginDrag(False, 4);

LuckyDog
Nice trick, thank you. Though I must add this doesn't give you much control over boundary checking either, except just a mere threshold.
utku_karatas