Click here to Skip to main content
14,325,129 members
Rate this:
Please Sign up or sign in to vote.
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
Rate this:
Please Sign up or sign in to vote.

Solution 2

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>
   
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
Rate this:
Please Sign up or sign in to vote.

Solution 1

[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 {
   /* ... */
}
   
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()));
sooraj subramanya 17-May-11 6:03am
   
Thanks for the solution . I have implemented the same. But the the solution you have provided fails when i decrease the size of the ellipse.

When i decrease the size of an ellipse the handles wont be available at 22.5 degree...

By which wrong cursors are displayed. Ex:
TopRightShape = LeftRightArrowShape.... etc
Stefan_Lang 17-May-11 6:19am
   
Ah, I see. I just checked it using the Ellipse shape in the Word document, and it looks like the 'Mid' handles don't get displayed when the size in that direction is not sufficiently large to differentiate between the corner and the mid handles.

The code should work, but you may not be able to access some of the handle, so you may have to
(a) save the rotary angle with respect to the original position and direction when you created the ellipse (if you didn't do that already)
(b) save the shape info of the four different arrow shapes used in the original image (make sure to make a copy, not just save the pointer, which may or may not be valid later)
(c) check whether the handles you want to modifiy are actually visible (if not you don't need to change them)
(d) determine the required arrow shape based on the 'total' rotary angle and the shape info you saved.

I'm sorry I don't know the functions required for any of these steps (especially saving or copying the shape info), but with the help of the documentation this shouldn't be too hard, I hope.

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




CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100