mapgis二次开发教程:
目前MAPGIS二次开发库主要以API函数、MFC(Microsoft Foundation Class)类库、Com组件、ActiveX 控件四种方式提供。开发库被封装在若干动态链接库(DLL)中。
API函数在使用方法上与Windows的API函数完全一样,因此是独立于开发工具的。无论您使用VC++、VB还是BC++、Dephi…,您在这些工具中如何调用Windows的API函数,您就可以怎么调用这些二次开发函数。
MAPGIS类库是为基于MFC类库的C++开发者提供的多个可重用基类,它将应用程序所需的常见基本功能作了封装,使用便利,改动灵活。开发者只需从类库派生即可使自己的程序获得从窗口显示控制到图形查询编辑的各项功能。
MAPGIS COM组件是MAPGIS新一代体系结构的表现,功能更加强大,使用更加便利。具有二次开发方便、易于集成、无限扩展等特点。支持多种开发软件,包括Visual C++、Visual Basic、Delphi、script、InterDev、Power Builder等,开发者可以多层次的访问MAPGIS组件的数据层、功能层和界面层。
ActiveX 控件是MAPGIS完成组件化改造的成果之一,它们使得二次开发更为快捷便利,代码的可复用性更高。
上述各类开发接口提供了从最基本数据单元的读取、保存、更新和维护到MAPGIS地图库的建立和漫游,以及空间分析,图象处理等一系列功能。其中,API函数是基础,使用上最灵活,但技巧性要求也最高。所以本书大量篇幅用于介绍C++ API函数。MAPGIS将不断丰富完善各类二次开发接口,以多种开发手段满足不同层次、不同应用的需求。这些函数所
?
在的C++头文件表4-1所示:
?
? 函数库名称 | ? C,C++说明文件 |
? 各类头文件集合 | ? MapGis.h |
? 工作区基础函数 | ? Win_area.h |
? 图形显示输出函数 | ? Map_out.h |
? 窗口操作API函数 | ? Win_oper.h |
? 图形显示函数 | ? Mapdisp.h |
? 图形编辑函数 | ? Mapedit.h |
? 拓扑操作函数 | ? Gistopo.h |
? 剪贴板操作函数 | ? clippaste.h |
? 数字化设备参数设置及初始化调用函数 | ? W32_Dig.h |
? 图框生成函数 | ? frmdll32.h |
? 投影变换函数 | ? projdll.h |
? 工作区投影变换函数 | ? cordcvt.h |
? 工程管理及拼版文件操作函数 | ? Map_prj.h |
? 窗口操作类库 | ? CGisView.h |
? 输入编辑类库 | ? CGisEdit.h |
? 工程管理类库 | ? CPrjEdit.h |
? 地图库读取显示函数 | ? Dbs_View.h |
? 空间分析函数 | ? Spc_anly.h |
? Tin基本操作函数 | ? TinBas32.h |
? Tin工作区函数 | ? Tin_area.h |
? 网络分析函数 | ? Net_oper.h |
? 统计分析和统计图制作函数 | ? Att_Sta.h |
? 转换函数 | ? GisConv.h |
? 客户化菜单函数 | ? Custom.h |
? 图像输入输出函数 | ? msiio.h |
?
表4-1 二次开发头文件
4.2 MAPGIS基本术语
下面介绍MAPGIS系统中经常使用的一些基本概念。
??? 地图:是按一定的数学法则和特有的符号系统及制图综合原则将地球表面的各种自然和社会经济现象缩小表示在平面上的图形,它反映制图现象的空间分布、组合、联系及在时空方面的变化和发展。
??? 窗口:是用户坐标系中的一个矩形区域。用户可以改变这个矩形的大小、或移动位置来选择所要观察的图形。窗口就象照相机的取景框,当我们瞄准不同的地方,就选取了不同的景物。离景物越远框内包括的景物越多而成像就小;当我们靠近它,所包括的景物越少,成像越大。利用窗口技术,我们可以有选择的考察图形的某一部分,观察图形的细致部分或全局。
??? 视区:是设备坐标系中的矩形区域,它是图形在设备上的显示区。可视区是在一定高程和一个或多个视点内,通过计算所得到的一个或多个视点的可见区域。
??? 图层:用户按照一定的需要或标准把某些相关的物体组合在一起,我们称之为图层。如地图中水系构成一个图层,铁路构成一个图层等。我们可以把一个图层理解为一张透明薄膜,每一层上的物体在同一张薄膜上。一张图就是由若干层薄膜叠置而成的,图形分层有利于提高检索和显示速度。
? ??靶区:是屏幕上用来捕获被编辑物体(图形)的矩形区域,它由用户在屏幕上形成。
?? ?控制点:控制点是指已知平面位置和地表
?
1 工作区介绍
?
?
??? 工作区是MAPGIS提出的一个概念,简单的说,工作区就是一个数据池,存放实体的空间数据、拓扑数据、图形数据和属性数据,每个工作区对应一个MAPGIS数据文件。MAPGIS开发函数库提供对工作区实施操作的一系列函数,如将工作区中的内容存盘,从盘上将数据装入工作区,对工作区中的内容进行添加、修改、删除、检索等等。对硬盘数据的存取及虚拟内存的管理等等复杂繁琐的工作无需应用程序的编程者去关心,而是有MAPGIS工作区管理模块自动完成。因此,深入了解工作区的逻辑结构和工作区操作函数的使用,是进行成功的二次开发的关键。
? ? ? |
?
2 工作区操作函数
?
??? MAPGIS的空间数据和属性数据的读写操作都是在工作区的基础上进行的,工作区是应用程序和数据文件的桥梁,他保证了数据的一致性、完整性。
?
? [工作区操作流程]
?? 1)初始化工作区实例(_InitWorkArea)
?? ???可循环执行2-5步
?? 2)打开工作区(点,线,区,网,表)(_OpenArea)
?? 3)装文件至工作区(_LoadFile)
?? 4)...实体(图形,属性)操作,表格操作......
?? 5)关闭打开的工作区(_CloseArea)
?? 6)释放工作区实例(_FreeWorkArea)
工作区实例是MAPGIS为了便于管理工作区而定义的句柄。
MAPGIS应用程序在结束之前,必须调用_CloseAllArea函数或者_FreeWorkArea函数,以便关闭所有工作区并且释放工作区实例。_CloseAllArea函数和_FreeWorkArea函数功能相同。
C示范5-1:打开点工作区,装入点文件:
??? AREA_HINST AHInst;
short?? AiPnt;
AHInst = _InitWorkArea(NULL);
AiPnt =_OpenArea(AHInst,PNT);
If(_LoadFile(AiPnt) > 0)
{
…..//实体操作
}
??? //关闭工作区
??? if(_IsOpenArea(AiPnt))? //如果工作区打开
??? {
??????? _SetChangeFlag(AiPnt, 0); //如果工作区改变了,且不想保留更改的内容
??????? _CloseArea(AiPnt);
??? }
??? _FreeWorkArea(AHInst);
?
3 工作区函数
?
1)AREA_HINST _InitWorkArea(HINSTANCE hInst);//初始化工作区实例
2)int _FreeWorkArea(AREA_HINST ahInst);//释放工作区实例
3)short _OpenArea(AREA_HINST,short type);//打开某种类型的工作区
4)int _CloseArea(short ai);//关闭指定的工作区
5)short _LoadAFile(char * datName,short ai);//将某个文件装入指定的工作区,datName为文件名指针,必须带路径
short _LoadFile(short ai);
6)char _GetAreaType(short ai); ?? //取工作区文件类型
7)short _IsAreaEmpty(short ai); ? //指定的工作区是否为空
8)short _IsOpenArea(short ai);???? //指定的工作区是否已经打开? ?
9)short _GetAreaNumber(AREA_HINST? ahInst); //获取打开的工作区数
10)short _GetFirstAreaNo(AREA_HINST ahInst);//取属于ahInst实例的第一个工作区号。
11)short _GetNextAReaNo(AREA_HINST ahInst);//取属于ahInst实例的下一个工作区号。??
12)short _SetPackFlag(short ai,short flag);//设置数据压缩标志,flag=0/1:不压/压缩
13)short _SetChangeFlag(short ai,char chg);//设工作区改变标志
14)short _SaveFile(short ai,short ver=VERSION);??? //将工作区内容存入文件
_SaveAFile? //将工作区内容存入指定文件
注意:版本号ver只能取VERSION50或VERSION60。
?
??? C示范5-2:读取属于AREA_HINST实例的所有工作区(假设工作区已经打开)
short i,ai,an;
…
??? an = _GetAreaNumber(AHInst);
??? ai = _GetFirstAreaNo(AHInst);
??? for(i = 0; i < an; i++,ai = _GetNextAreaNo(AHInst))
??? {
??? ??? //使用工作区ai...
??? }
?
?
实体存取主要依据实体数据的唯一标识:实体号
实体类型有(Lin,Pnt,Nod,Reg,Net,Path)
?
1 取实体个数
??? _Get...Num:?? 逻辑数,物理数
如:
short WINAPI _GetLinNum(short ai,long *logN,long *n);
short WINAPI _GetRegNum(short ai,long *logN,long *n);
short WINAPI _GetPntNum(short ai,long *logN,long *n);
short WINAPI _GetNodNum(short ai,long *logN,long *n);
short WINAPI _GetNetNum(short ai,long *logN,long *n);
short WINAPI _GetPathNum(short ai,long *logN,long *n);
这里lonN返回逻辑数,n返回物理数。
?
2 取实体空间数据,图形数据
_Get...取得实体数据,图形数据信息。
如取线:
short WINAPI _GetLin(short ai,long li,D_DOT **dat,long *len,LIN_INFO *inf,short *dim=NULL);
dat和inf分别返回线数据和线信息。
?
3 实体操作
??? 1)取实体图形参数???? _Get...Info
??? 2)更新实体图形参数?? _Update....Info
??? 3)添加实体?????????? _Append...
??? 4)删除实体?????????? _Del...
5)撤销删除实体?????? _UnDel...
对空间实体,上述方法是相似的。
[注意]:函数返回值是short型,则1表示成功;0表示失败;-1表示该图元被删除;
返回值是long型,则不同的函数含义有所不同,对于_Append...函数,>0表示实体号,否则表示失败。
?? C示范5-3:将ai号工作区中所有黑色线改为兰色
long i,linN;
long len;
LIN_INFO linf;
D_DOT *lxy;
?? _GetLinNum(ai,&i,&linN); //取线实体数,i返回逻辑数,linN返回物理数
?? for(i = 1;i < linN; i++)
?? {
????? if(_GetLin(ai,i,&lxy,&len,&linf) <= 0)
??????? continue;
????? //处理线实体代码
if(linf.lclr==1)
{
?? linf.lclr=5;
?? _UpdateLinInfo(ai,i,&linf);
}
?? }
?
C示范5-4:取ai工作区中的所有点,并进行处理
??? long?????? i,pntN;
??? short????? len;
??? PNT_INFO?? inf;
??? D_DOT????? xy;
??? char?????? *dat;???????
_GetPntNum(ai,&i,&pntN);??? //取点数
for(i=1;i<pntN;i++)
{
if(_GetPnt(ai,i,&xy,&dat,&len,&inf)<=0)
???? continue;
switch(inf.type)
{
????? case PNT_NOTE: …?? break;? //处理字符串
????? case PNT_SUB: …??? break;? //处理子图
??? case PNT_CIR: …??? break;? //处理圆
??? case PNT_ARC: …??? break;? //处理弧
????? case PNT_IMAGE: …? break;? //处理图象
case PNT_TEXT: …?? break;? //处理文本
????? default:??? break;
}
…
}
C示范5-5:添加一个字符串类型的点,坐标为(500,500),内容为“中地公司”,颜色为红色,字高宽均为10,
??? PNT_INFO?? inf;
??? D_DOT????? xy;
??? char?????? dat[64];????????
xy.x=500;
xy.y=500;
lstrcpy(dat,”中地公司”);
memset(&inf,0,sizeof(PNT_INFO));
inf.type=PNT_NOTE;
inf.info.ch.height=10;
inf.info.ch.width=10;
inf.iclr=6;
_AppendPnt(ai,&xy,dat,lstrlen(dat),&inf);
?
C示范5-6:添加一条折线,颜色为绿色,坐标点为(20,50),(100,200),(200,200);
LIN_INFO inf;
D_DOT xy[3];
xy[0].x=20; xy[0].y=50;
?
一、显示输出的基本概念
??? 1. 逻辑坐标、设备坐标、窗口坐标、屏幕坐标
逻辑坐标:又称图形坐标或用户坐标,是用户处理自己的图形实际所采用的坐标系。
例如:用户自定义坐标、大地坐标、地理坐标。
设备坐标:是图形设备的坐标系。
例如:数字化仪,该设备的坐标原点一般在中心;
笔式绘图仪,该设备通常以步距为单位,以中心或某一角为原点。
注意:在MAPGIS二次开发中,应用程序窗口也是一种设备,它的设备坐标称为窗口设备坐标,它把某窗口的客户区当作将要绘图的设备,该坐标系以窗口客户区左下角为原点,右手坐标系。
窗口坐标:原点在指定窗口客户区左上角的坐标,以象素为单位,左手坐标系。
屏幕坐标:原点在屏幕左上角的坐标,以象素为单位,左手坐标系。
2. HDC、MyDC
DC、HDC:熟悉Windows编程的人,对DC、HDC的概念一定不会陌生。设备描述表(DC)不仅描述了设备对象、设备对象的属性以及图形显示模式;同时,还指向了一个实际的物理输出设备,包括设备名称、设备驱动程序以及其他一些信息。实际用GDI函数进行编程时,我们经常使用的是一个指向DC的句柄HDC。利用HDC,我们就可以避开千变万化的外部输出设备,以一种透明、简便的方式实现对图形设备的控制,最终达到我们所要实现的目的。在开始绘图前,如果您调用Windows API绘图函数,首先需获取当前绘图窗口的HDC。绘图结束后应释放该HDC。
MyDC:显示对象,有时候也称显示设备句柄,类似于Windows中的HDC, 是MAPGIS引入的一个新概念。在显示对象中集成了Windows的DC和MAPGIS基本显示处理的函数。MAPGIS的所有显示函数都是针对某一个显示对象的,即所有显示都显示在这个对象所联系的窗口上。每个窗口都对应不同的显示对象,都可以设置不同的图形模式和显示参数。在开始绘图前,如果您使用MAPGIS API绘图函数,首先需调用_GetMyDC获取当前绘图窗口的MyDC。绘图结束后应调用_DeleteMyDC释放该MyDC。
3. 显示模式、显示参数、显示范围
显示模式:MAPGIS的显示模式概念与Windows的显示模式概念类似。显示模式将决定最终的显示效果。函数_SetMyDCMode将显示对象设置为多边形交错填充模式、设备左下角为原点、右手坐标系。
显示参数:定义了视口原点坐标,x、y方向的缩放比例,显示角度等信息。通过对显示参数的设置,可实现地图的移动、放大、缩小等操作。函数_SetDispParam实现显示参数的设置。函数_GetDispParam实现显示参数的读取。
显示范围:显示对象所显示的地图的范围。函数_SetDispRect实现显示范围的设置。函数_GetDispRect实现显示范围的读取。
4. 还原显示、坐标点显示
还原显示:还原显示状态下,显示图元的函数按模拟输出的标准显示,所用的线型、图案等都显示出来,在这个状态下显示速度较慢;在非还原显示状态下,线型、图案等信息都不显示,汉字显示等函数也作了简化处理,故显示速度较快。可用_SetOriginalDisp函数来设置还原显示或非还原显示状态。
坐标点显示:在坐标点显示状态下,显示图元的函数在图元的坐标点处显示一个小的红十字,在编辑时可作为参考。可用_SetCoordPntDisp函数来设置坐标点显示或非坐标点显示状态。
5. 调色板、笔、刷子
调色板:MAPGIS有一套自己的调色板,该调色板是针对地图着色而设计的。调用_SetMyDCPalette函数可以将原来的Windows逻辑调色板替换为MAPGIS调色板。
笔:定义了画笔的颜色、笔宽、模式等信息。使用前,需用_SetPen函数来定义画笔;使用结束,应用函数_CleanPen来清除画笔。画线、画圆、画弧、显示字符串等函数多用到画笔。
刷子:定义了刷子的颜色、填充图案、笔宽、模式等信息。使用前,需用_SetBrush函数来定义刷子;使用结束,应用函数_CleanBrush来清除刷子。与画笔不同的是,刷子多用于与填充有关的函数。
?
二、图形显示输出的过程
在开始绘图或显示图形前,首先需获得图形显示设备句柄(HDC)或显示对象句柄(MyDC)。如果您调用Windows API绘图函数,则需获取当前绘图窗口的HDC,如果您使用MAPGIS API绘图函数,则需获取当前绘图窗口的MyDC。获得了显示设备句柄后,可以设置不同的图形模式和显示参数,接着可以开始绘图或进行图形显示了。在使用画笔绘图时,您需要设置画笔的颜色、笔宽、模式等。在使用刷子填充区域时,您同样需要设置刷子的颜色、填充图案、笔宽、模式等。在绘图完毕,需要将设置的画笔和刷子清除掉。在此过程中可能会涉及各类坐标之间的转换。
?
三、图形显示输出基本函数
??? 本章所有函数为MAPGIS API函数,函数头文件为map_out.h。
设备设置函数:
MyDC _GetMyDC(HWND hwnd,PAINTSTRUCT *lpps=NULL); //显示对象句柄的获取
void _DeleteMyDC(MyDC mdc); //删除显示对象句柄
void _SetMyDCMode(MyDC mdc); //设置显示对象图形模式
void _SetMyDCPalette(MyDC mdc); //设置设备调色板
short _SetDispParam(MyDC mdc,double fx0,double fy0,double fScalex,double fScaley = 0,double fAngle = 0); //设置显示参数
short _GetDispParam(MyDC mdc,double? *pfx0,double *pfy0,double *pfScalex,double *pfScaley= NULL,double *pfAngle=NULL); //获取显示参数
short _SetDispRect(MyDC mdc,D_RECT frc); //设置显示范围
short _GetDispRect(MyDC mdc,D_RECT *frc); //获取显示范围
/*设置特殊显示状态*/
short _SetOriginalDisp(MyDC mdc,short Origif); //设置还原显示状态
short _SetCoordPntDisp(MyDC mdc,short sCoord); //设置坐标点显示状态
short _SetMessageDisp(MyDC mdc,short Dispif); //设置错误信息提示状态
/*颜色锁定和解除*/
void _LockColor(MyDC mdc,COLORREF col); //颜色锁定
void _UnLockColor(MyDC mdc); //颜色锁定解除
short _GetLockState(MyDC mdc);//取颜色锁定状态
/*绘图工具设置*/
void _SetPen(MyDC mdc,int penno,int color);
void _CleanPen(MyDC mdc);
void _SetBrush(MyDC mdc,long bcol, short pno=0, double phei=1,long pcol=0);
void _CleanBrush(MyDC mdc);
void _SetPenColor(MyDC mdc, COLORREF clr);
void _CleanPenColor(MyDC mdc);
int? _SetPenMode(MyDC mdc,int nMode);
int? _GetPenMode(MyDC mdc);
/*逻辑坐标(或图形坐标)与设备坐标互换*/
void _LpToDp(MyDC mdc,D_DOT *pdP);
void _DpToLp(MyDC mdc,double *pfx,double *pfy);
显示、输出整个工作区:
short _DispPntArea(MyDC mdc,short ai,short layon=0);
short _DispLinArea(MyDC mdc,short ai,short layon=0);??
short _DispRegArea(MyDC mdc,short ai,short layon=0);
在用户坐标系下显示输出实体:
short _DispPnt(MyDC mdc,short ai,long gno,long col=0);
short _DispLin(MyDC mdc,short ai,long gno,long col=0);
short _DispReg(MyDC mdc,short ai,long gno,long col=0);
short _DispPnt(MyDC mdc,D_DOT xy,char *dat,short len,PNT_INFO *inf,long col=0);
short _DispLin(MyDC mdc,D_DOT? *lxy,long len,LIN_INFO *inf,long col=0);
short _DispReg(MyDC mdc,short ai,long *rdata,long len,REG_INFO *inf,long col=0);
在设备坐标系下显示输出实体 :
/*显示输出实体函数*/
void _DrawLine(MyDC mdc,POINT *xy,long len, long col=0); //画线
void _RegionFill(MyDC mdc,POINT *xy,int *ne, int regnum,int col=0);? //区域填充
short _DispString(MyDC mdc,double x,double y,float h, float w,char *str,short zt,short zx,float ang, float sp,char pl,long col=0);? //显示字符串
short _DispText(MyDC mdc,double x,double y,float px, float py,float h,float w,char *str,short zt, short zx, float ang, float sp,float ls,char pl,long col);
//显示文本
short _DispSubgr(MyDC mdc,long subno,double x,double y,double hei,double wid,double ang,long col=0); //显示子图
short? _DispImage(MyDC mdc,char* name,double x,double y,double w,double h);
//显示图象
/*基本绘图函数*/
void _Line(MyDC mdc,double x1,double y1, double x2,double y2);
void _LineTo(MyDC mdc,double x,double y);
void _MoveTo(MyDC mdc,double x,double y); //移动到
void _Arc(MyDC mdc,double r,double ang1, double ang2);
void _Circle(MyDC mdc,double rad);
void _CircleFill(MyDC mdc,long rad);???
void _PolyLine(MyDC mdc,D_DOT *lxy,long *ne, int na); //画折线
void _PolyGon(MyDC mdc,D_DOT *lxy,long *ne,int na);? //画填充多边形
void _Rect(MyDC mdc,double x1,double y1, double x2,double y2);
MAPGIS库函数:
/*取符号数*/
short _GetPatternNum(void); //取图案数
short _GetLineStyleNum(void); // 取线型数
(原文地址:http://www.3sfield.com/content.php?id=482)