Figure 2: Part of TDrawBox component source file

//-------------------------------------------
// DrawBox.cpp - sicherer@sichemsoft.nl
// Complete commented code available on line
// NOTE: only functions whose prototypes are 
// shown in Figure 1 are shown here!
//-------------------------------------------
// ... #includes and constants omitted
//-------------------------------------------
__fastcall
TDrawBox::TDrawBox(TComponent* Owner)
  : inherited(Owner)
{
   Surface = new TDrawBoxSurface(this);
   Canvas = Surface->Canvas;
// ... default property assignments omitted
}
//-------------------------------------------
__fastcall
TDrawBox::~TDrawBox() // virtual
{
   if (PrintThread)
      PrintThread->Terminate();
   delete Surface;
}
//-------------------------------------------
void
TDrawBox::SetWindowExtents
   (double x1, double y1, 
    double x2, double y2)
{
   assert(x1 != x2 && y1 != y2);
   xw1 = x1; yw1 = y1; xw2 = x2; yw2 = y2;
   SetTransformation();
// ... code omitted
}
//-------------------------------------------
bool
TDrawBox::SaveToFileAsEMF
   (const AnsiString &file, 
    double x1, double y1, 
    double x2, double y2)
{
   return Save(file, true, x1, y1, x2, y2);
}
//-------------------------------------------
void
TDrawBox::DrawLine(double x1, double y1,
   double x2, double y2)
{
   int xx1, yy1, xx2, yy2;
   WorldtoPC(x1, y1, &xx1, &yy1);
   WorldtoPC(x2, y2, &xx2, &yy2);
   Canvas->MoveTo(xx1, yy1);
   Canvas->LineTo(xx2, yy2);
}
//-------------------------------------------
void __fastcall
TDrawBox::SetCrossHairs(bool on)
{
   if (Surface->CrossHairs != on) {
      Surface->CrossHairs = on;
      if (on) {
         oldCursor = Cursor; Cursor = crNone;
      } else
         Cursor = oldCursor;
      Invalidate();
   }
}
//-------------------------------------------
bool __fastcall
TDrawBox::GetCrossHairs() const
{
   return Surface->CrossHairs;
}
//-------------------------------------------
void
TDrawBox::NotifyMarked(int x1, int y1,
   int x2, int y2, bool region)
{
   if (region) { // area marked
      if (FOnMarked && MarkShape != msNone) {
         double xx1, yy1, xx2, yy2;
         PCtoWorld(x1, y1, &xx1, &yy1);
         PCtoWorld(x2, y2, &xx2, &yy2);
         FOnMarked(this, xx1, yy1, xx2, yy2);
      }
   } else { // point clicked
      if (Caret)
         Surface->SetCaret(x2, y2);
      if (FOnClick) {
         double x, y;
         PCtoWorld(x2, y2, &x, &y);
         FOnClick(this, x, y);
      }
   }
}
//-------------------------------------------
void
TDrawBox::NotifyMouseUp(TMouseButton button,
   TShiftState shift, int x, int y)
{
   if (!FOnMouseUp)
      return; // no user event handler

   double xx, yy;
   PCtoWorld(x, y, &xx, &yy);
   FOnMouseUp(this, button, shift, xx, yy);
}
//-------------------------------------------
void
TDrawBox::NotifyPaint()
{
   if (FOnPaint) // call user's event handler
      FOnPaint(this);
}
//-------------------------------------------
bool
TDrawBox::ScrollIfNeeded()
{
   assert(Surface->Marking);

   // retrieve current mouse position
   // and compute window boundaries
   POINT mousePosition;
   ::GetCursorPos(&mousePosition);
   POINT surfacePosition = ClientOrigin;
   int left = surfacePosition.x;
   int top = surfacePosition.y;
   int right = left + ClientWidth;
   int bottom = top + ClientHeight;
   int x = mousePosition.x;
   int y = mousePosition.y;
   if (x >= left && x < right &&
       y >= top && y < bottom)
      return false;

   // determine horizontal scroll
   int dx = 0;
   if (x < left)
      dx = x - left;
   else if (x > right)
      dx = x - right;

   // determine vertical scroll
   int dy = 0;
   if (y < top)
      dy = y - top;
   else if (y > bottom)
      dy = y - bottom;

   // scroll window
   if (dx || dy) {
      if (dx) dx = 1 + dx / 2;
      if (dy) dy = 1 + dy / 2;
      int xpos = HorzScrollBar->Position;
      HorzScrollBar->Position = xpos + dx;
      int ypos = VertScrollBar->Position;
      VertScrollBar->Position = ypos + dy;
      if (xpos != HorzScrollBar->Position ||
          ypos != VertScrollBar->Position)
         return true;
   }

   // window not scrolled
   return false;
}
//-------------------------------------------
TMetafile *
TDrawBox::CreateMetafile(double x1, double y1,
   double x2, double y2)
{
   // do nothing if there is no 
   // OnPaint handler!
   if (!FOnPaint)
      return NULL;

   double xx1, yy1, xx2, yy2;
   int vw, vh;
   bool fullWindow;

   if (x1 != x2) { // use specified window

      fullWindow = false;
      // remember original window and viewport
      xx1 = xw1;  yy1 = yw1;
      xx2 = xw2;  yy2 = yw2;
      vw = ViewportWidth; vh = ViewportHeight;
      // compute proportional viewport size
      WorldtoPC(abs(x2 - x1), abs(y2 - y1),
         &ViewportWidth, &ViewportHeight);

   } else { // use full window extents

      fullWindow = true;
      ViewportWidth  = HorzScrollBar->Range;
      ViewportHeight = VertScrollBar->Range;

   }

   // create metafile with size of viewport
   TMetafile *metafile = new TMetafile;
   metafile->Width  = ViewportWidth;
   metafile->Height = ViewportHeight;

   // create metafile canvas to draw on
   TMetafileCanvas *metafileCanvas =
      new TMetafileCanvas(metafile, 
             Canvas->Handle);

   // copy attributes from screen window 
   // canvas
   metafileCanvas->Pen->Assign(Canvas->Pen);
   metafileCanvas->Brush->
      Assign(Canvas->Brush);
   metafileCanvas->Font->Assign(Canvas->Font);

   // change Canvas pointer to metafile canvas
   Canvas = metafileCanvas;

   if (!fullWindow) {
      // set new window extents
      SetWindowExtents(x1, y1, x2, y2);
   }

   // set clipping rectangle to viewport
   HRGN hrgn = 
      ::CreateRectRgn(0, 0,
         ViewportWidth, ViewportHeight);
   ::SelectClipRgn(Canvas->Handle, hrgn);
   ::DeleteObject(hrgn);

   // call user's OnPaint
   FOnPaint(this);

   if (!fullWindow) {
      // restore previous window and viewport
      ViewportWidth = vw; ViewportHeight = vh;
      SetWindowExtents(xx1, yy1, xx2, yy2);
   }

   // change Canvas pointer back to screen 
   // window
   Canvas = Surface->Canvas;

   // close metafile canvas and return 
   // metafile
   delete metafileCanvas;
   return metafile;
}
//-------------------------------------------
bool
TDrawBox::Save(const AnsiString &filename,
   bool emf, double x1, double y1,
   double x2, double y2)
{
   // create metafile with copy of window
   TMetafile *metafile =
      CreateMetafile(x1, y1, x2, y2);
   if (!metafile)
      return false;
   bool result = true;

   // save/copy as enhanced metafile
   if (emf) {

      // copy metafile to clipboard
      if (filename.IsEmpty()) {
         Clipboard()->Open();
         Clipboard()->Assign(metafile);
         Clipboard()->Close();

      // or save metafile on disk
      } else {
         try {
            metafile->SaveToFile(filename);
         } catch (...) {
            result = false;
         }
      }

   // or save/copy as bitmap
   } else {

      // create temporary bitmap
      Graphics::TBitmap *bitmap =
         new Graphics::TBitmap();

      // set bitmap to size of metafile
      bitmap->Width = metafile->Width;
      bitmap->Height = metafile->Height;

      // draw metafile on bitmap's canvas
      bitmap->Canvas->Draw(0,0,metafile);

      // copy bitmap to clipboard
      if (filename.IsEmpty()) {
         Clipboard()->Open();
         Clipboard()->Assign(bitmap);
         Clipboard()->Close();

      // or save bitmap on disk
      } else {
         try {
            bitmap->SaveToFile(filename);
         } catch(...) {
            result = false;
         }
      }

      // delete temporary bitmap
      delete bitmap;
   }

   // delete created metafile
   delete metafile;
   return result;
}
//-------------------------------------------
namespace Drawbox
{
  void __fastcall PACKAGE Register()
  {
     TComponentClass classes[1] =
        {__classid(TDrawBox)};
     RegisterComponents("Sichemsoft", 
        classes, 0);
  }
}
//-------------------------------------------
//-------------------------------------------
__fastcall
TDrawBoxSurface::
   TDrawBoxSurface(TComponent* owner):
   inherited(owner)
{
// ... default property assignments omitted
}
//-------------------------------------------
void __fastcall
TDrawBoxSurface::MouseUp(TMouseButton button,
   TShiftState shift, int x, int y)
{
   inherited::MouseUp(button,shift,x,y);
   DrawBox->NotifyMouseUp(button, 
               shift, x, y);

   if (!(Marking && button == mbLeft))
      return;

   // undraw rectangle
   CurrentX = x; CurrentY = y;
   if (MarkShape != msNone)
      DrawMarkShape();

   // fit and normalize shape
   int x1 = OriginX; int x2 = x;
   int y1 = OriginY; int y2 = y;
   if (MarkShape == msLine) {
      x1 = max(0, x1); x1 = min(x1, Width);
      y1 = max(0, y1); y1 = min(y1, Height);
      x2 = max(0, x2); x2 = min(x2, Width);
      y2 = max(0, y2); y2 = min(y2, Height);
   } else {
      if (x1 > x2) Swap(x1, x2);
      if (y1 > y2) Swap(y1, y2);
      x1 = max(0, x1); y1 = max(0, y1);
      x2 = min(x2, Width);
      y2 = min(y2, Height);
   }

   // is region or point marked?
   bool region = abs(x2-x1)>2 || abs(y2-y1)>2;

   // redraw rectangle if necessary
   if (region && MarkShape == msMark) {
      DrawMarkShape();
      OriginX = x1; OriginY = y1;
      MarkedX = x2; MarkedY = y2;
      Marked = true;
   }

   // send notification to surface object
   if (MarkShape != msNone)
      delete Timer;
   DrawBox->NotifyMarked(x1, y1, x2, y2, 
               region);
   Marking = false;
}
//-------------------------------------------
void __fastcall
TDrawBoxSurface::TimerTick(TObject* Sender)
{
   assert(Marking);

   if (DrawBox->ScrollIfNeeded())
      Invalidate();
}
//-------------------------------------------