Dragging points to change the shapes

2019-06-09 16:36发布

问题:

I have managed to connect 4 points where the mouse click is made using the following code.(I am using MFC).

  void CChildView::OnLButtonDown(UINT nFlags,CPoint point)
  {    
  if(m_LastPoint.x!=-1 && m_iPointAmount<6)
  {
    CDC* pDC= GetDC();
    pDC->MoveTo(m_LastPoint.x,m_LastPoint.y);
    pDC->LineTo(point.x,point.y);
  }
    m_LastPoint=point;
    m_iPointAmount++;
  }

The variables are initialized in the constructor as follows.

 m_LastPoint.x=-1;
 m_LastPoint.y=-1;
 m_iPointAmount=1;

I want to do the following now.

1.Whenever the mouse click is made on one of the points and dragged, the point should relocate to the new position.(so the shape is changed).

2.This should be applicable for all the four points.

Pls guide me on how to achieve this.

回答1:

how this works

start clicking on the window until you reach the amount sepcified in m_iPolygonMaximumSides. When you reach the amount of points specified the polygon will be closed, so now you are able to select a point. Click near a point to select it, the drag will keep going until you click again. To reset the polygon you will have to close the window.

code

in the cpp file of your CChildView class add the following include, because it is used to calculate square root

#include <math.h>

in your CChildView class add the following methods and variables

CList<CPoint> m_PointList;
CPoint m_selectedPoint;
int m_iPolygonMaximumSides;
afx_msg void OnMouseMove(UINT nFlags, CPoint point);
void DrawPolygonFromList();

in the message map of your CChildView class add these lines

ON_WM_LBUTTONDOWN()
ON_WM_MOUSEMOVE()

in the CChildView constructor initialize m_iPolygonMaximumSides with the amount you want (4) and m_selectedPoint with (-1,-1) like

m_iPolygonMaximumSides = 4;
m_selectedPoint = CPoint(-1,-1);

then this is to be added to your CChildView cpp file, these are all the moethods used

void CChildView::OnLButtonDown(UINT nFlags, CPoint point)
{

    //check if we already reached the maximum point number
    if (m_PointList.GetSize() == m_iPolygonMaximumSides)
    {
        //check if a point was already selected, and so we are in the drag mode
        if (m_selectedPoint.x !=-1)
        {
            //if the point was already selected it means that we want to stop the dragging,
            //so we just set the x to -1
            m_selectedPoint.x =-1;
        }
        else
        {
            //if we didn't have a point selected we have to check if the point clicked is one of our points
            //so we will use this for to search for out point
            for (POSITION pos = m_PointList.GetHeadPosition();pos != NULL;m_PointList.GetNext(pos))
            {
                CPoint currentPoint = m_PointList.GetAt(pos);
                //this is the pythagorean theorem to find a distance between two points A and B
                // distance = squareRoot( (A.x-B.x)^2+(A.y-B.y)^2)
                int distanceBetweenPoints = floor(sqrt(pow(double(currentPoint.x-point.x),2)+pow(double(currentPoint.y-point.y),2)));
                //if this distance is less than 10 pixels, then we accept it as a click on our points
                //this is just a tollerance, so we can reduce or increment it as we like
                //the smaller the tollerance nearer you will have to click to be able to select the point
                if (distanceBetweenPoints <= 10)
                {
                    //if the tollerance is met then we set the point as our selected point
                    m_selectedPoint = currentPoint;
                    //interrupt the iteration, because we don't need to look further
                    break;
                }
            }
        }
    }
    //if we didn't reach the maximum point amount it means that we still have to keep going on getting the points
    else if (m_PointList.GetSize() > 0)
    {
        CDC* pDC= GetDC();
        CPoint lastPoint = m_PointList.GetTail();
        //draw a line from the previous (last) point to the new one
        pDC->MoveTo(lastPoint.x,lastPoint.y);
        pDC->LineTo(point.x,point.y);

        //if we are going to reach the maximum amount of points then we will have to close the polygon
        if (m_PointList.GetSize()==m_iPolygonMaximumSides-1)
        {
            CPoint firstPoint = m_PointList.GetHead();
            //draw a line from the current point to the first point
            pDC->MoveTo(point.x,point.y);
            pDC->LineTo(firstPoint.x,firstPoint.y);
        }
    }
    //add the point to the list only after you have done everything, only if we didn't reachthe maximum amount
    if (m_PointList.GetSize() < m_iPolygonMaximumSides)
        m_PointList.AddTail(point);
}


void CChildView::OnMouseMove(UINT nFlags, CPoint point)
{
    //check if we already have the maximum number of points
    if (m_PointList.GetSize()==m_iPolygonMaximumSides)
    {
        //check i
        if (m_selectedPoint.x != -1)
        {
            //check if we actually find the point
            POSITION posFound = m_PointList.Find(m_selectedPoint);
            if (posFound != NULL)
            {
                //update the selected point with the new one
                m_selectedPoint=point;
                //now also update the list
                m_PointList.SetAt(posFound,point);
                //draw the polygon
                DrawPolygonFromList();
            }
        }
    }
}

void CChildView::DrawPolygonFromList()
{
    //this is checked again because we might want to use this function in another place
    if (m_PointList.GetSize()==m_iPolygonMaximumSides)
    {
        //use this to clear the window
        RedrawWindow();
        //this will be used to draw
        CDC* pDC= GetDC();
        POSITION pos = m_PointList.GetHeadPosition();
        //load the first and second point
        CPoint pointBefore = m_PointList.GetNext(pos);
        CPoint currentPoint = m_PointList.GetNext(pos);
        //draw the line connecting the first and the second point
        pDC->MoveTo(pointBefore.x,pointBefore.y);
        pDC->LineTo(currentPoint.x,currentPoint.y);

        //draw the intermediary points
        while (pos != NULL) 
        {
            pointBefore = currentPoint;
            currentPoint = m_PointList.GetNext(pos);
            pDC->MoveTo(pointBefore.x,pointBefore.y);
            pDC->LineTo(currentPoint.x,currentPoint.y);
        } 
        //now close the poligon
        pointBefore = currentPoint;
        currentPoint = m_PointList.GetHead();
        pDC->MoveTo(pointBefore.x,pointBefore.y);
        pDC->LineTo(currentPoint.x,currentPoint.y);
    }
}


标签: mfc gdi