VC++开发GIS系统(128)选择点类的实现

前文《VC++开发GIS系统(127)选择点类的设计》中已经对选择点做了一个定义,本文介绍实现的代码:

代码实现

/*
* 选择点实现
*/
malaPoint CmalaPointsSelect::m_pnt;
malaPointPro CmalaPointsSelect::m_PntPro;
CView* CmalaPointsSelect::m_StaticView = NULL;
malaScreen* CmalaPointsSelect::m_Screen = NULL;

CmalaPointsSelect::CmalaPointsSelect()
{

}

CmalaPointsSelect::CmalaPointsSelect(CView* mView, malaScreen *pScreen, CString &fileFullPath)
{
    mBaseView = mView;
    m_StaticView = mView;
    mPath = fileFullPath;

    m_bDraw = FALSE;
    m_Selected = FALSE;
    m_Screen = pScreen;
}

CmalaPointsSelect::~CmalaPointsSelect()
{

}

void CmalaPointsSelect::LButtonDown(UINT nFlags, malaPoint point)
{
    m_bDraw = TRUE;
    m_ptOrigin = m_perPoint = point;
}

void CmalaPointsSelect::LButtonUp(UINT nFlags, malaPoint point)
{
    m_bDraw = FALSE;
    malaCDC dc(mBaseView, *m_Screen);
    dc.drawRectNULLFill(m_ptOrigin, point);
    if (m_ptOrigin.x > point.x)
    {
        m_rect.xmax = m_ptOrigin.x;
        m_rect.xmin = point.x;
    }
    else
    {
        m_rect.xmin = m_ptOrigin.x;
        m_rect.xmax = point.x;
    }

    if (m_ptOrigin.y > point.y)
    {
        m_rect.ymax = m_ptOrigin.y;
        m_rect.ymin = point.y;
    }
    else
    {
        m_rect.ymin = m_ptOrigin.y;
        m_rect.ymax = point.y;
    }
    //先获取所有符合条件的点
    CPointIO pio;
    vector<malaPointFile>allPoints;
    pio.getAllPoint(*m_Screen, allPoints, mPath);
    //再查找是否被选中
    malaLogic tlog;
    for (size_t j = 0; j < allPoints.size(); j++)
    {
        if (tlog.isPntInRect(allPoints[j].m_point, m_rect))
        {
            m_pnt = allPoints[j].m_point;
            m_PntPro = allPoints[j].m_pointpro;
            CPoint A, B;
            A.x = long(m_pnt.x - m_PntPro.pointRadio);
            A.y = long(m_pnt.y - m_PntPro.pointRadio);
            B.x = long(m_pnt.x + m_PntPro.pointRadio);
            B.y = long(m_pnt.y + m_PntPro.pointRadio);
            SetTimer(mBaseView->m_hWnd, 1, 500, TimerProc);
            if (MessageBox(mBaseView->m_hWnd, L"选择该点吗?", L"提示", MB_YESNO | MB_ICONQUESTION) == IDYES)
            {
                KillTimer(mBaseView->m_hWnd, 1);
                mBaseView->InvalidateRect(CRect(A, B), TRUE);
                malaCDC dc(mBaseView,*m_Screen);
                dc.drawSelectRectPoint(m_pnt, m_PntPro);
                m_Selected = TRUE;
                break;
            }
            KillTimer(mBaseView->m_hWnd, 1);
            mBaseView->InvalidateRect(CRect(A, B), TRUE);
        }
    }
}

void CmalaPointsSelect::MouseMove(UINT nFlags, malaPoint point)
{
    if (m_bDraw)
    {
        malaCDC dc(mBaseView, *m_Screen);
        dc.drawRectNULLFill(m_ptOrigin, m_perPoint);
        dc.drawRectNULLFill(m_ptOrigin, point);
        m_perPoint = point;
    }

}

代码解析

因为定义了静态变量,所以在类的实现的时候需要先赋值

malaPoint CmalaPointsSelect::m_pnt;
malaPointPro CmalaPointsSelect::m_PntPro;
CView* CmalaPointsSelect::m_StaticView = NULL;
malaScreen* CmalaPointsSelect::m_Screen = NULL;

关于静态变量,推荐参考:C++中Static作用和使用方法。这里实现的橡皮筋绘图和放大地图中所用的一致,可以参考:VC++开发GIS系统(110)放大地图之简析橡皮筋绘图

这里比较关键的是在LButtonUp的时候,先获取当前所有的点,并遍历所有的点。如果点在所拉矩形框中(用到了isPntInRect函数,参考:VC++开发GIS系统(93)窗口的重绘(三)),使用SetTimer,每隔500ms调用一次函数TimerProc,实现点的闪烁。如果是要选中的点,则使用KillTimer关闭闪烁,并使用InvalidateRect实现局部刷新,不必全部重绘,然后使用drawSelectRectPoint函数在选中点周围做一个标记。代码如下:

/*
* 绘制选中状态的外接矩形
*/
void malaCDC::drawSelectRectPoint(malaPoint Point, malaPointPro PntPro)
{
    PntPro.pointRadio++;
    
    CClientDC dc(mView);

    LOGBRUSH log;
    log.lbColor = RGB(0 ,139, 139);
    log.lbStyle = BS_SOLID;

    CPen pen(PS_GEOMETRIC | PS_DASH, 2, &log);
    CPen* OldPen = dc.SelectObject(&pen);
    
    CPoint Point1, Point2;
    CoordToScreen(Point.x - PntPro.pointRadio, Point.y + PntPro.pointRadio, mScreen, &Point1.x, &Point1.y);
    CoordToScreen(Point.x + PntPro.pointRadio, Point.y - PntPro.pointRadio, mScreen, &Point2.x, &Point2.y);

    dc.Rectangle(CRect(Point1, Point2));
    dc.SelectObject(OldPen);

}

效果如下:

详细代码可以参考:GitHub

VC++开发GIS系统(127)选择点类的设计 VC++开发GIS系统(129)选择点之菜单响应

作者:,GIS爱好者。
分享本文,请您带上本文链接
分享到:

发表评论