Outlining, Dragging, and Pasting a Region (Delphi)

Take the following steps to add code that lets you outline an area with a mouse, drag a copy of the selected area, and paste the copy into another part of the bitmap:

1.

Start with the project that you created in Loading and Displaying an Image.

2.

Add a second LEAD control, name it Lead2, and set its Visible property to False.

3.

Add the following declarations to the private section of the Unit1 file. In online help, you can copy the block of code and paste it into your application.

ReadyToDrag: Boolean; {The state after marking the region but before dragging }
Dragging: Boolean; {The state when the mouse is used for dragging the floater }
StartX: Integer; {Starting X position in screen pixels }
StartY: Integer; {Starting Y position in screen pixels }
FloaterX: Integer; {Floater X position in screen pixels }
FloaterY: Integer; {Floater Y position in screen pixels }
ZoomFactorX: Single; {Used for translating positioning information }
ZoomFactorY: Single; {Used for translating positioning information }

4.

image\btndbtn.gif At the top of your main form, add two command buttons and name them as follows:

 

Name

Caption

SelectRgn

Select Region

PasteFloater

Paste Floater

 

5.

Code the SelectRgn control's Click procedure as follows:

procedure TForm1.SelectRgnClick(Sender: TObject);
begin
Lead1.RgnMarkingMode := mmFreeHand;
ShowMessage('Draw a freehand region');
end;

6.

Code the PasteFloaterBtn control's Click procedure as follows:

procedure TForm1.PasteFloaterClick(Sender: TObject);
var
{Declare the variable for the Combine operation. }
MyOp: Integer;

{Declare variables for the client area coordinates. }
LCRgnX, LCRgnY , LCRgnWidth, LCRgnHeight: Integer;

{Declare variables for the bitmap coordinates. }
LBRgnX, LBRgnY , LBRgnWidth, LBRgnHeight: Integer;

begin
{Do nothing if there is no floater. }
If Lead1.Floater = 0 Then Exit;

{Get the floater into another bitmap }
Lead2.Bitmap := Lead1.Floater;

{Get the floater's client coordinates into local variables. }
LCRgnX := Lead1.FloaterDstLeft;
LCRgnY := Lead1.FloaterDstTop;
LCRgnWidth := Lead1.FloaterDstWidth;
LCRgnHeight := Lead1.FloaterDstHeight;

{Delete the floater. }
Lead1.FloaterVisible := False;
Lead1.Floater := 0;

{Translate the client coordinates to bitmap coordinates. }
LBRgnX := Round((LCRgnX - Lead1.DstLeft) / ZoomFactorX) + Lead1.SrcLeft;
LBRgnY := Round((LCRgnY - Lead1.DstTop) / ZoomFactorY) + Lead1.SrcTop;
LBRgnWidth := Round(LCRgnWidth / ZoomFactorX);
LBRgnHeight := Round(LCRgnHeight / ZoomFactorY);

{Reposition the region to use it as a mask for the Combine method. }
Lead1.OffsetRgn(LBRgnX - Lead1.RgnLeft, LBRgnY - Lead1.RgnTop);

{Use the Combine method to paste the Lead2 bitmap into the Lead1 bitmap. }
MyOp := CB_OP_ADD or CB_DST_0; {Operation flags for a simple paste. }
Lead1.Combine(LBRgnX, LBRgnY, LBRgnWidth, LBRgnHeight, 
     Lead2.Bitmap, 0, 0, MyOp);

{Repaint the part of the client area that has changed. }
Lead1.RepaintRect(LCRgnX, LCRgnY, LCRgnWidth, LCRgnHeight, False);

{Free the region. }
Lead1.FreeRgn;

end;

7.

In the LEAD1 control's OnMouseDown procedure, add the following code.

procedure TForm1.Lead1MouseDown (Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var

{Declare local variables. }
BitmapX, BitmapY: Integer;
NewX, NewY, NewWidth, NewHeight: Integer;

begin
{Do nothing if we are drawing a region. }
If Lead1.RgnMarkingMode <> mmNone Then Exit;

{ Save the starting position, in case we need it. }
StartY := Y;
StartX := X;

{If we are ready to drag the selection, get a floater. }
If ReadyToDrag = True Then
begin
    {Translate the current mouse coordinates. }
    {These coordinates account for the zoom factor and offset. }
    ZoomFactorX := Lead1.DstWidth / Lead1.SrcWidth;
    ZoomFactorY := Lead1.DstHeight / Lead1.SrcHeight;
    BitmapX := Round((x / ZoomFactorX) - (Lead1.DstLeft / ZoomFactorX) + Lead1.SrcLeft);
    BitmapY := Round((y / ZoomFactorY) - (Lead1.DstTop / ZoomFactorY) + Lead1.SrcTop);

    {Continue to create the floater if the mouse is pointing to
      the region we marked. }
    If Lead1.IsPtInRgn(BitmapX, BitmapY) Then
    begin
       {Hide the region frame. }
       Lead1.RgnFrameType := ftNone;

       {Create the floater bitmap, which will be the part of the main }
       {bitmap that is in the region's bounding rectangle. }
       Lead1.Floater := Lead1.Bitmap;

       {Translate the bitmap region coordinates to client area coordinates. }
       NewY := Round((Lead1.RgnTop - Lead1.SrcTop) * ZoomFactorY + Lead1.DstTop);
       NewX := Round((Lead1.RgnLeft - Lead1.SrcLeft) * ZoomFactorX + Lead1.DstLeft);
       NewWidth := Round(Lead1.RgnWidth * ZoomFactorX);
       NewHeight := Round(Lead1.RgnHeight * ZoomFactorY);

       {Set the initial display position of the floater. }
       Lead1.SetFloaterDstRect(NewX, NewY, NewWidth, NewHeight);

       {Set form-level variables. }
       FloaterY := Lead1.FloaterDstTop;
       FloaterX := Lead1.FloaterDstLeft;
       Lead1.FloaterVisible := True;
       Dragging := True;
       ReadyToDrag := False;
    end;
end;

end;

8.

In the LEAD1 control's MouseMove procedure, add the following code.

procedure TForm1.Lead1MouseMove (Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
var
{Declare variables for repositioning the floater. }
NewX, NewY, NewWidth, NewHeight, XDelta, YDelta: Integer;

begin
{Do nothing if we are drawing a region. }
If Lead1.RgnMarkingMode <> mmNone Then Exit;

{Reposition the floater if we are dragging it. }
If Dragging And (Shift = [ssLeft]) And (Lead1.Floater <> 0) Then
    If Lead1.IsPtInFloater(X, Y) Then
    begin
        {Update the position variables. }
        XDelta := X - StartX;
        YDelta := Y - StartY;
        NewX := FloaterX + XDelta;
        NewY := FloaterY + YDelta;
        NewWidth := Lead1.FloaterDstWidth;
        NewHeight := Lead1.FloaterDstHeight;

        {Reposition the floater. }
        Lead1.SetFloaterDstRect(NewX, NewY, NewWidth, NewHeight);

        {Save the form-level position variables. }
        FloaterY := NewY;
        FloaterX := NewX;
        StartY := Y;
        StartX := X;
    end;
end;

9.

In the LEAD1 control's MouseUp procedure, add the following code.

procedure TForm1.Lead1MouseUp (Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
{ If we were drawing a region, set up for the next operation. }
If Lead1.RgnMarkingMode <> mmNone Then
begin
    Lead1.RgnMarkingMode := mmNone;
    Lead1.RgnFrameType := ftStatic;
    ReadyToDrag := True;
    ShowMessage('Now, drag the selection to another place.');
end;

end;

10.

Run your program to test it.