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. |
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. |