Outlining, Dragging, and Pasting a Region (C++ Builder)

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.h file. In online help, you can copy the block of code and paste it into your application.

 

    bool ReadyToDrag; /*The state after marking the region but before dragging */
    bool Dragging; /*The state when the mouse is used for dragging the floater */
    int StartX; /*Starting X position in screen pixels */
    int StartY; /*Starting Y position in screen pixels */
    int FloaterX; /*Floater X position in screen pixels */
    int FloaterY; /*Floater Y position in screen pixels */
    float ZoomFactorX; /*Used for translating positioning information */
    float ZoomFactorY; /*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:

void __fastcall TForm1::SelectRgnClick(TObject *Sender)
{
   Lead1->RgnMarkingMode = mmFreeHand;
   ShowMessage("Draw a freehand region");
}

6.

Code the PasteFloaterBtn control's Click procedure as follows:

void __fastcall TForm1::PasteFloaterClick(TObject *Sender)
{
   /*Declare the variable for the Combine operation. */
   int MyOp;
   /*Declare variables for the client area coordinates. */
   int LCRgnX, LCRgnY , LCRgnWidth, LCRgnHeight;
   /*Declare variables for the bitmap coordinates. */
   int LBRgnX, LBRgnY , LBRgnWidth, LBRgnHeight;

   /*Do nothing if( there is no floater. */
   if(!Lead1->Floater)
      return;
   /*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 = (LCRgnX-Lead1->DstLeft) / ZoomFactorX + Lead1->SrcLeft;
   LBRgnY = (LCRgnY-Lead1->DstTop) / ZoomFactorY + Lead1->SrcTop;
   LBRgnWidth = LCRgnWidth / ZoomFactorX;
   LBRgnHeight = 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 | 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();
}

7.

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

void __fastcall TForm1::Lead1MouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
{
   /*Declare local variables. */
   int BitmapX, BitmapY;
   int NewX, NewY, NewWidth, NewHeight;

   /*Do nothing if we are drawing a region. */
   if(Lead1->RgnMarkingMode != mmNone)
      return;
   /* 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)
   {
      /*Translate the current mouse coordinates. */
      /*These coordinates account for the zoom factor and offset. */
      ZoomFactorX = (float)Lead1->DstWidth / (float)Lead1->SrcWidth;
      ZoomFactorY = (float)Lead1->DstHeight / (float)Lead1 >SrcHeight;
      BitmapX = (X / ZoomFactorX) - (Lead1->DstLeft / ZoomFactorX) + Lead1->SrcLeft;
      BitmapY = (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))
      {
         /*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 = (Lead1->RgnTop - Lead1->SrcTop) * ZoomFactorY + Lead1->DstTop;
         NewX = (Lead1->RgnLeft - Lead1->SrcLeft) * ZoomFactorX + Lead1->DstLeft;
         NewWidth = Lead1->RgnWidth * ZoomFactorX;
         NewHeight = 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;
      }
   }
}

8.

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

void __fastcall TForm1::Lead1MouseMove(TObject *Sender, TShiftState Shift, int X, int Y)
{
   /*Declare variables for repositioning the floater. */
   int NewX, NewY, NewWidth, NewHeight, XDelta, YDelta;

   /*Do nothing if( we are drawing a region. */
   if(Lead1->RgnMarkingMode != mmNone)
      return;
   /*Reposition the floater if we are dragging it. */
   if(Dragging && Shift==(TShiftState() << ssLeft) && (Lead1 >Floater))
      if(Lead1->IsPtInFloater(X, Y))
      {
         /*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;
      }
}

9.

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

void __fastcall TForm1::Lead1MouseUp(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
{
   /*if we were drawing a region, set up for the next operation*/
   if(Lead1->RgnMarkingMode != mmNone)
   {
      Lead1->RgnMarkingMode = mmNone;
      Lead1->RgnFrameType = ftStatic;
      ReadyToDrag = true;
      ShowMessage("Now, drag the selection to another place.");
   }
}

10.

Run your program to test it.