Programming C++Builder How to Use Drawing Tools and Share Codes Among Event Handlers in CBuilder?

How to use the drawing tools?

Now that you can tell what tool to use, you must indicate how to draw the different shapes. The only methods that perform any drawing are the mouse-move and mouse-up handlers, and the only drawing code draws lines, no matter what tool is selected.

To use different drawing tools, your code needs to specify how to draw, based on the selected tool. You add this instruction to each tool's event handler.
This section describes:

  1. Drawing shapes.
  2. Sharing code among event handlers.

How to draw shapes?

Drawing shapes is just as easy as drawing lines. Each one takes a single statement; you just need the coordinates.

Here's a rewrite of the OnMouseUp event handler that draws shapes for all four tools:

void __fastcallTForm1::FormMouseUp(TObject *Sender, TMouseButton Button,
  TShiftState Shift, int X, int Y){
  switch (DrawingTool)
  {
    case dtLine:
      Canvas->MoveTo(Origin.x, Origin.y);
      Canvas->LineTo(X, Y);
      break;
    case dtRectangle:
      Canvas->Rectangle(Origin.x, Origin.y, X, Y);
      break;
    case dtEllipse:
      Canvas->Ellipse(Origin.x, Origin.y, X, Y);
      break;
    case dtRoundRect:
      Canvas->Rectangle(Origin.x, Origin.y, X, Y, (Origin.x - X)/2,

                        (Origin.y - Y)/2);
      break;
  }
  Drawing = false;
}

Of course, you also need to update the OnMouseMove handler to draw shapes:

void __fastcallTForm1::FormMouseMove(TObject *Sender, TMouseButton Button,
  TShiftState Shift, int X, int Y)
{
  if (Drawing)
  {
    Canvas->Pen->Mode = pmNotXor;        // use XOR mode to draw/erase
    switch (DrawingTool)
    {
      case dtLine:
        Canvas->MoveTo(Origin.x, Origin.y);
        Canvas->LineTo(MovePt.x, MovePt.y);
        Canvas->MoveTo(Origin.x, Origin.y);
        Canvas->LineTo(X, Y);
        break;
      case dtRectangle:
        Canvas->Rectangle(Origin.x, Origin.y, MovePt.x, MovePt.y);

        Canvas->Rectangle(Origin.x, Origin.y, X, Y);
        break;
      case dtEllipse:
        Canvas->Ellipse(Origin.x, Origin.y, MovePt.x, MovePt.y);
        Canvas->Ellipse(Origin.x, Origin.y, X, Y);
        break;
      case dtRoundRect:
        Canvas->Rectangle(Origin.x, Origin.y, MovePt.x, MovePt.y,
                         (Origin.x - MovePt.x)/2,(Origin.y - MovePt.y)/2);
        Canvas->Rectangle(Origin.x, Origin.y, X, Y,

                         (Origin.x - X)/2, (Origin.y - Y)/2);
        break;
    }
    MovePt = Point(X, Y);
  }
  Canvas->Pen->Mode = pmCopy;
}

Typically, all the repetitious code that is in the above example would be in a separate routine. The next section shows all the shape-drawing code in a single routine that all mouse-event handlers can call.

How to share code among event handlers?

Any time you find that many your event handlers use the same code, you can make your application more efficient by moving the repeated code into a routine that all event handlers can share.

To add a method to a form:

  1. Add the method declaration to the form object. You can add the declaration in either the public or private parts at the end of the form object's declaration. If the code is just sharing the details of handling some events, it's probably safest to make the shared method private.
  2. Write the method implementation in the .cpp file for the form's unit.

The header for the method implementation must match the declaration exactly, with the same parameters in the same order.

See the following codes examples which are shared among event handlers.

The following code adds a method to the form called DrawShape and calls it from each of the handlers. First, the declaration of DrawShape is added to the form object's declaration:

enum TDrawingTool {dtLine, dtRectangle, dtEllipse, dtRoundRect};
class TForm1 : public TForm
{
__published:  // IDE-managed Components
  void __fastcall FormMouseDown(TObject *Sender, TMouseButton Button,
  TShiftState Shift, int X, int Y);
  void __fastcall FormMouseMove(TObject *Sender, TShiftState Shift, int X,
  int Y);
  void __fastcall FormMouseUp(TObject *Sender, TMouseButton Button,
  TShiftState Shift, int X, int Y);
private: // User declarations
  void __fastcall DrawShape(TPoint TopLeft, TPoint BottomRight, TPenMode AMode);

public:  // User declarations
  __fastcall TForm1(TComponent* Owner);
  bool Drawing;  //field to track whether button was pressed
  TPoint Origin, MovePt;  // fields to store points
  TDrawingTool DrawingTool;  // field to hold current tool
};

Then, the implementation of DrawShape is written in the .cpp file for the unit

void __fastcallTForm1::DrawShape(TPoint TopLeft, TPoint BottomRight,
  TPenMode AMode)
{
  Canvas->Pen->Mode = AMode;
  switch (DrawingTool)
  {
    case dtLine:
      Canvas->MoveTo(TopLeft.x, TopLeft.y);
      Canvas->LineTo(BottomRight.x, BottomRight.y);
      break;
    case dtRectangle:
      Canvas->Rectangle(TopLeft.x, TopLeft.y, BottomRight.x, BottomRight.y);
      break;
    case dtEllipse:
      Canvas->Ellipse(TopLeft.x, TopLeft.y, BottomRight.x, BottomRight.y);
      break;

    case dtRoundRect:
      Canvas->Rectangle(TopLeft.x, TopLeft.y, BottomRight.x, BottomRight.y,
                  (TopLeft.x - BottomRight.x)/2,(TopLeft.y - BottomRight.y)/2);
      break;
  }
}

The other event handlers are modified to call DrawShape.

void __fastcall TForm1::FormMouseUp(TObject *Sender)
{
  DrawShape(Origin, Point(X,Y), pmCopy); // draw the final shape
  Drawing = false;
}

void __fastcall TForm1::FormMouseMove(TObject *Sender, TMouseButton Button,
  TShiftState Shift, int X, int Y)
{
  if (Drawing)
  {
    DrawShape(Origin, MovePt, pmNotXor); // erase previous shape
    MovePt = Point(X, Y);
    DrawShape(Origin, MovePt, pmNotXor); // draw current shape
  }
}


Add comment


Security code
Refresh

Programming - C++Builder