阅读:1600回复:0
MAPGIS二次开发问题集锦(VC)
<b>
</b>VC部分 <P>1> Q: 1)当连续打开较大文件时出错,提示为:TEMP目录下暂存盘已满,后发现该目录下暂时文件大概2-3百兆不知道</P> <P>问题出在那里。 2)数据压缩存盘,文件大小并没有减小多少,有没有别的办法减小文件大小? A: 1)如果打开大文件时提示“TEMP目录下暂存盘已满”,可能的确是临时空间不够,因为每打开一个文件要相应的</P> <P>产生临时文件,并且和源文件的大小有关系。您可以试着把temp目录改到有更大空间的盘符上。 2)数据的压缩存盘是指把文件中已做了删除标记的实体/记录内容真正清除掉,并不是指把所有的数据</P> <P>按照某种算法压缩以减少容量。所有只有对文件做过大量的编辑/删除操作时,压缩存盘的效果才会比较明显。</P> <P>2> Q: 6.1版本中,装入一个文件对话框中有一个选项:网络数据。请问,网络数据中的wt、wl和wp文件指的是什么数据</P> <P>,它们和单机数据有什么异同? A: 网络数据的wt、wl和wp分别指网络数据库中的线文件、区文件、点文件数据;它们和单机数据的差异在于单机数</P> <P>据是以*.wt、*.wl、*.wp的文件形式组织数据;而网络数据则是在数据库装载这些点、线、面数据。</P> <P>3> Q: 请问在VC6.0中进行MAPGIS6.1二次开发环境如何设置? A: 1、vc的环境配置: 假设您的开发动态库在目录c:\mapgis61\program下;lib库在:c:\mapgis1\lib下;头文件在</P> <P>:c:\mapgis61\include下。 假设您开发的工程应用程序为:MyTry.exe 对应vc的设置为: vc菜单[project]->[project setting]->[general]->[output files]: c:\mapgis61\program vc菜单[project]->[project setting]->[link]->[output file name]: c:\mapgis61\program\mytry.exe vc菜单[tools]->[options]->[directories]->{include files}: c:\mapgis61\include vc菜单[tools]->[options]->[directories]->{library files}: c:\mapgis1\lib 2、再将mapgis的系统环境(工作目录、系统库目录、临时目录)配置好。</P> <P>4> Q: 如何将MAPGIS文件中的图层信息读出? A: 图层操作在头文件"win_area.h": /*取当前层号 参数:入口 ai - 工作区号 出口 *curlay -当前层号 返回: 成功1,失败则返回0 */ short WINAPI _GetCurLayer(short ai,short *curLay); //取当前层名 /*layName 必须至少有LAYER_NAME_LEN个字节*/ short WINAPI _GetCurLayerName(short ai,char *layName); /*判断某一层是否有图元*/ short WINAPI _IsALayHasElement(short ai,short layer);</P> <P>5> Q: 调用_LoadAFile("c:\\mapgis60\\sample\\testlayer206\\line.wl",li)这个函数,出现异常,这是什么原因? A: _LoadAFile("c:\\mapgis60\\sample\\testlayer206\\line.wl",li)异常是因为不能直接将字符串常量作为参数</P> <P>传入(VC6 版本原因),修改方法: char fileName[MAX_PATH]; lstrcpy(fileName,"c:\\mapgis60\\sample\\testlayer206\\line.wl"); _LoadAFile(fileName,li);</P> <P>6> Q: 如何使用函数_GetAreaFileName1(short ai,char *fname,short len);参数fname和len怎么设置? A: _GetAreaFileName1的功能是取工作区文件名(不包括路径)其中: fname - 文件名字符串地址; len - fname长度; 成功返回1,失败返回0。 如: char fname[MAX_PATH]; short len; fname[0] = 0; _GetAreaFileName1(ai,fname,MAX_PATH*sizeof(char));</P> <P>7> Q: 功能类似于_SelectAreaList()函数,但每次只能选择单个文件,MAPGIS中有这样的现成函数吗? A: 每次只选择单个文件的函数名为_SelectArea();</P> <P>8> Q: 怎样获得图幅范围? A: 获得图幅范围的函数为:short WINAPI _GetRange(short ai,D_RECT *rect);</P> <P>9> Q: 怎样使用函数_DelStruFldOnNumb(short ai,short aType,short fldi),执行完后,本该删除掉的字段还保留在</P> <P>属性结构中,为什么? A: 您是否是用循环来操作此函数,如果是的需要从属性结构的尾部进行删除。打个很简单的例子:如果有四个属性</P> <P>结构,删除了第二个属性结构后,则原来第四个属性结构变成了第三个属性结构。所以 for(i=0;i<Num;i++) { _DelStruFldOnNumb(i); }和 for(i=Num-1;i>=0;i--) { _DelStruFldOnNumb(i); }是不相同的。</P> <P>10> Q: 我想在一个条件查询对话框中打开数据库,找出满足条件的记录号,在调用程序中对这些记录进行处理,为了简</P> <P>化,写了以下一个小程序不知为什么,无法得到相应的记录号,请指正。 void get(int* ii) { int* nn; nn=new int[5]; for(int m=0;m<5;m++) nn[m]=m; ii=nn; }</P> <P>void test() { int* p; test(p); CString s;</P> <P>s.Format("p=%d",p[0],p[1],p[2],p[3],p[4]); AfxMessageBox(s); } A: 主要是指针的原因,您可以参考c语言教程。 void get(int** ii) { int *nn; nn=new int[5]; for(int m=0;m<5;m++) nn[m]=m; *ii=nn;//!! }</P> <P>void test() { int* p; get(;p);//送指针的地址 CString s;</P> <P>s.Format("p=%d,%d,%d,%d,%d",p[0],p[1],p[2],p[3],p[4]); AfxMessageBox(s); delete[]p; }</P> <P>11> Q: 距离计算函数_CalculateLength(D_DOT *xy,long len),如何使用? A: 参数说明: D_DOT *xy--点坐标序列 long -len --点序列的数目 例: D_DOT *xy; xy = new D_DOT[5]; xy[0].x = 10;xy[0].y = 19; xy[1].x = 20;xy[1].y = 29; xy[2].x = 30;xy[2].y = 39; xy[3].x = 40;xy[3].y = 49; xy[4].x = 50;xy[4].y = 59; _CalculateLength(xy,5); delete[]xy;</P> <P>12> Q: 在利用函数_LoadFile(short ai)向一个工作区添加文件时,如果在工作区实例中已经打开了这个文件,就会出现</P> <P>"文件不能重复装入"的错误提示,请问我该如何判断用户是否又打开已经打开的文件? A: short WINAPI _IsOpenArea(short ai);是判断工作区是否打开(1-打开,0-没打开)。</P> <P>13> Q: 在mapgis6.1版本中,输出成EPS文件,为何出现aihead.ps文件打不开的错误提示,而文件中的确有此文件,请问</P> <P>这是为什么? A: 6.1版中应该使用aihead.eps文件。</P> <P>14> Q: 按常规,在CWinApp::InitInstance() 中调用 ::GetCurrentDirectory函数可以取得程序启动时的目录,但是,</P> <P>当引用MAPGIS的CGisView后,MAPGIS内核提前把当前目录改成了MAPGIS系统环境目录中的工作目录。当您不使用</P> <P>MAPGIS的类,把CMyView:CGisView 改成CMyView:CView之后,编译重运行,立即可以获得正确的程序启动目录。</P> <P>因此,在InitInstance()中不能再使用::GetCurrentDirectory() API 函数取当前目录了。请问,如何在MAPGIS</P> <P>内核之前,获得自已程序启动时所在目录? A: 使用以下代码即可得到程序启动时所在目录: char szBuff[_MAX_PATH]; VERIFY(::GetModuleFileName(m_hInstance, szBuff, _MAX_PATH)); long len = lstrlen(szBuff); char ch = szBuff[len-1]; do { len--; ch = szBuff[len-1]; } while(ch!='\\'); szBuff[len-1]='\0';</P> <P>15> Q: 怎样从当前打开的文件中提取出只属于该文件的图层名称或序号? A: 可通过函数实现: for(short i=0;i<MAX_LAYNUM;i++) {/*判断某一层是否有图元*/ short HaveElement = _IsALayHasElement(ai,i); if(HaveElement) TRACE( "area is %d at layer = %d has element\n", ai, i ); else TRACE( "area is %d at layer = %d has not element\n", ai, i ); }</P> <P>16> Q: _TurnLayerSwitch(),_TurnOnOffAllLayer(),自己进行调用后,例如将层开关设为Off后,仍然显示。另外,有</P> <P>关取图层信息板和图层开关板函数如何使用? A: 请尝试调用下面的函数: void CloseAllLay()//关闭所有图层 { _TurnOnOffAllLayer(GetCurrentLinArea(),0); _TurnOnOffAllLayer(GetCurrentPntArea(),0); _TurnOnOffAllLayer(GetCurrentRegArea(),0); }</P> <P>17> Q: 能够通过区域的边界点的地理坐标求得区域得实际面积吗 </P> <P>我有一个区域,比如坐标分别为(111.75,29.66),(111.43,28.97),(111.73,28.80),(112.05,</P> <P>29.49)由这些点构成的四边形区域,能否直接键盘输入为区实体,并设置为什么坐标系类型和地图参数,才能使</P> <P>属性字段中的面积代表区的实际面积,单位都设置成什么?请详细说明,谢谢</P> <P>A: 设置为高斯投影,大地坐标方式,则表示你的坐标单位为米,面积的结果也就为平方米。 在projDll中有函数double WINAPI _CountPolygonArea(D_DOT *xyLst,int len,MAP_PARA *map); 可以根据形成多边形的点集以及相应的地图参数计算出实际面积。</P> <P>18> Q: 我有两个线工作区,一个装了一条直线,另一个装了一系列等值线,我希望得到直线与等值线相交的一系列点,</P> <P>求教实现方法! 谢谢!</P> <P>A: 可以用函数: short _CalCrossDot(D_DOT *la0,D_DOT *la1,D_DOT *lb0,D_DOT *lb1,D_DOT *xy)</P> <P> 参数:入口 *la0 - 线段的起点坐标</P> <P> *la1 - 线段的终点坐标</P> <P> *lb0 - 另一线段的起点坐标</P> <P> *lb1 - 另一线段的终点坐标</P> <P> 出口 *xy - 两直线的交点坐标</P> <P> 返回值 1/0 - 成功/失败 用一个双循环,对每一条等值线调用_GetLin得到线的空间数据,其中会返回一个点集,点集中每两个相邻的点</P> <P>形成一条直线,对这每一条直线和直线工作区中的直线调用上述的函数_CalCrossDot即可得到交点坐标。</P> <P>19> Q: 我在程序中进行多次区点相交显示,一切工作正常,然而,我在第二次在进行操作, 要把区点相交的结果显示出来时,出现点的图元,不知道如何解决:</P> <P>A: 以下是我的代码: short op; if (ai_reg1==0) ai_reg1 = _OpenRegArea(ahInst); if (ai_pnt1==0) ai_pnt1 = _OpenPntArea(ahInst);</P> <P> ai_reg2res = _OpenRegArea(ahInst); //2.装叠加文件1和叠加文件2 if (_IsAreaEmpty(ai_reg1)) if(_LoadFile(ai_reg1)<=0) goto END ; if (_IsAreaEmpty(ai_pnt1)) if(_LoadFile(ai_pnt1)<=0) goto END ; </P> <P> //3.叠加分析 //op: 叠加操作符 op = OVLY_INTER; //OVLY_INTER,OVLY_SUB,OVLY_IDENT if(Anly(ai_reg1,ai_pnt1,ai_reg2res,op)<=0) goto END;</P> <P> if(_AppendArea(ai_reg2res) <= 0) { AfxMessageBox("相交完的区文件单元数太少"); // _SaveAFile(ai_reg1,chtemp); _CloseArea(ai_reg1); // DeleteFile(chtemp); _CloseArea(ai_pnt1); _CloseArea(ai_reg2res); // return false; return; } _UpdateWindow(); return; END: //5.关闭所有数据工作区 _SetChangeFlag(ai_reg1,0); _CloseArea(ai_reg1); _SetChangeFlag(ai_pnt1,0); _CloseArea(ai_pnt1); //_SetChangeFlag(ai3,0); _CloseArea(ai_reg2res); </P> <P>short WINAPI Anly(short ai1,short ai2,short ai3,short op) {//空间分析 short Flag=0;</P> <P> switch(_AType(ai1)) { case REG: if(_AType(ai2)==REG) Flag = _PolygonCover(ai1, ai2, ai3,0.5, op); //_OverlayRegReg(ai1, ai2, ai3, op); else if(_AType(ai2)==PNT) Flag = _OverlayRegPnt(ai1, ai2, ai3, op); else return 0; break; case LIN: if(_AType(ai2)==REG) Flag = _OverlayLinReg(ai1, ai2, ai3, op); else return 0; break; case PNT: if(_AType(ai2)==REG) Flag = _OverlayPntReg(ai1, ai2, ai3, op); else if(_AType(ai2)==LIN) Flag = _OverlayPntLin(ai1, ai2, ai3, op); else return 0; break; default: return 0; } </P> <P> return Flag; }</P> <P> 20> Q: 我要应用MyDC的方法往工作区内添加一个椭圆,简单的或者是圆,我怎样把圆的圆心的坐标转换为图形坐标,即</P> <P>添加的圆有地理意义。另外,重要的是圆的半径又怎么样能和图形坐标对应,以公里或者米为单位。 最好谁能告诉我,已知地理经纬度的点,以它为圆心,以100公里为半径画一个圆,要怎么做,画一个长短轴已知</P> <P>,长轴方向已知的椭圆,又怎么实现! 急!急!急啊</P> <P>在MyDC的绘图方法中有没有绘制椭圆形填充区的API函数! 我如果要绘制一个椭圆该怎么做呢?</P> <P>跳转显示区一般要将窗口跳转到什么位置呀,怎么做呀? void CZBySHASView::OnJumpReg() //跳转显示区 { // TOD Add your command handler code here CZByJumpDispDlg dlg; REG_INFO reginfo; long * rdat; //D_DOT * ldat; long len; short Ai=GetEditArea(REG); if(!Ai) { MessageBox("当前没有线文件"); return; } if(dlg.DoModal() != IDOK) return; //short WINAPI _GetReg(short ai,long ri,long **rdat,long *len,REG_INFO *inf); if(_GetReg(Ai, dlg.m_ID, ;rdat, ;len, ?info) <= 0) return;</P> <P>//_GotoWindowFxy(ldat[0].x, ldat[0].y);?????????????</P> <P>//闪烁指定的图元 _FlashReg(Ai, ;dlg.m_ID, 1); }</P> <P>A: 1、除了知道地理经纬度的点,还要知道,该图的比例尺,即要知道原图的地图参数,目标投影参数即平面直角</P> <P>坐标,应用投影变换的函数,将圆心的经纬度投影成大地坐标。 2、显示这个圆,和显示其他类型的线是一样的,即要知道组成这条线的点集。下面构造该圆的点集,将该圆平</P> <P>均分成若干份(如360份),即可算出这个圆上的360个点(此时这些点的坐标仍然是大地坐标),将这些点反过来</P> <P>变换成相应的经纬度再按照一定的顺序添加到点集中。 3、对于椭圆同样可使用上述方法,只是算每个点的坐标的时候用的是椭圆的解析式。 4、若要形成区图元,可将上述点集添加到区文件中成为弧段,再构造区空间数据的rdat,_AppendReg添加区即</P> <P>可。</P> <P>21> Q: 在MAPGIS里如何获得一个区的最长的边,并且怎么知道它的方位</P> <P>A: 对每一个区调用_GetReg(...,rdat,len....); double maxLength=0; double tempLength; double maxLi=0; for(i=1;i<len;i++) { if(rdat[I!=0) { _GetLin(...abs(rdat[I),dotset,linlen...) tempLength=_CalculateLength(dotset,linlen); if(tempLength>maxLeghth) { maxLeghth=tempLeghth; maxLi=abs(rdat[I); } } }</P> <P>22> Q: 请讲讲PointSelectLin()函数的用法。</P> <P>A: //通过点击选择线 int WINAPI PointSelectLin(short *psAi,int num,D_DOT* pt,double radiu,SELECTGRAPH* selLin,int </P> <P>bufnum); 通过输入捕捉点的坐标,在多个工作区中捕捉线,并返回捕捉到的线数目,在selLin中返回捕捉到的线信息。 参数依次为: 入口:工作区列表,工作区列表个数,捕捉的点的坐标,捕捉半径,存储返回捕捉到的线的缓冲区,缓冲区的长</P> <P>度。</P> <P>selLin需要在调用前自己申请空间。</P> <P>23> Q: 怎么样使弹出对话框打开的文档为*.MPJ文件,而不是所有文件格式 BOOL CZBySHASDoc::OnOpenDocument(LPCTSTR lpszPathName) //打开工程 { if (!CDocument::OnOpenDocument(lpszPathName)) return FALSE;</P> <P> m_cpPrj = _PRJLoadAProject((char *)lpszPathName); return TRUE; }</P> <P>A: 在ResourceView的StringTable中查找和Menu中对应的ID号,双击它的Caption 改为 \nmapprj\n工程文件\nMAPGIS工程文件(*.mpj) \n.mpj\nMapprj.Document\nProject Document 即可</P> <P>24> Q: _EditAtt这个函数包含联动的功能吗?我使用_EditAtt不能实现图形的联动,请问还需要使用别的函数吗?</P> <P>A: _EditAtt函数会弹出一个窗体,返回值是这个窗口的句柄。 程序实现联动就是这个窗口和图形所在的视图窗口之间互相通信的结果。 当在属性编辑窗口中编辑某个记录的字段时会像视图窗口发送消息MGM_FLASH_GRAPH,该消息的wParam参数为属性</P> <P>窗口状态,它可以是下列宏定义之一: BEGIN_EDATT: 表示开始编辑属性。 EDITING_ATT: 表示正在编辑属性。 END_EDATT : 表示结束编辑属性。</P> <P>属性窗口发送此状态时,属性窗口没有撤消。一般情况,属性窗口发送的所有MGM_FLASH_GRAPH消息中,开始时为</P> <P>BEGIN_EDATT状态,最后为END_EDATT状态,中间为若干EDITING_ATT状态。</P> <P>lParam参数为指向MGMSG结构的指针,该指针所指结构空间属于属性编辑窗口,MGMSG结构如下:</P> <P>//图元实体信息结构</P> <P>typedef struct </P> <P> {short ai; //工作区号。</P> <P> short type; //图元类型,为LIN,PNT,REG,NOD,NET,TBL之一。</P> <P> long elmi; //图元号。</P> <P> }ENTITY_MSG;</P> <P>//图元重新显示信息结构</P> <P>typedef ENTITY_MSG MGMSG;</P> <P>通过lParam参数,通知hWnd窗口当前记录对应的图元是什么。</P> <P>当联动状态为断开时,属性窗口不给hWnd窗口发送当前图元消息。</P> <P>当鼠标在视图窗口双击选中一个实体时应该像属性窗口发送GoToAtt的消息,让属性跳转到和空间实体对应的属性</P> <P>处。</P> <P>25> Q: 加载图文件时的警告提示? 我用CGisEditView类在用 if(_LoadAFile(OpenFileName,Ai)<=0) AfxMessageBox(OpenError); SetEditArea(Ai); 当在SetEditArea(Ai);时”有时“会出现“与其它文件投影参数不同,不能同时编辑”的警告提示,有时又不会</P> <P>出现,我检查过,全部的文件投影参数都是相同的。</P> <P>请教会是什么原因?</P> <P>A: 在SetEditArea(Ai)进行设置当前工作区时候,我们会和CGisEditView中其他非空的其他类型的工作区进行“地图</P> <P>参数”比较,使用的函数是 _IsSameMapPara,如果不相同则会提示上述内容;当然用_IsSameMapPara来进行比</P> <P>较,是会有它比较的规则,你注意是否“地图参数”中的各个内容是否相同.</P> <P>示例代码: short pai,lai,rai,nai; BOOL isMatch=TRUE; MAp_PARA map,map2; pai=GetEditArea(PNT); lai=GetEditArea(LIN); rai=GetEditArea(REG); nai=GetEditArea(NET);</P> <P> if(_LoadAFile(OpenFileName,Ai)<=0) AfxMessageBox(OpenError);</P> <P>_GetMapParam(Ai,;map); //分别进行判断 if(pai ;; !_IsAreaEmpty(pai)) { _GetMapParam(pai,;map2); if( _IsSameMapPara(;map,;map2) <=0) { isMatch = FALSE; } }</P> <P>if(lai ;; !_IsAreaEmpty(lai)) { _GetMapParam(lai,;map2); if( _IsSameMapPara(;map,;map2) <=0) { isMatch = FALSE; } }</P> <P>if(rai ;; !_IsAreaEmpty(rai)) { _GetMapParam(rai,;map2); if( _IsSameMapPara(;map,;map2) <=0) { isMatch = FALSE; } }</P> <P>if(nai ;; !_IsAreaEmpty(nai)) { _GetMapParam(nai,;map2); if( _IsSameMapPara(;map,;map2) <=0) { isMatch = FALSE; } }</P> <P>if (isMatch) SetEditArea(Ai);</P> <P>26> Q: 我在一个PrjEditView里在工程里插入了一个文件,想在插入后自动更新listview,应该怎么做,是不是要用消息</P> <P>A:</P> <P>void CZBySHASView::OnInputLinFile() //添加线文件 { // TOD Add your command handler code here int flag; char szName[256]; char dsn[32]; char owner[32]; char ftype; char openflag; char filter[]="MapGis线文件(*.wl)\0*.wl\0\0"; char ttlStr[]="添加线文件";</P> <P>openflag=0;</P> <P>memset(szName,0,sizeof(szName)); memset(dsn,0,sizeof(dsn)); memset(owner,0,sizeof(owner));</P> <P>flag=_InputFileName(szName, dsn, owner, ;ftype, openflag, filter, ttlStr);</P> <P>if(flag=1) { //给工程添加文件,只需要知道该文件的文件名,并不需要打开该文件(装入工作区) _PRJAppend(GetProject(),szName,NULL,-1);</P> <P> //PrjListView中显示刚添加进的文件 ((CZByPrjListView *)(((CChildFrame *)(((CFrameWnd </P> <P>*)(AfxGetMainWnd()))->GetActiveFrame()))->m_wndSplitter.GetPane( 0, 0 )))->ReloadPrjItems();</P> <P> //PrjEditView复位显示 OnRestoreWindow();</P> <P>} </P> |
|
|