爱气象,爱气象家园! 

气象家园

 找回密码
 立即注册

QQ登录

只需一步,快速开始

新浪微博登陆

只需一步, 快速开始

搜索
查看: 17995|回复: 28

用MeteoInfoC.dll类库进行软件开发

[复制链接]

新浪微博达人勋

发表于 2011-9-6 19:38:17 | 显示全部楼层 |阅读模式

登录后查看更多精彩内容~

您需要 登录 才可以下载或查看,没有帐号?立即注册 新浪微博登陆

x
        meteoinfo版主曾经在怀化论坛写过一篇关于使用MeteoinfoC.dll进行二次开发的详细过程,并发布Demo,由于怀化论坛改版原文图片丢失,幸好当时我在硬盘有保存那个帖子,故此处帮meteoinfo版主重新发布,文章版权仍归meteoinfo版主所有,本人仅是代为整理和发布。
      《用MeteoInfoC.dll类库进行软件开发》原帖地址:
http://bbs.121323.com/read.php?tid-52541.html


内容基本保持原来帖子的面貌,以下为正文:
        由于MeteoInfoC.dll类库已经基本成形,在它的基础上开发的MeteoInfo功能也还算可以,所以利用这个帖子讲讲用MeteoInfoC.dll进行软件开发。

        我会用一个C#的Demo程序进行讲解。开发环境:Microsoft Visual C# 2008 Express Edition (这是免费版本,可以在微软官方网站上下载)。需要的类库:MeteoInfoC.dll 和wContour.dll (如果想显示NetCDF格式数据还需要NetCDF4.dll)。

       MeteoInfoC.dll是我用C#开发的气象数据显示分析类库,还具备一些简单的GIS功能。wContour.dll是我开发的等值线相关算法类库。两个类库结合使用可以方便的开发出功能比较强的气象软件(当然也可以开发其他相关软件)。下载见这里哦:http://bbs.06climate.com/forum.php?mod=viewthread&tid=989&fromuid=214


首先创建一个新的Project。
1.bmp

在References中引用MeteoInfoC.dll和wContour.dll类库。
2.bmp

在ToolBox中点击鼠标右键,点击Choose Items...菜单,在Choose ToolBox Items对话框中点中.Net Framwork  Components选项,点击Browse...按钮并打开MeteoInfoC.dll文件,然后选中LayersLegend和MapView两个控件,点击OK。
3.bmp

在ToolBox栏中会出现选中的两个控件。
4.bmp
这部分主要介绍如何引用MeteoInfoC.dll类库及加载LayersLegend和MapView两个控件到ToolBox栏中。其实不用加载也可以在代码中直接使用这些控件。


在Form1中添加ToolStrip、StatusStrip和SplitContainer.
5.bmp

在splitContainer1的Panel1中添加LayersLegend控件,在Panel2中添加MapView控件,并将两个控件的Dock属性设置为Fill。将layersLegend1控件的MapView属性设置为mapView1(非常重要)。
6.bmp

在toolStrip1中添加一个按钮,命名为TSB_OpenFile。
7.bmp


在Form1的代码区添加MeteoInfoC的相关命名空间。
8.bmp

在TSB_OpenFile控件的Click事件中添加如下代码,实现打开shape文件和各种格式image文件的功能。
9.bmp

好,现在运行一下程序,打开country1.shp文件。图层名显示在layersLegend1控件中,地图数据显示在mapView1控件中。
   10.bmp


用鼠标双击图层名,出现图层属性对话框,然后你可以修改图层的LegendScheme。
11.bmp

在试试打开一个图像文件GLOBALeb3colshade.jpg
   12.bmp
OK,就这么简单。今天先到这里,改天再讲图形的放大、缩小、移动功能实现。




这一讲是关于图形缩放和移动的。
在toolStrip1控件中添加下图中的几个按钮(图标文件自己在网上找吧)。分别命名为TSB_None, TSB_ZoomIn, TSB_ZoomOut, TSB_FullExtent, TSB_ZoomToLayer。
13.bmp

在TSB_ZoomIn的Click事件中写入如下代码:
14.bmp
TSB_None, TSB_ZoomOut 和TSB_Pan的Click事件代码和上面的基本一样,只需要修改最后一行代码。当作大家的作业了。


在TSB_FullExtent和TSB_ZoomToLayer的Click事件中添加如下代码:
  1.     private void TSB_FullExent_Click(object sender, EventArgs e)
  2.         {
  3.             this.mapView1.ZoomToExtent(this.mapView1.ExtentV);
  4.         }

  5.         private void TSB_ZoomToLayer_Click(object sender, EventArgs e)
  6.         {
  7.             object aLayer = this.mapView1.GetLayerFromHandle(this.layersLegend1.SelectedLayer);
  8.             if (aLayer == null)
  9.                 return;

  10.             Extent aExtent = new Extent();
  11.             if (aLayer.GetType() == typeof(VectorLayer))
  12.             {
  13.                 VectorLayer sLayer = (VectorLayer)aLayer;
  14.                 aExtent = sLayer.Extent;
  15.             }
  16.             else
  17.             {
  18.                 ImageLayer iLayer = (ImageLayer)aLayer;
  19.                 aExtent = iLayer.Extent;
  20.             }

  21.             this.mapView1.ZoomToExtent(aExtent);
  22.         }
复制代码
好了,你已经拥有一个不错的地理底图功能了。我也该休息一下了。
15.bmp



在状态栏显示鼠标所在位置的经纬度。
在状态栏statusStrip1中添加一个StatusLabel控件,命名为TSSL_Coord。
在代码区添加一个MapView的MouseMove事件函数:
  1.     private void MapView_MouseMove(object sender, MouseEventArgs e)
  2.         {
  3.             double ProjX, ProjY;
  4.             ProjX = 0;
  5.             ProjY = 0;
  6.             this.mapView1.MapExtentSetV.ScreenToProj(ref ProjX, ref ProjY, e.X, e.Y, this.mapView1.MapExtentSetV);
  7.             this.TSSL_Coord.Text = "Lon: " + ProjX.ToString("0.00") + "; Lat: " + ProjY.ToString("0.00");         
  8.         }
复制代码
在frmMain(我将Form1改名为了frmMain)的Load事件中添加mapView1的MouseMove事件:
  1.     private void frmMain_Load(object sender, EventArgs e)
  2.         {
  3.             this.mapView1.MouseMove += new MouseEventHandler(this.MapView_MouseMove);
  4.          }
复制代码
再运行程序会看见鼠标所在位置的经纬度显示在状态栏中。
16.bmp



查询图元属性:
在工具栏toolStrip1中添加一个ToolButton,命名为TSB_Identifer。在TSB_Identifer的Click事件中输入下面的代码:
  1.     private void TSB_Identifer_Click(object sender, EventArgs e)
  2.         {
  3.             for (int j = 0; j < toolStrip1.Items.Count; j++)
  4.             {
  5.                 if (toolStrip1.Items[j].GetType() == typeof(ToolStripButton))
  6.                 {
  7.                     ToolStripButton aTSB = (ToolStripButton)toolStrip1.Items[j];
  8.                     if (aTSB.Checked)
  9.                         aTSB.Checked = false;
  10.                 }
  11.             }
  12.             ToolStripButton currentTool = (ToolStripButton)sender;
  13.             currentTool.Checked = true;

  14.             this.mapView1.Cursor = Cursors.Cross;
  15.         }
复制代码
添加一个MapView的MouseDown事件函数:
  1.         private void MapView_MouseDown(object sender, MouseEventArgs e)
  2.         {
  3.             if (TSB_Identifer.Checked && e.Button == MouseButtons.Left)
  4.             {
  5.                 double ProjX, ProjY;
  6.                 ProjX = 0;
  7.                 ProjY = 0;
  8.                 Single sX, sY;
  9.                 sX = e.X;
  10.                 sY = e.Y;
  11.                 this.mapView1.MapExtentSetV.ScreenToProj(ref ProjX, ref ProjY, e.X, e.Y, this.mapView1.MapExtentSetV);
  12.                 object aLayerObj = this.mapView1.GetLayerFromHandle(this.layersLegend1.SelectedLayer);
  13.                 if (aLayerObj.GetType() != typeof(VectorLayer))
  14.                     return;

  15.                 VectorLayer aLayer = (VectorLayer)aLayerObj;
  16.                 if (this.mapView1.Projection.IsLonLatMap)
  17.                 {
  18.                     if (ProjX < aLayer.Extent.minX)
  19.                     {
  20.                         if (aLayer.Extent.minX > -360 && aLayer.Extent.maxX > 0)
  21.                         {                           
  22.                             this.mapView1.MapExtentSetV.ProjToScreen(ProjX, ProjY, ref sX, ref sY, 360, this.mapView1.MapExtentSetV);
  23.                         }
  24.                     }
  25.                     if (ProjX > aLayer.Extent.maxX)
  26.                     {
  27.                         if (aLayer.Extent.maxX < 360 && aLayer.Extent.minX < 0)
  28.                         {                           
  29.                             this.mapView1.MapExtentSetV.ProjToScreen(ProjX, ProjY, ref sX, ref sY, -360, this.mapView1.MapExtentSetV);
  30.                         }
  31.                     }
  32.                 }

  33.                 int Buffer = 5;
  34.                 Extent aExtent = new Extent();
  35.                 this.mapView1.MapExtentSetV.ScreenToProj(ref ProjX, ref ProjY, sX - Buffer, sY + Buffer, this.mapView1.MapExtentSetV);
  36.                 aExtent.minX = ProjX;
  37.                 aExtent.minY = ProjY;
  38.                 this.mapView1.MapExtentSetV.ScreenToProj(ref ProjX, ref ProjY, sX + Buffer, sY - Buffer, this.mapView1.MapExtentSetV);
  39.                 aExtent.maxX = ProjX;
  40.                 aExtent.maxY = ProjY;

  41.                 List<int> SelectedShapes = new List<int>();
  42.                 if (aLayer.SelectShapes(aExtent, ref SelectedShapes))
  43.                 {                                       
  44.                     string fieldStr, valueStr;
  45.                     int shapeIdx = SelectedShapes[0];

  46.                     string cellStr = "";

  47.                     if (aLayer.ShapeNum > 0)
  48.                     {
  49.                         for (int i = 0; i < aLayer.NumFields; i++)
  50.                         {
  51.                             fieldStr = aLayer.GetFieldName(i);
  52.                             valueStr = aLayer.GetCellValue(i, shapeIdx).ToString();
  53.                             cellStr = cellStr + Environment.NewLine + fieldStr + ": " + valueStr;
  54.                         }
  55.                     }

  56.                     MessageBox.Show(cellStr, "Identifer");
  57.                 }
  58.             }
  59.         }
复制代码
在frmMain的Loaded事件中添加mapView1的MouseDown事件:
  1.         private void frmMain_Load(object sender, EventArgs e)
  2.         {
  3.             this.mapView1.MouseMove += new MouseEventHandler(this.MapView_MouseMove);
  4.             this.mapView1.MouseDown += new MouseEventHandler(this.MapView_MouseDown);
  5.         }
复制代码
运行效果如下:
17.bmp



根据属性字段值进行标注:
在toolStrip1中添加一个ToolButton,命名为TSB_Label,在其Click事件中添加下面的代码:
  1.         private void TSB_Label_Click(object sender, EventArgs e)
  2.         {
  3.             //Get selected layer
  4.             object aLayerObj = this.mapView1.GetLayerFromHandle(this.layersLegend1.SelectedLayer);
  5.             if (aLayerObj.GetType() != typeof(VectorLayer))
  6.                 return;

  7.             VectorLayer aLayer = (VectorLayer)aLayerObj;

  8.             //Set label
  9.             List<string> fieldNameList = aLayer.GetFieldNameList();
  10.             string fieldName;
  11.             if (aLayer.LayerName == "country1.shp")
  12.                 fieldName = fieldNameList[3];    //This is special for 'country1.shp'.
  13.             else
  14.                 fieldName = fieldNameList[0];

  15.             aLayer.LabelSetV.FieldName = fieldName;
  16.             aLayer.LabelSetV.AvoidCollision = true;
  17.             aLayer.LabelSetV.LabelAlignType = MeteoInfoC.Label.AlignType.Center;
  18.             aLayer.LabelSetV.Offset = 0;
  19.             aLayer.LabelSetV.LabelFont = new Font("Arial", 8);
  20.             aLayer.LabelSetV.LabelColor = Color.Red;
  21.             aLayer.LabelSetV.DrawShadow = false;
  22.             aLayer.LabelSetV.ShadowColor = Color.White;
  23.             aLayer.LabelSetV.DrawLabels = true;
  24.             aLayer.LabelSetV.ColorByLegend = false;

  25.             //Add labels
  26.             aLayer.AddLabels();
  27.             this.mapView1.PaintLayers();
  28.         }
复制代码
运行效果如下:
18.bmp



前面讲的和气象不沾边,今天讲讲咱气象人关系的东西:用MICAPS1格式数据做站点填图。
在程序主界面上添加一个菜单栏,然后添加如下菜单项:
20.bmp

在代码区添加气象数据命名空间的引用:
using MeteoInfoC.Data.MeteoData;
在'StationModel'子菜单的Click事件中添加如下代码:
  1.         private void TSMI_MICAPS1_StationModel_Click(object sender, EventArgs e)
  2.         {
  3.             MICAPSData aMData = new MICAPSData();
  4.             MICAPS1DataInfo aDataInfo = new MICAPS1DataInfo();
  5.             string aFile = Application.StartupPath + @"\Sample\09031417.000";
  6.             aDataInfo = aMData.ReadMicaps1(aFile);

  7.             LegendManage CLegendManage = new LegendManage();
  8.             LegendScheme aLS = CLegendManage.CreateSingleSymbolLegendScheme(ShapeType.Point, Color.Blue, 12);            

  9.             double[,] stationModelData = new double[10, 1];
  10.             Extent aExtent = new Extent();
  11.             stationModelData = aMData.GetStationModelData_M1(aDataInfo, ref aExtent);

  12.             DrawMeteoData CDrawMeteoData = new DrawMeteoData();
  13.             VectorLayer aLayer = new VectorLayer(ShapeType.Point);
  14.             aLayer = CDrawMeteoData.CreateStationModelLayer(stationModelData,
  15.                     aDataInfo.UNDEF, aLS, "MICAPS1");
  16.             aLayer.IsMaskout = true;
  17.             this.layersLegend1.AddLayer(aLayer, true, true);
  18.         }
复制代码
这就OK了。运行效果如下:
21.bmp



今天讲讲打开和保存项目文件。
业务软件通常需要在打开的时候加载一些相关的图层和设置,这个可以在frmMain的Load事件中一个个图层添加,并设置每个图层的Legendscheme等,很不灵活。项目文件可以将复杂的软件设置、图层管理等信息放在一个文件里,提供了极大的便利和灵活性。通常xml格式的文件很适合用作项目文件。MeteoInfoC.dll中MapView、LayersLegend、MapLayout等类中提供了以xml格式输出和读入相关设置的功能,可以方便的用于形成软件的项目文件。

在Demo程序中添加一个类ProjectFile,添加一个FileName变量和SaveProject、LoadProject方法。
  1.         public void SaveProjFile(string aFile)
  2.         {
  3.             m_FileName = aFile;

  4.             XmlDocument doc = new XmlDocument();
  5.             doc.LoadXml("<MeteoInfo name='" + Path.GetFileNameWithoutExtension(aFile) + "' type='projectfile'></MeteoInfo>");
  6.             XmlElement root = doc.DocumentElement;            

  7.             //Add MapView content
  8.             frmMain.G_LayerLegend.MapView.ExportProjectXML(ref doc, root, m_FileName);               

  9.             //Save project file            
  10.             doc.Save(aFile);
  11.         }   

  12.         public void LoadProjFile(string aFile)
  13.         {
  14.             m_FileName = aFile;

  15.             XmlDocument doc = new XmlDocument();
  16.             doc.Load(aFile);
  17.             XmlElement root = doc.DocumentElement;

  18.             //Load elements
  19.             frmMain.G_LayerLegend.MapView.LockViewUpdate = true;
  20.                
  21.             //Load MapView content
  22.             frmMain.G_LayerLegend.ImportProjectXML(root);
  23.                   
  24.             frmMain.G_LayerLegend.MapView.LockViewUpdate = false;
  25.             frmMain.G_LayerLegend.MapView.PaintLayers();            
  26.         }   
复制代码
在frmMain窗体中添加Project菜单和Open, Save, Save As子菜单。
  1.         private void TSMI_OpenProject_Click(object sender, EventArgs e)
  2.         {
  3.             OpenFileDialog aDlg = new OpenFileDialog();
  4.             aDlg.Filter = "MeteoInfo Project File (*.mip)|*.mip";
  5.             if (aDlg.ShowDialog() == DialogResult.OK)
  6.             {
  7.                 string aFile = aDlg.FileName;

  8.                 if (G_LayerLegend.MapView.Layers.Layers.Count > 0)
  9.                 {
  10.                     G_LayerLegend.RemoveAllLayers();
  11.                 }
  12.                 Application.DoEvents();
  13.                 m_ProjectFile.LoadProjFile(aFile);
  14.                 this.Text = "MeteoInfoC Demo - " + Path.GetFileNameWithoutExtension(aFile);
  15.                 G_LayerLegend.MapView.ZoomToExtent(G_LayerLegend.MapView.ViewExtent);
  16.             }
  17.         }

  18.         private void TSMI_SaveProjetFile_Click(object sender, EventArgs e)
  19.         {
  20.             if (File.Exists(m_ProjectFile.FileName))
  21.                 m_ProjectFile.SaveProjFile(m_ProjectFile.FileName);
  22.             else
  23.             {
  24.                 SaveFileDialog aDlg = new SaveFileDialog();
  25.                 aDlg.Filter = "MeteoInfo Project File (*.mip)|*.mip";
  26.                 if (aDlg.ShowDialog() == DialogResult.OK)
  27.                 {
  28.                     string aFile = aDlg.FileName;

  29.                     m_ProjectFile.SaveProjFile(aFile);
  30.                     this.Text = "MeteoInfoC Demo - " + Path.GetFileNameWithoutExtension(aFile);
  31.                 }
  32.             }
  33.         }

  34.         private void TSMI_SaveAsProject_Click(object sender, EventArgs e)
  35.         {
  36.             SaveFileDialog aDlg = new SaveFileDialog();
  37.             aDlg.Filter = "MeteoInfo Project File (*.mip)|*.mip";
  38.             if (aDlg.ShowDialog() == DialogResult.OK)
  39.             {
  40.                 string aFile = aDlg.FileName;

  41.                 m_ProjectFile.SaveProjFile(aFile);
  42.                 this.Text = "MeteoInfoC Demo - " + Path.GetFileNameWithoutExtension(aFile);
  43.             }
  44.         }
复制代码
如果想做软件打开时加载缺省项目文件如Default.mip,可以在frmMain的Load事件中添加相关代码。
  1.            //Open default project file            
  2.             string aFile = Application.StartupPath + "\\Default.mip";            
  3.             if (File.Exists(aFile))
  4.             {
  5.                 m_ProjectFile.LoadProjFile(aFile);
  6.                 this.Text = "MeteoInfoC Demo - " + Path.GetFileNameWithoutExtension(aFile);
  7.             }
复制代码
其中m_ProjectFile是一个ProjectFile类的对象,在frmMain的变量声明中定义:
private ProjectFile m_ProjectFile = new ProjectFile();

结束。内容我都从原来的帖子复制过来了。就这些啦。希望对大家有用吧。

评分

参与人数 4金钱 +31 贡献 +11 收起 理由
huangfucheng + 1 很给力!
MeteoInfo + 10 + 4 辛勤劳动
athlon8048 + 10 + 2 很给力!
mofangbao + 10 + 5 顶顶 加油

查看全部评分

密码修改失败请联系微信:mofangbao

新浪微博达人勋

 楼主| 发表于 2011-9-6 19:51:24 | 显示全部楼层
帖子先写到这里吧。。。网速太慢,发个帖子可痛苦了。。。
后续我再编辑下里面的内容。。。
密码修改失败请联系微信:mofangbao

新浪微博达人勋

0
早起挑战累计收入
发表于 2011-9-6 20:05:44 | 显示全部楼层
呵呵 中间顶你一下 难得  射月楼主的帖子个个都很厉害
密码修改失败请联系微信:mofangbao

新浪微博达人勋

发表于 2011-9-6 21:28:14 | 显示全部楼层
本帖最后由 MeteoInfo 于 2011-9-6 21:28 编辑

赞一个先!怀化论坛的这个帖子因为论坛改版的缘故已经把图都丢了,难得孤蓝还有保存,帮了我一个大忙,也希望对大家有用。
密码修改失败请联系微信:mofangbao

新浪微博达人勋

发表于 2011-9-7 10:23:40 | 显示全部楼层
孤篮就是麝月吗?好给力,顶一个先!多多活动啊,这个贴发的辛苦啦!感谢分享
密码修改失败请联系微信:mofangbao

新浪微博达人勋

发表于 2011-9-7 10:29:35 | 显示全部楼层

这个得澄清一下。MeteoInfo(也就是本人了)才是射月楼主。一楼孤蓝发的内容是我在怀化气象论坛的一个帖子里的部分内容。怀化上的帖子图都被弄掉了,我也懒得再重新弄了,幸好孤蓝保存了那个帖子,所以帮忙整理出来了,感谢孤蓝的辛勤劳动!
密码修改失败请联系微信:mofangbao

新浪微博达人勋

发表于 2011-9-7 10:32:46 | 显示全部楼层
MeteoInfo 发表于 2011-9-7 10:29
这个得澄清一下。MeteoInfo(也就是本人了)才是射月楼主。一楼孤蓝发的内容是我在怀化气象论坛的一个帖子 ...

哦,犯错误了,麝月见谅啊!
密码修改失败请联系微信:mofangbao

新浪微博达人勋

0
早起挑战累计收入
发表于 2011-9-7 10:49:04 | 显示全部楼层
zsmnantong 发表于 2011-9-7 10:23
孤篮就是麝月吗?好给力,顶一个先!多多活动啊,这个贴发的辛苦啦!感谢分享

快赶上深深那个评分的帖子啦 哈哈

点评

还没找你呢,我的小红旗怎么没了  发表于 2011-9-7 10:59
密码修改失败请联系微信:mofangbao

新浪微博达人勋

0
早起挑战累计收入
发表于 2011-9-7 11:04:00 | 显示全部楼层
mofangbao 发表于 2011-9-7 10:49
快赶上深深那个评分的帖子啦 哈哈

可能是连续得缘故 我设置了有效期为一周 看来得我手动改了
密码修改失败请联系微信:mofangbao

新浪微博达人勋

 楼主| 发表于 2011-9-7 13:05:39 | 显示全部楼层
zsmnantong 发表于 2011-9-7 10:23
孤篮就是麝月吗?好给力,顶一个先!多多活动啊,这个贴发的辛苦啦!感谢分享

我不是射月,我不是射月。
看来我要在内容中强调下。要不有错觉。嗯
密码修改失败请联系微信:mofangbao
您需要登录后才可以回帖 登录 | 立即注册 新浪微博登陆

本版积分规则

Copyright ©2011-2014 bbs.06climate.com All Rights Reserved.  Powered by Discuz! (京ICP-10201084)

本站信息均由会员发表,不代表气象家园立场,禁止在本站发表与国家法律相抵触言论

快速回复 返回顶部 返回列表