SuperMap IObjects C++组件学习笔记(三) - 利用组件绘制的回调方法控制自定义绘制

利用IObjects C++组件绘制的回调方法实现(控制)自定义绘制

一、IObjects C++组件自定义绘制概述

利用IObjects C++组件的绘制回调函方法来实现自定义流程的绘制。IObjects C++组件在地图绘制开始前、绘制完成后,图层绘制完成前、绘制完成后都可以回调我们自己的方法,并将绘制时是Graphics传出来,得到这个Graphics,我们就可以在利用他直接在地图上绘制我们想要的数据。
下面就分别说说在地图绘制完成后和图层绘制完成后来进行回调自定义绘制的方法

二、地图绘制完成后的回调方法

在IObjects C++组件中,当地图绘制完成后,组件会回调

 AfterMapDrawProc(UGlong pWnd,UGGraphics* pGraphics)

其中UGlong pWnd存储的是一个指针,在常见的各平台上,指针和long所占内存长度都为系统位数,即x64系统的long和指针都占64位,基于此特性,我们可以将一个指针转换为UGlong类型传入回调方法,并在方法中强制转换回我们原来的指针类型。这里我们将this传入,就可以在回调方法中执行当前类中的方法。

首先我们需要在组件中注册我们的回调方法,即让组件在完成指定动作时调用我们的回调方法:

pMap->SetAfterMapDrawFunc(DrawnCallBack,UGlong(this));

pMap为当前绘制的地图,DrawnCallBack为我们自己的回调函数指针,this当前类。
然后我们在当前类CPP文件的最上面添加我们的DrawnCallBack方法:

void UGSTDCALL DrawnCallBack(UGlong pWnd,UGGraphics* pGraphics)
{
}

这时在地图绘制完成后就会调用DrawnCallBack(UGlong pWnd,UGGraphics* pGraphics)方法。
我们就可以在这个方法里按照我们所需要的流程来实现图像绘制。
这里我写了一个JustDraw类,在该类里,我事先查询并获取到我需要绘制的地理数据:

//查询获取数据集中的地理要素
QList<UGGeometry *>* JustDraw::getGeomentry(UGString dataSetName, QList<UGGeometry *>* list)
{
    //m_pWorkspace为之前加载地图时打开的Workspace,其中已经有名为"China400"的中国地理数据源,
    //数据源中有名为"China_CitDistrict_P"的点数据集
    UGDataSource* pDataSource = m_pWorkspace->GetDataSource(_U("China400"));
    //GetDataset()方法返回的是一个UGDataset类型,该类型为素有数据集类型的基类,
    //由于我已知我要得到的数据集是矢量数据,所以直接强转为UGDatasetVector
    UGDatasetVector* pDvNode = (UGDatasetVector*)(pDataSource->GetDataset(dataSetName));

    //新建查询信息
    UGQueryDef qdf;
    qdf.m_nType = UGQueryDef::General;//查询类型:一般的属性条件查询
    qdf.m_nOptions = UGQueryDef::Both;//查询选项:几何对象(Geometry)和属性(Attribute)都查询
    qdf.m_nMode = UGQueryDef::GeneralQuery;//查询模式:一般查询(非模糊查询)
    qdf.m_nCursorType = UGQueryDef::OpenStatic;//游标类型:静态游标

    //查询
    //查询后,满足条件的要素会存到一个UGRecordset链表中,查询的返回值为该链表头的指针
    UGRecordset* pRsNewObjs = pDvNode->Query(qdf);

    //为确保我们得到的指针是链表表头,我们需要MoveFirst()一下,当然,当前代码中这句可省略
    pRsNewObjs->MoveFirst();

    //遍历,如果不为UGRecordset链表结尾

    while(!pRsNewObjs->IsEOF())
    {
        UGGeometry* geometry = NULL;//GetGeometry方法必须传入一个空指针或者自己carete一个UGGeometry传入,否则指针地址不会改变
        //从当前指针指向的链表记录中获取要绘制点的地理坐标
        if(pRsNewObjs->GetGeometry(geometry))
        {
            //将地理坐标存入list的QList<QPointF>中并移动链表指针
            list->append(geometry);
        }

        pRsNewObjs->MoveNext();
    }
    pDvNode->ReleaseRecordset(pRsNewObjs);

    return list;
}

//向Graphics上绘制地理要素
void JustDraw::DrawGeometry(UGGraphics *pGraphics, QList<UGGeometry *> *geometies, UGStyle *style)
{
    //获取到地图的Drowing,其中包含当前地图的比例尺、坐标系等
    UGDrawing* pDrawing = m_pMapEditWnd->m_mapWnd.m_Map.GetDrawing();
    //将绘制所用的Graphics绑定到Drowing,并保存之前的Graphics
    UGGraphics *pOldGraphics = pDrawing->SetGraphics(pGraphics);
    bool prepared = false;

    foreach(UGGeometry* geo, *geometies)
    {
        if(!prepared)//如果没有准备过样式,则准备
        {
            if(style)//如果有传入样式,则使用传入的样式绘制
            {
                pDrawing->Prepare(*style, geo->GetDimension());
            }
            else//如果没有传入样式,则创建
            {
                style = new UGStyle;

                style->SetMarkerSize(3);

                pDrawing->Prepare(*style, geo->GetDimension());
            }
            prepared = true;
        }
        //绘制图像
        pDrawing->Draw(geo);
    }
    //绘制完释放Drowing,如果不释放,Drawing里的画笔画刷会保留,可能影响下次绘制
    pDrawing->Release();
    //完成绘制后将Graphics还原
    pDrawing->SetGraphics(pOldGraphics);
}

//m_pGeosCity,m_pGeosCapital为QList容器的指针
QList<UGGeometry*>* m_pGeosCity = new QList<UGGeometry*>;
QList<UGGeometry*>* m_pGeosCapital = new QList<UGGeometry*>;
JustDraw* m_pJd = NULL;

void UGMapControl::init()
{
    m_pJd = new JustDraw(this);
    //获取需要绘制的地理数据China_CitDistrict_P、China_Capital_P(城市和省会)
    m_pJd->getGeomentry(_U("China_CitDistrict_P"), m_pGeosCity);
    m_pJd->getGeomentry(_U("China_Capital_P"), m_pGeosCapital);
}

这时,我们就可以在我们的回调方法中去调用自己的绘制方法来像图像中绘制东西了:

void UGSTDCALL DrawnCallBack(UGlong pWnd,UGGraphics* pGraphics)
{
    // 这里pw指针即为注册回调方法时传入的this指针
    UGMapControl* pw = (UGMapControl*)pWnd;
    pw->CapitalModifyDraw(pGraphics);
}
void UGMapControl::CapitalModifyDraw(UGGraphics *pGraphics)
{
    //创建一个样式用回省会绘制
    UGStyle sty;
    sty.SetMarkerSize(5);//点大小,5
    sty.SetLineColor(UGRGB(255,0,0));//设置点颜色为红色

    m_pJd->DrawGeometry(pGraphics,m_pGeosCapital,&sty);//使用给定的Style绘制
}

三、 图层绘制完成后的回调方法

与上面地图绘制完成后的回调方法类似,在地图的每一个图层绘制前后都会有回调方法,这里我们注册图层绘制完成时的回调方法:

pMap->m_Layers.SetAfterLayerDrawFunc(AfterLayerDrawCallBack,UGlong(this));

其中AfterLayerDrawCallBack为图层绘制完成后的回调方法指针:

void UGSTDCALL AfterLayerDrawCallBack(UGlong pWnd,UGint nLayerIndex,UGGraphics* pGraphics,LayerDrawReport& layerDrawReport, const UGString& strIndexInLayers)
{
}

pWnd为注册时传入的this指针nLayerIndex为图层索引(编号),layerDrawReport为性能分析时使用这里暂不探讨,strIndexInLayers为图层索引字符串,在有图层分组的情况下虚根据该字符串才能判断出绘制的是哪个图层。

和绘制完成后的自定义绘制一样,在LayerDrawCallBack`方法中实现我们的绘制:

void UGSTDCALL AfterLayerDrawCallBack(UGlong pWnd,UGint nLayerIndex,UGGraphics* pGraphics,LayerDrawReport& layerDrawReport, const UGString& strIndexInLayers)
{
    UGMapControl* pw = (UGMapControl*)pWnd;
    //判断,完成的绘制的图层是指定图层则绘制
    if(nLayerIndex == 8)
    {
        pw->CityModifyDraw(pGraphics);
    }
}

void UGMapControl::CityModifyDraw(UGGraphics *pGraphics)
{
    m_pJd->DrawGeometry(pGraphics,m_pGeosCity);
}

本文对应完整源码请转至:http://download.csdn.net/detail/ufolr/8599801

你可能感兴趣的:(C++,Gis,supermap,地图绘制)