Click here to Skip to main content
15,885,216 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I have drawn an Ellipse. Have given 8 handle to it. Handles are TopLeft, MidTop,TopRight, MidLeft, MidRight, BottomLeft, MidBottom,BottomRight. Whenever a user hovers on any of these handles cursor gets displayed.

For displaying the cursor i have referred MS-WORD shape ellipse.

Problem arrives when i roatate or i make a mirror image of an ellipse I am not able to rearrange the Co-ordinates ,hence the cursors are not displayed properly.

Please Help. Tried in google,found no relevant answers.

Note: Please open MS-WoRD.
Goto "INSERT"
Select "SHAPPES"
In that select "Ellipse" shape.
Draw it.
If you click on it you will see 8 points surrounding ellipse shape. Those are called handles. If you hover your mouse on any of the handle check the cursor display. Cursor display is depending the handle.
I need to implement the same functionality as it is in MS-WORD in VC++.
Posted
Updated 16-May-11 22:27pm
v2

if( IsSelected())
			{
				UINT iTopLeft_BottomRight_Cursor = 0;
				UINT iMidTop_MidBottom_Cursor = 0;
				UINT iTopRight_BottomLeft_Cursor = 0;
				UINT iMidLeft_MidRight_Cursor = 0;
				float fRotationAngle = 0.0f;
				GetRotationAngleForFrame(GetCurrentFrame(), fRotationAngle);
				int nRotAngle = Round(fRotationAngle * (180.0f/PI));
}           
 
 if (
                ( (nRotAngle > 0) && (nRotAngle < 23 ) )
                || ( (nRotAngle > 180) && (nRotAngle < 203) )
                || ( (nRotAngle > 270) && (nRotAngle < 293) )
                || ( (nRotAngle > 90 ) && (nRotAngle < 113) )
                )
            {
                iTopLeft_BottomRight_Cursor =   CURSOR_NESW;
                iMidTop_MidBottom_Cursor    =   CURSOR_EW;
                iTopRight_BottomLeft_Cursor =   CURSOR_NWSE;
                iMidLeft_MidRight_Cursor    =   CURSOR_NS;
            }
            else if (
                (nRotAngle > 337)
                || (nRotAngle > 157 && nRotAngle <= 180)
                || (nRotAngle == 0 )
                || (nRotAngle > 67 && nRotAngle < 91)
                || (nRotAngle > 247 && nRotAngle <= 270)
                )
            {
                iTopLeft_BottomRight_Cursor =   CURSOR_NWSE;
                iMidTop_MidBottom_Cursor    =   CURSOR_NS;
                iTopRight_BottomLeft_Cursor =   CURSOR_NESW;
                iMidLeft_MidRight_Cursor    =   CURSOR_EW;
            }
            else if (
                (nRotAngle > 22 && nRotAngle < 68)
                || (nRotAngle > 202 && nRotAngle < 248)
                || (nRotAngle > 112 && nRotAngle < 158)
                || (nRotAngle > 292 && nRotAngle < 338)
                )
            {
                iTopLeft_BottomRight_Cursor =   CURSOR_EW;
                iMidTop_MidBottom_Cursor    =   CURSOR_NWSE;
                iTopRight_BottomLeft_Cursor =   CURSOR_NS;
                iMidLeft_MidRight_Cursor    =   CURSOR_NESW;
            }
            UpdateHandlesWhenHover();
           
            if (m_TopLeftRect.PtInRect(pt) || m_BottomRightRect.PtInRect(pt) )
            {
                if(hCursor)
                {
                    DestroyIcon(hCursor);
                    hCursor = NULL;
                }
                hCursor = GetCustomCursor(AfxGetInstanceHandle(), iTopLeft_BottomRight_Cursor, _T("PNG"));
            }
            else if (m_MidTopRect.PtInRect(pt) || m_MidBottomRect.PtInRect(pt))
            {
                if(hCursor)
                {
                    DestroyIcon(hCursor);
                    hCursor = NULL;
                }
                hCursor = GetCustomCursor(AfxGetInstanceHandle(), iMidTop_MidBottom_Cursor, _T("PNG"));
            }
            else if (m_TopRightRect.PtInRect(pt) || m_BottomLeftRect.PtInRect(pt))
            {
                if(hCursor)
                {
                    DestroyIcon(hCursor);
                    hCursor = NULL;
                }
                hCursor = GetCustomCursor(AfxGetInstanceHandle(), iTopRight_BottomLeft_Cursor, _T("PNG"));
            }
            else if (m_MidLeftRect.PtInRect(pt) || m_MidRightRect.PtInRect(pt) )
            {
                if(hCursor)
                {
                    DestroyIcon(hCursor);
                    hCursor = NULL;
                }
                hCursor = GetCustomCursor(AfxGetInstanceHandle(), iMidLeft_MidRight_Cursor, _T("PNG"));
            }
                       else if(IsPtWithinROI(pt))
            {
                if(hCursor)
                {
                    DestroyIcon(hCursor);
                    hCursor = NULL;
                }
                hCursor = GetCustomCursor(AfxGetInstanceHandle(), IDR_MOVE_CURSOR, _T("PNG"));
                break;
            }
            else
            {
                  if(hCursor)
                {
                    DestroyIcon(hCursor);
                    hCursor = NULL;
                }
                hCursor = GetCustomCursor(AfxGetInstanceHandle(), IDR_ARROW_CURSOR, _T("PNG"));
                   }
               }
        break;
    }
case CURSOR_ON_REGION:
    {
        //Temporarily SIZEALL cursor is loaded. It is to be changed to SIZEALL + ARROW.
        if(hCursor)
        {
            DestroyIcon(hCursor);
            hCursor = NULL;
        }
        hCursor = GetCustomCursor(AfxGetInstanceHandle(), IDR_MOVE_CURSOR, _T("PNG"));
        break;
    }
case CURSOR_ON_ROTATION_HANDLE:
    {
        if(hCursor)
        {
            DestroyIcon(hCursor);
            hCursor = NULL;
        }
        hCursor = GetCustomCursor(AfxGetInstanceHandle(), IDR_ROTATION_MARK_CURSOR, _T("PNG"));
        break;
    }
case CURSOR_ROTATING_REGION:
    {
        if(hCursor)
        {
            DestroyIcon(hCursor);
            hCursor = NULL;
        }
        hCursor = GetCustomCursor(AfxGetInstanceHandle(), IDR_ROTATING_MARK_CURSOR, _T("PNG"));
        break;
    }
default:
    {
        if(hCursor)
        {
            DestroyIcon(hCursor);
            hCursor = NULL;
        }
        hCursor = GetCustomCursor(AfxGetInstanceHandle(), IDR_ARROW_CURSOR, _T("PNG"));
 
        break;
    }
}
 
pmainDlg->m_hCursor = hCursor;
SetCursor(pmainDlg->m_hCursor);
 
 
UpdateHandlesWhenHover()
{
	CShapeCal cShapeCal;
	CRect rcMeasRect(0,0,100,100);
	CBaseMeasCal cBaseMeasCal;
	CPrecisionPoint  ptCenter;
	CList<CPrecisionPoint,CPrecisionPoint&> ptInputList;
	CPrecisionPoint  ptPoint;
	ptPoint = m_TopLeftRect.CenterPoint();
	ptInputList.AddTail(ptPoint);
	ptPoint = m_MidLeftRect.CenterPoint();
	ptInputList.AddTail(ptPoint);
	ptPoint = m_BottomLeftRect.CenterPoint();
	ptInputList.AddTail(ptPoint);
	ptPoint = m_MidTopRect.CenterPoint();
	ptInputList.AddTail(ptPoint);
	ptPoint = m_MidBottomRect.CenterPoint();
	ptInputList.AddTail(ptPoint);
	ptPoint = m_TopRightRect.CenterPoint();
	ptInputList.AddTail(ptPoint);
	ptPoint = m_MidRightRect.CenterPoint();
	ptInputList.AddTail(ptPoint);
	ptPoint = m_BottomRightRect.CenterPoint();
	ptInputList.AddTail(ptPoint);
	cBaseMeasCal.CalculateCenterPoint(ptInputList,ptCenter);
	CList<CPrecisionPoint,CPrecisionPoint&> ptOutputList;
	double dReturn = 0.0;
	dReturn = cShapeCal.SortEditPoint(rcMeasRect,ptInputList,ptCenter,ptOutputList);
	CPrecisionPoint ptTopLeft(-1,-1);
	//
	vector<CPoint> vectHandles;
	vectHandles.push_back(CPoint(m_TopLeftRect.CenterPoint()));
	vectHandles.push_back(CPoint(m_MidLeftRect.CenterPoint()));
	vectHandles.push_back(CPoint(m_BottomLeftRect.CenterPoint()));
	vectHandles.push_back(CPoint(m_MidTopRect.CenterPoint()));
	vectHandles.push_back(CPoint(m_MidBottomRect.CenterPoint()));
	vectHandles.push_back(CPoint(m_TopRightRect.CenterPoint()));
	vectHandles.push_back(CPoint(m_MidRightRect.CenterPoint()));
	vectHandles.push_back(CPoint(m_BottomRightRect.CenterPoint()));
	::sort(vectHandles.begin(), vectHandles.end(), SortingFunction());
	ptTopLeft = vectHandles[0];
	POSITION position = ptOutputList.GetHeadPosition();
	while( position != NULL )
	{
		ptPoint  = ptOutputList.GetNext(position);
		if(ptTopLeft == ptPoint)
		{
			m_TopLeftRect.SetRect(ptPoint.x,ptPoint.y,ptPoint.x,ptPoint.y);
			m_TopLeftRect.InflateRect(ROI_HANDLE_MARGIN,ROI_HANDLE_MARGIN);
			if( position == NULL )
			{
				position = ptOutputList.GetHeadPosition();
			}
			ptPoint  = ptOutputList.GetNext(position);
			m_MidTopRect.SetRect(ptPoint.x,ptPoint.y,ptPoint.x,ptPoint.y);
			m_MidTopRect.InflateRect(ROI_HANDLE_MARGIN,ROI_HANDLE_MARGIN);
			if( position == NULL )
			{
				position = ptOutputList.GetHeadPosition();
			}
			ptPoint  = ptOutputList.GetNext(position);
			m_TopRightRect.SetRect(ptPoint.x,ptPoint.y,ptPoint.x,ptPoint.y);
			m_TopRightRect.InflateRect(ROI_HANDLE_MARGIN,ROI_HANDLE_MARGIN);
			if( position == NULL )
			{
				position = ptOutputList.GetHeadPosition();
			}
			ptPoint  = ptOutputList.GetNext(position);
			m_MidRightRect.SetRect(ptPoint.x,ptPoint.y,ptPoint.x,ptPoint.y);
			m_MidRightRect.InflateRect(ROI_HANDLE_MARGIN,ROI_HANDLE_MARGIN);
			if( position == NULL )
			{
				position = ptOutputList.GetHeadPosition();
			}
			ptPoint  = ptOutputList.GetNext(position);
			m_BottomRightRect.SetRect(ptPoint.x,ptPoint.y,ptPoint.x,ptPoint.y);
			m_BottomRightRect.InflateRect(ROI_HANDLE_MARGIN,ROI_HANDLE_MARGIN);
			if( position == NULL )
			{
				position = ptOutputList.GetHeadPosition();
			}
			ptPoint  = ptOutputList.GetNext(position);
			m_MidBottomRect.SetRect(ptPoint.x,ptPoint.y,ptPoint.x,ptPoint.y);
			m_MidBottomRect.InflateRect(ROI_HANDLE_MARGIN,ROI_HANDLE_MARGIN);
			if( position == NULL )
			{
				position = ptOutputList.GetHeadPosition();
			}
			ptPoint  = ptOutputList.GetNext(position);
			m_BottomLeftRect.SetRect(ptPoint.x,ptPoint.y,ptPoint.x,ptPoint.y);
			m_BottomLeftRect.InflateRect(ROI_HANDLE_MARGIN,ROI_HANDLE_MARGIN);
			if( position == NULL )
			{
				position = ptOutputList.GetHeadPosition();
			}
			ptPoint  = ptOutputList.GetNext(position);
			m_MidLeftRect.SetRect(ptPoint.x,ptPoint.y,ptPoint.x,ptPoint.y);
			m_MidLeftRect.InflateRect(ROI_HANDLE_MARGIN,ROI_HANDLE_MARGIN);
			break;
		}
	}
}
 
struct SortingFunction
{  
	bool operator()(const CRect& a, const CRect& b)
    {
        if (a.left == b.left)
            return a.top <= b.top;
        else
            return a.left < b.left;
	}
    bool operator()(const CPoint& a, const CPoint& b)
    {
        if (a.x == b.x)
            return a.y <= b.y;
        else
            return a.x < b.x;
    }
};<pre>
 
Share this answer
 
Comments
sooraj subramanya 18-May-11 4:16am    
Thanks for the help.
I have proposed the solution i hav implemented in which I store all the handles coordinates, if i rotate the shape, then i sort the points and assign lowest x as Top-Left then i display the cursor based on the angle of the shape
[edit]updated to reflect the additional info from the updated original post[/edit]

It's a bit hard to provide help when you don't really state what exactly you need help with. Please give us a bit more information on some or all of the following:

1. What is the question?
(a) You don't know how to set the coordinates of your 'handles'
(b) You don't know how to calculate the new positions of your 'handles'
(c) You set the new positions, but somehow it doesn't work

You don't know how to properly update the cursor shapes after rotation

2. Can the rotation be at an arbitrary angle?
(a) If so, should the handles be at the appropriate rotated positions (the geometrically sensible solution)
(b) or, if so, should the handles still be aligned to the x and y axis (MS standard)
(c) if not, what angles are possible


3. What has MS_WORD got to do with this?
--> see updated post

4. Depending on the details provided above, could you please post some code that you need help with, or that shows the current flow of your calculations
--> see snippets in responses below


P.S.: The best way to provide this information is by updating your original post. If you just post the answer as a comment here, people might miss it!

Solution to 1 (pseudocode):
 // check rotary angle in steps of 45 degrees
// since cursors are the same for opposite handles, the relevant
// ranges are [x-22.5 , x+22.5] and [x+180-22.5 , x+180+22.5]
if ((angle > 22.55 && angle <= 67.5) || (angle > 202.5 && angle <= 247.5)) {
   // update cursors to the next shapes, counter-clockwise
   MidRightShape = MidLeftShape = SlantedUpwardArrowShape;
   TopRightShape = BottomLeftShape = UpDownArrowShape;
   MidTopShape = MidBottomShape = SlantedDownwardArrowShape;
   TopLeftShape = BottomRightShape = LeftRightArrowShape;
}
else if ((angle > 67.5 && angle <= 112.5) || (angle > 247.5 && angle <= 192.5)) {
   // update to the second next shapes, counter clockwise
   MidRightShape = MidLeftShape = LeftRightArrowShape;
   TopRightShape = BottomLeftShape = SlantedUpwardArrowShape;
   MidTopShape = MidBottomShape = UpDownArrowShape;
   TopLeftShape = BottomRightShape = SlantedDownwardArrowShape;
}
else if (/*...*/) { // etc.
   /* ... */
}
else {
   /* ... */
}
 
Share this answer
 
v6
Comments
sooraj subramanya 17-May-11 4:28am    
Thanks for your replying. I have updated the question.
Please check it.
Stefan_Lang 17-May-11 4:41am    
Very good.

Now, if you have problems calculating the new positions (option 1.(b) above), then I can help you with that. If you have other problems (1.(a) or (c) or something else), then it would help to show the code that you currently have to update the handle positions. That way we could see what you do and don't understand.
sooraj subramanya 17-May-11 5:03am    
The problem is with rearranging the coordinates after i rotate,
If i roatate the ellipse slightly towards right (try in MS-WoRD). Which point do i consider as Top-Left?
struct SortingFunction
{
bool operator()(const CRect& a, const CRect& b)
{
if (a.left == b.left)
return a.top <= b.top;
else
return a.left < b.left;
}
I tried to rearrange with the above code. But it dint work for many cases.
Getting the top-left point after I rotate the ellipse is the main big problem i am facing right now.
Stefan_Lang 17-May-11 5:24am    
Ok. I'm not sure I can help you here, but I'll try to at least clarify:

1. The ellipse is defined by its position, width, height, and its rotary angle. For all purposes, these parameters are the same as for a rectangle.

2. Upon creation, you defined handles that you called 'TopLeft', etc. according to their position.

3. After rotating, you feel the need to reassign the handles according to the changed positions.
--> I believe you shouldn't change anything at all! If after rotating clockwise by 90 degrees the 'TopLeft' handle is now at the bottom left corner, so be it - 'TopLeft' is just a name! What you need to chenge is:
(a) update the position)
(b) update the cursor shape

Note that the behavious of the handles remains independent of the rotation: the 'Mid' handles will only adjust either the width or the height of the ellipse, whereas the others will adjust both! So you may not reassign the handles as a whole, you need to only change their position and cursor shape.

I suspect that you did (a), and noticed you needed to do something about (b). I don't know how to set cursor shapes, maybe someone else can help here. But with respect on chosing the shape I'll update my solution above. Give a a bit time to work it out for myself though.
sooraj subramanya 17-May-11 5:06am    
the order in which i passed the handles to sort is vector<crect> vectHandleRects;

// vectHandleRects.push_back(CRect(m_TopLeftRect.TopLeft(), m_TopLeftRect.BottomRight()));

// vectHandleRects.push_back(CRect(m_MidLeftRect.TopLeft(), m_MidLeftRect.BottomRight()));

// vectHandleRects.push_back(CRect(m_BottomLeftRect.TopLeft(), m_BottomLeftRect.BottomRight()));

// vectHandleRects.push_back(CRect(m_MidTopRect.TopLeft(), m_MidTopRect.BottomRight()));

// vectHandleRects.push_back(CRect(m_MidBottomRect.TopLeft(), m_MidBottomRect.BottomRight()));

// vectHandleRects.push_back(CRect(m_TopRightRect.TopLeft(), m_TopRightRect.BottomRight()));

// vectHandleRects.push_back(CRect(m_MidRightRect.TopLeft(), m_MidRightRect.BottomRight()));

// vectHandleRects.push_back(CRect(m_BottomRightRect.TopLeft(), m_BottomRightRect.BottomRight()));

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900