AnnMouseDown example for C++ 5.0 and later

For details on event handling of the COM objects in MFC, and m_pDlg and m_pRasterAnn declarations, refer to the "Creating and Using Annotations (C++ 5.0 and later) Tutorial"

//This example shows 
//1.
//How to create a custom annotation (circle inside a square)
//Set the AnnTool property to ANN_TOOL_USER_FIRST to see how this works

//2.
//How to restrict the rectangle annotation to be a square
//Set AnnTool property to ANN_TOOL_RECTANGLE and hold the SHIFT key when drawing to see how this works

//Global declarations
//long m_hRectObject;
//long m_hEllipseObject;
//long m_x0;
//long m_y0;
//
//For details on event handling of the COM objects in MFC,
//  and m_pDlg and m_pRasterAnn delcarations, refer to 
//  the "Creating and Using Annotations (C++ 5.0 and later) Tutorial"

void CRasterAnnSink::AdjustMousePos(int Shift, long x, long y)
{
   int dx;
   int dy;
   if (Shift == 1) 
   {
      // if shift key is down, force the creation of squares
      dx = abs(x - m_x0);
      dy = abs(y - m_y0);
      if (dx > dy)
      {
         // adjust y to be as far from m_y0 as x is from m_x0
         y = (y>m_y0) ? m_y0 + dx : m_y0 - dx;
      }
      else
      {
         // adjust x to be as far from m_x0 as y is from m_y0
         x = (x>m_x0) ? m_x0 + dy : m_x0 - dy;
      }
      // set the mouse cursor and update its position
      m_pDlg->m_pRasterAnn->SetMousePos((float)x, (float)y, FALSE);
   }
}

void CRasterAnnSink::OnAnnMouseDown(short Button, short Shift, long x, long y)
{   
   m_x0 = x;
   m_y0 = y;
   switch(m_pDlg->m_pRasterAnn->GetAnnTool())
   {
   case ANN_TOOL_USER_FIRST:
      //create the objects
      m_pDlg->m_pRasterAnn->AnnSetSelected(m_pDlg->m_pRasterAnn->AnnContainer, FALSE, TRUE);
      
      //Add an undo node to undo the creation of these objects.
      m_pDlg->m_pRasterAnn->AnnAddUndoNode();
      
      m_pDlg->m_pRasterAnn->AnnCreate(ANN_OBJECT_RECT, TRUE, TRUE);
      m_hRectObject = m_pDlg->m_pRasterAnn->GetAnnObject();

      m_pDlg->m_pRasterAnn->AnnCreate(ANN_OBJECT_ELLIPSE, TRUE, TRUE);
       hEllipseObject = m_pDlg->m_pRasterAnn->GetAnnObject();

      
      //set the automation defaults to the objects newly created
      m_pDlg->m_pRasterAnn->AnnSetAutoDefaults(m_hRectObject, 0);
      m_pDlg->m_pRasterAnn->AnnSetAutoDefaults(m_hEllipseObject, 0);
      
      //start defining them from the x, y coordinate
      m_pDlg->m_pRasterAnn->AnnDefine(m_hRectObject, (float)x, (float)y, ANN_DEFINE_BEGINSET);
      m_pDlg->m_pRasterAnn->AnnDefine(m_hEllipseObject, (float)x, (float)y, ANN_DEFINE_BEGINSET);
   }
}

void CRasterAnnSink::OnAnnMouseMove(short Button, short Shift, long x, long y)
{
   //if left button pressed
   if (Button == 1)  
   {
      switch( m_pDlg->m_pRasterAnn->GetAnnTool())
      {
      case ANN_TOOL_USER_FIRST:
         //update the objects from the x, y coordinate
         m_pDlg->m_pRasterAnn->AnnDefine(m_hRectObject, (float)x, (float)y, ANN_DEFINE_UPDATE);
         m_pDlg->m_pRasterAnn->AnnDefine(m_hEllipseObject, (float)x, (float)y, ANN_DEFINE_UPDATE);
         break;
         
      case ANN_TOOL_RECT:
         AdjustMousePos (Shift, x, y);
         break;
      }
   }
}

void CRasterAnnSink::OnAnnMouseUp(short Button, short Shift, long x, long y)
{
   switch( m_pDlg->m_pRasterAnn->GetAnnTool())
      
   {
   case ANN_TOOL_USER_FIRST:
      m_pDlg->m_pRasterAnn->AnnDefine(m_hRectObject, (float)x, (float)y, ANN_DEFINE_END);
      m_pDlg->m_pRasterAnn->AnnDefine(m_hEllipseObject, (float)x, (float)y, ANN_DEFINE_END);
      m_pDlg->m_pRasterAnn->AnnSetSelected(m_hRectObject, TRUE, FALSE);
      m_pDlg->m_pRasterAnn->AnnSetSelected(m_hEllipseObject, TRUE, FALSE);
      m_pDlg->m_pRasterAnn->AnnGroup(m_pDlg->m_pRasterAnn->AnnContainer, ANN_FLAG_RECURSE + ANN_FLAG_SELECTED, "");
      m_hEllipseObject = 0;
      m_hRectObject = 0;
      break;
      
   case ANN_TOOL_RECT:
      AdjustMousePos(Shift, x, y);
      break;
   }
}