Hit Testing

The rule governing the Circle control flash behavior is that the circle should flash only if the mouse is within the circular area of the control. To achieve this effect, you must implement "hit testing," which checks the coordinates of every mouse click within the control to see if they are within the circle. Hit testing is implemented in the Circle control by the InCircle function. InCircle returns TRUE if the given point is within the area of the circle or the ellipse.

To implement the InCircle function

  1. On WizardBar, select CCircCtl to edit the CCIRCCTL.CPP file.

  2. Click the arrow on the action button, located on the right end of the WizardBar, and select Add Member Function.

    The Add Member Function dialog box is displayed.

  3. In the Function Type edit box, type BOOL. This is the type of value the function will return.

  4. In the Function Declaration edit box, type InCircle(CPoint& point).

  5. Under Access, click Protected.

  6. Click OK to close the Add Member Function dialog box.

    This will add the following declaration in the protected section of CIRCCTL.H:

    BOOL InCircle(CPoint& point);
    

    It will also add a function definition at the end of CIRCCTL.CPP and position the cursor in the function:

    BOOL CCircCtrl::InCircle(CPoint& point)
    {
    
    }
    
  7. Add code to the function in CIRCCTL.CPP as shown:
    BOOL CCircCtrl::InCircle(CPoint& point)
    {
        CRect rc;
        GetClientRect(rc);
        GetDrawRect(&rc);
    
        // Determine radii
        double a = (rc.right - rc.left) / 2;
        double b = (rc.bottom - rc.top) / 2;
    
        // Determine x, y
        double x = point.x - (rc.left + rc.right) / 2;
        double y = point.y - (rc.top + rc.bottom) / 2;
    
        // Apply ellipse formula
        return ((x * x) / (a * a) + (y * y) / (b * b) <= 1);
    }
    

The function works by calculating whether the point is within the boundary of the ellipse. The GetDrawRect function is called to make the necessary adjustments to the bounding rectangle if the value of the CircleShape property is TRUE.

The variables a and b are set to the horizontal and vertical radii of the ellipse. Based on the given point, the variables x and y are translated into the coordinates that are offsets from the center of the ellipse. The last line returns the Boolean result of the calculation, using the standard formula for an ellipse. Note that this calculation is also valid for a circle because a circle is simply a special case of an ellipse.

The mouse message handlers perform hit testing by passing the point coordinates that they receive as parameters to the InCircle member function. If InCircle returns TRUE, the circle is painted appropriately.