最后更新时间:2019年8月16日
4.1 自定义地图视图
实现功能:打开地图文档,并显示该地图文档里的第一个地图。
效果预览如下图所示:
插件项:MenuBar(菜单栏)、Command(命令按钮)、DockWindow(停靠窗口)、MapContentsView(地图视图)。
步骤一:打开VS 2010新建一个MapGIS项目,命名为“CustomMapViewDemo”,在该MapGIS插件项目中创建一个MenuBar菜单栏,将Name属性值设为“MapOperationMB”,Caption属性值设为“进阶应用”;添加一个Command插件项(命名为“OpenDocCmd”)打开地图文档视图功能;添加一个MapContentsView插件项(命名为“MapContentsView”)用于承载地图视图控件;在VS 2010中自定义一个用户控件,命名为“UserControl1”,在控件窗体中拖入一个地图视图MapControl控件,设置其Modifiers属性为public,Dock属性为Fill;
步骤二:将OpenDocCmd命令按钮插件项添加到MapOperationMB菜单项中,具体实现代码请参考1.2小节的内容;
步骤三:将UserControl1自定义用户控件绑定到MapContentsView地图视图插件项中,具体实现步骤如下。
(1) 在MapContentsView.cs文件中定义一个自定义用户控件(UserControl1对象) userControl的全局变量;
(2) 修改MapContentsView.cs文件中的ObjecthWnd属性代码如下所示:
程序代码 4 1 修改ObjecthWnd属性代码
public Control ObjecthWnd { get { return userControl; } }
(3) 修改MapControl属性代码如下所示之后就完成了绑定功能。 程序代码 4 2 修改MapControl属性代码
public MapGIS.GISControl.MapControl MapControl { get { return userControl.mapControl1; } }
步骤四:在OpenDocCmd.cs文件中实现打开地图文档,并显示该地图文档里的第一个地图功能,具体步骤如下。
(1) 在OpenDocCmd.cs文件中定义一个应用框架(IApplication对象)hk全局变量,定 义一个地图视图控件(MapControl对象)mapCtrl全局变量,获取插件容器中的地图视图插件MapContentsView对象,然后根据地图视图插件MapContentsView对象来获取对应的MapContorl地图视图控件对象,在OnCreate方法中的关键代码如下:
程序代码 4 3 获取MapControl控件关键代码
public void OnCreate(IApplication hook) { hk = hook; //内容视图控件 IContentsView cv = null; //获取指定的内容视图控件 hk.PluginContainer.ContentsViews.TryGetValue("CustomMapViewDemo.MapContentsView", out cv); //获取地图视图插件项 IMapContentsView mapview = cv as IMapContentsView; //获取该视图的MapControl属性 mapCtrl = mapview.MapControl; }
(2) 打开地图文档,将地图文档中的第一个地图显示到MapControl中,在OnClick方法中关键代码如下:
程序代码 4 4 显示地图关键代码
public void OnClick() { Map map = null; string docName = null; if (mapCtrl == null) return; Document doc = this.hk.Document; //选择打开地图文档 OpenFileDialog ofd = new OpenFileDialog(); ofd.Multiselect = true; ofd.Filter = "(地图文档mapx)|*.mapx|(地图map)|*.map"; if (ofd.ShowDialog() == DialogResult.OK) { //获取打开的地图文档的名称 docName = ofd.FileName; } if (doc == null) return; doc.Open(docName); Maps maps = doc.GetMaps(); if (maps.Count > 0) { //获取当前第一个地图 map = maps.GetMap(0); //设置地图的第一个图层为激活状态 map.get_Layer(0).State = LayerState.Active; mapCtrl.ActiveMap = map; mapCtrl.Restore(); } }
步骤五:在MapGIS.AppLoader.exe上面加载完MapGIS.WorkSpace.Plugin.dll此库后,用户单击“打开地图文档”,打开地图文档,并显示该地图文档里的第一个地图。
4.2 交互式几何查询
实现功能:用户在默认地图窗口中拉框查询,闪烁查询结果,属性列表中显示当前被查询中的第一个激活图层中的记录属性。 效果预览如下图所示:
插件项:MenuBar(菜单栏)、Command(命令按钮)、DockWindow(停靠窗口)。
步骤一:打开VS 2010新建一个MapGIS项目,命名为“InterGeomQuery”,在该MapGIS插件项目中创建一个MenuBar菜单栏,将Name属性值设为“SetBasToolMBar”,Caption属性值设为“查询方式”;添加2个Command插件项(命名为“QueryByRectCmd”,“QueryByCirCmd”)分别实现矩形查询和圆查询的功能;添加一个DockWindow插件项(命名为“DockWindow”)用于承载属性视图控件;在VS 2010中自定义一个用户控件,命名为“AttUserControl”,在控件窗体中拖入一个属性视图AttControl控件,设置其Modifiers属性为public,Dock属性为Fill;
步骤二:将QueryByRectCmd和QueryByCirCmd两个命令按钮插件项添加到SetBasToolMBar菜单项中,具体实现代码请参考3.2小节的内容;
步骤三:将AttUserControl自定义用户控件绑定到DockWindow停靠窗口插件项中,具体实现步骤如下。
(1) 在DockWindow.cs文件中自定义一个属性视图控件(AttUserControl对象)attCtrl 全局变量;
(2) 修改ChildHWND属性字段代码如下所示,即可实现绑定功能:
程序代码 4 5 修改ChildHWND属性字段代码
public Control ChildHWND { get { return attCtrl; } }
步骤四:创建自定义类,命名为“SelectToolClass”,该类继承并重写GISBasTool 类,在SelectToolClass类定义一个选择工具控件(SelectTool对象 )selTool全局变量,注册selTool的选择事件,并在事件中完成查询功能,关键代码如下:
程序代码 4 6 SelectToolClass类中的全局变量
//地图视图控件 MapControl mapCtrl; //交互工具:选择工具控件 SelectTool selTool; //选择数据时的数据类型过滤 SelectDataType dataType; //地理类对象基类接口 IBasCls basClass = null; //结果集对象 RecordSet rcdSet = null; //属性视图控件 AttControl attCtrl = null; //查询选择方式:圆选择、多边形选择、矩形选择 SelectType selType;
程序代码 4 7 SelectToolClass类的构造函数代码
////// 实现拉框选择查询 /// /// 地图视图控件 /// 选择数据时的数据类型过滤 /// 属性视图控件 /// 查询选择方式:矩形选择 public SelectToolClass(MapControl control, SelectDataType dataType, AttControl attctr,SelectType seltype) : base() { this.mapCtrl = control; this.dataType = dataType; this.attCtrl = attctr; this.selType = seltype; //查询选择项 SelectOption selOpt = new SelectOption(); selOpt.DataType = dataType; //选择数据时的类型过滤类型 selOpt.SelMode = SelectMode.Multiply; //选择模式 selOpt.UnMode = UnionMode.Copy; //结果数据合并模式 selOpt.LayerCtrl = SelectLayerControl.Editable; //选择数据时的图层过滤类型 //创建圆交互工具 selTool = new SelectTool(control, selType, selOpt, SpaQueryMode.MBRIntersect, control.Transformation); //注册选择事件 selTool.Selected += new SelectTool.SelectHandler(selTool_Selected); }
程序代码 4 8 SelectTool的Selected事件响应关键代码
void selTool_Selected(object sender, SelectEventArgs e) { if (e.SelSet != null) { this.mapCtrl.FlashSelectSet(); int objCount = getSelectSetCount(e.SelSet); MessageBox.Show("共选择了" + objCount + "个图元"); } }
程序代码 4 9获取选择集中的个数中的关键代码
////// 获取选择集中的个数 /// /// 选择集对象 ///选择集中的个数 public int getSelectSetCount(SelectSet set) { int count = 0; //记录符合选择项的ids ObjectIDs oids = new ObjectIDs(); ObjectID oid = new ObjectID(); if (set != null) { //获取选择集列表 Listlst = set.Get(); foreach (SelectSetItem item in lst) { count += item.IDList.Count; } if (lst == null || lst.Count == 0) return count; //获取图层信息 MapLayer maplayer = lst[0].Layer; //获取图层对应的要素类的信息 basClass = maplayer.GetData(); //获取处于编辑状态第一个图层的要素ID列表 List idArr = lst[0].IDList; for (int i = 0; i < idArr.Count; i++) { oid.Int64Val = idArr[i]; oids.Append(oid); } rcdSet = new RecordSet(basClass); //添加结果集 rcdSet.AddSet(oids); } attCtrl.SetXCls((IVectorCls)basClass, rcdSet); return count; }
步骤四:实现查询功能,以矩形查询为例进行说明,在QueryByRectCmd插件中的 OnCreate方法中获取当前地图视图控件MapControl对象,以及获取DockWindow插件所绑定的属性视图控件AttControl对象,具体代码如下所示:
程序代码 4 10 OnCreate方法关键代码
public void OnCreate(IApplication hook) { hk = hook; //获取DockWindow插件 hk.PluginContainer.DockWindows.TryGetValue("InterGeomQuery.DockWindow", out dw); //通过停靠窗口来获取用户控件中的属性控件对象 attCtrl = (dw.ChildHWND as AttUserControl).attControl1; //获取当前激活视图的MapControl属性 IMapContentsView mapConView = null; mapConView = hk.ActiveContentsView as IMapContentsView; if (mapConView == null) return; mapCtrl = mapConView.MapControl; mapCtrl.Restore(); }
步骤五:在QueryByRectCmd插件中的OnClick方法中实现矩形查询,具体代码如下所示:
程序代码 4 11 OnClick方法中的关键代码
public void OnClick() { //设置为拉框查询 SelectType seltype = SelectType.Rectangle; IMapContentsView mapConView = null; mapConView = hk.ActiveContentsView as IMapContentsView; if (mapConView == null) return; //获取当前激活视图的MapControl属性 mapCtrl = (hk.ActiveContentsView as IMapContentsView).MapControl; //创建拉框选择类对象 SelectToolClass basTool = new SelectToolClass(mapCtrl, SelectDataType.Anyone, attCtrl, seltype); mapCtrl.SetBasTool(basTool); if (attCtrl == null) return; this.attCtrl.AttLButtonDown += new AttControl.AttLBtDownEventHandler(attctrl_AttLButtonDown); }
步骤六:在MapGIS.AppLoader.exe上面加载完MapGIS.WorkSpace.Plugin.dll,InterGeomQuery.dll这个2个库后,就可以实现查询功能。
4.3 插件间通讯
实现功能:插件间通讯,主要是调用目标插件的资源,如方法等;本示例功能为通过插件容器获取MapGIS.WorkSpace.Plugin插件中的CmdOpen命令按钮插件来打开一个地图文档。
效果预览如下图所示:
插件项:MenuBar(菜单栏)、Command(命令按钮)。
步骤一:打开VS 2010新建一个MapGIS项目,命名为“PluginInteraction”,在该MapGIS插件项目中创建一个MenuBar菜单栏,将Name属性值设为“PluginMenuBar”,Caption属性值设为“插件交互”;添加1个Command插件项(命名为“OpenCmd”)实现打开地图文档的功能;
步骤二:将QueryByRectCmd命令按钮插件项添加到PluginMenuBar菜单项中,具体实现代码请参考1.2小节的内容;
步骤三:定义一个命令按钮插件(ICommand对象)cmd,通过插件容器获取MapGIS.WorkSpace.Plugin插件中的CmdOpen命令按钮插件,将该插件传给cmd对象,调用cmd插件的OnClick方法打开地图文档,关键代码如下所示:
程序代码 4 12 OnClick方法实现打开地图文档代码
public void OnClick() { //命名按钮插件对象 ICommand cmd = null; //通过插件容器获取MapGIS.WorkSpace.Plugin插件中的CmdOpen命令按钮插件 hk.PluginContainer.Commands.TryGetValue("MapGIS.WorkSpace.Plugin.CmdOpen", out cmd); //获取成功 if (cmd != null) { //打开地图文档 cmd.OnClick(); //获取打开的地图文档对象 Document doc = hk.Document; //获取第一个地图 Map map = doc.GetMaps().GetMap(0); if (map == null) return; //在地图视图上显示第一个地图 hk.WorkSpaceEngine.FireMenuItemClickEvent("MapGIS.WorkSpace.Style.PreviewMap", map); }
步骤四:在MapGIS.AppLoader.exe上面加载完MapGIS.WorkSpace.Plugin.dll,CustomMapViewDemo.dll和MapGIS.MapEditor.Plugin.dll这个2个库后,就可以实现查询功能。
4.4 自定义工作空间
实现功能:自定义工作空间的开发,涉及停靠窗口(IDockWindw)插件的开发,以及工作空间目录树中地图节点的显示,目录树右键菜单的维护等;主要借助平台提供的MapGIS.UI.Controls 程序集里的MapWorkSpaceTree 类实现目录树的构建。
效果预览如下图所示:
步骤一:打开VS 2010新建一个MapGIS项目,命名为“CustomWorkspaceTree”,在该MapGIS插件项目中创建一个IMapContentsView地图视图插件,将Name属性值设为“MapView”,Caption属性值设为“自定义地图视图”;添加一个IDockWindow插件项将Name属性值设为“WorkspaceTree”,Caption属性值设为“自定义工作空间”;添加2个自定义用户控件,设置Name属性值分别为“MapViewCtrl”、“TreeView”;在“MapViewCtrl”自定义控件中拖入一个MapControl地图视图控件,设置MapControl地图视图控件Name属性值为“mapCtrl”;在“TreeView”自定义控件中拖入一个MapWorkSpackTree工作空间树控件,设置MapWorkSpackTree工作空间树控件的Name属性值为“m_tree”;
步骤二:将“MapViewCtrl”自定义控件绑定到“MapView”地图视图插件中,具体实现步骤如下:
(1) 在MapView.cs文件中定义一个自定义用户控件(MapViewCtrl对象)mapViewCtrl 的全局变量;
(2) 修改MapView.cs文件中的ObjecthWnd属性代码如下所示: 程序代码 4 13 修改ObjecthWnd属性代码
public Control ObjecthWnd { get { return mapViewCtrl; } }
(3) 修改MapView.cs文件中的MapControl属性代码如下所示之后就完成了绑定功能。
程序代码 4 14 修改MapControl属性代码
public MapGIS.GISControl.MapControl MapControl { get { return mapViewCtrl. mapCtrl; } }
步骤三:将“TreeView”自定义用户控件绑定到“WorkspaceTree”停靠窗口插件项中,具体实现步骤如下。
(1) 在DockWindow.cs文件中定义一个自定义控件(TreeView对象)tree全局变量;
(2) 修改ChildHWND属性字段代码如下所示,即可实现绑定功能:
程序代码 4 15 修改ChildHWND属性字段代码
public Control ChildHWND { get { return tree; } }
步骤四:在TreeView.cs文件中实现自定义工作空间树的相应功能,实现自定义工作空间具体步骤为:
(1) 定义一个工作空间树控件(MapWorkSpackTree对象)m_tree,添加该树的右键菜 单事件处理,关键代码如下:
程序代码 4 16 TreeView.cs文件中的全局变量
#region 变量定义 //工作空间树 MapWorkSpaceTree m_tree = null; //框架对象 IApplication app = null; //地图视图控件 MapControl mapCtrl = null; //地图集合对象 Maps maps = null; #endregion
程序代码 4 17 TreeView自定义控件加载事件代码
private void TreeView_Load(object sender, EventArgs e) { try { //获取框架对象 app = WorkspaceTree.hk; //加载树 m_tree = new MapWorkSpaceTree(); m_tree.Dock = DockStyle.Fill; //添加到用户控件 this.Controls.Add(m_tree); //注册节点右键菜单单击事件 m_tree.MenuItemOnClickEvent += new MapGIS.WorkSpaceEngine.MenuItemOnClickHandler(m_tree_MenuItemOnClickEvent); m_tree.Document.Title = "地图文档"; } catch(Exception ex){ MessageBox.Show(ex.ToString()); } }
(2) 实现目录树上的地图节点右键菜单预览地图的功能,在右键菜单单击事件中实现关 键代码如下所示:
程序代码 4 18 mtreeMenuItemOnClickEvent关键代码
void m_tree_MenuItemOnClickEvent(string typeName, MapGIS.GeoMap.DocumentItem item) { try { #region 预览地图 if (item is Map) { Map map = item as Map; //内容视图插件 IContentsView icv = null; //获取地图视图 app.PluginContainer.ContentsViews.TryGetValue(map.Handle.ToString() + "$MapView", out icv); if (icv == null) { //创建自定义地图视图插件 icv = app.PluginContainer.CreateContentsView("CustomWorkspaceTree.MapView", map.Handle.ToString() + "$MapView"); if (icv != null && icv is IMapContentsView) { IMapContentsView mv = icv as IMapContentsView; //获取地图视图控件 mapCtrl = mv.MapControl; //激活地图 mv.MapControl.ActiveMap = map; //设置地图显示控件 m_tree.WorkSpace.SetMapControl(map, mv.MapControl); //获取地图显示范围 Rect rect = map.GetViewRange(); if (rect != null && (rect.XMax - rect.XMin).CompareTo(0) > 0 && (rect.YMax - rect.YMin).CompareTo(0) > 0) mv.MapControl.Transformation.SetDispRect(rect); mv.MapControl.Refresh(); app.StateManager.OnStateChanged(this, new StateEventArgs()); } } else { //如果自定义地图视图插件已经打开 IMapContentsView mv = icv as IMapContentsView; if (mv != null) { //激活地图视图 app.PluginContainer.ActiveContentsView(mv); Rect rt = map.GetEntireRange(); Rect rt1 = map.GetViewRange(); mv.MapControl.Refresh(); } } } #endregion } catch(Exception ex){ MessageBox.Show(ex.ToString()); } }
步骤五:在地图右键菜单中添加一个自定义菜单,具体步骤为:
(1) 在TreeView.cs文件中定义一个自定义菜单类CustomGloableMenu,该类继承并实 现ISingleMenuItem 接口,具体代码如下:
程序代码 4 19 CustomGloableMenu类中代码
#region 单选右键菜单项类 class CustomGloableMenu : ISingleMenuItem { //新建地图文档 #region ISingleMenuItem 成员 public bool BeginGroup { get { return false; } } public Bitmap Bitmap { get { return null; } } public string Caption { get { return "自定义菜单"; } } public bool Checked { get { return false; } } public bool Enabled { get { return true; } } public bool Visible { get { return true; } } public void OnClick(DocumentItem item) { MessageBox.Show("自定义菜单演示!"); } public void OnCreate(MapGIS.WorkSpaceEngine.IWorkSpace ws) { } #endregion } #endregion
(2) 调用mtree类的WorkSpace属性获取工作空间WorkSpace对象,再调用WorkSpace 对象的GetMenuExtand 方法获取右键菜单项,将返回值传给菜单扩展(IMenuExtander对象)ime;定义一个CustomGloableMenu类对象,并初始化,调用ime对象的AddItem方法将CustomGloableMenu类添加到右键菜单栏中,在DocumentOpenedDocument打开地图文档事件中实现该功能,具体代码如下:
程序代码 4 20 自定义菜单实现具体代码
void Document_OpenedDocument(object sender, EventArgs e) { //为地图节点添加右键菜单项 IMenuExtander ime = this.m_tree.WorkSpace.GetMenuExtand(typeof(MapGIS.GeoMap.Map)); //自定义菜单对象 CustomGloableMenu menuItem = new CustomGloableMenu(); menuItem.OnCreate(this.m_tree.WorkSpace); //将自定义菜单添加到右键菜单项 ime.AddItem(menuItem); }
效果如下图所示:
步骤五:在MapGIS.AppLoader.exe上面加载完CustomWorkspaceTree.dll这个库后,就可以实现自定义工作空间功能。