在ArcMap中,一些对话框是很复杂的,例如设置点线面样式的对话框,选择空间参考的对话框等,但这些对话框有些在ArcObjects SDK中是可以直接调用的。
var mySpatialReference = this.UI_SpatialReference_TextBox.Tag as ISpatialReference; if (mySpatialReference == null) { return; } var mySpatialReferenceDialog = new SpatialReferenceDialogClass { BasicMap = this._Grid.BasicMap }; mySpatialReference = mySpatialReferenceDialog.DoModalEdit(mySpatialReference, true, false, false, false, false, 0) as ISpatialReference; if (mySpatialReference != null) { this.UI_SpatialReference_TextBox.Text = mySpatialReference.Name; this.UI_SpatialReference_TextBox.Tag = mySpatialReference; }
我们看下SpatialReferenceDialogClass类的定义。
BasicMap属性,该属性是可以在弹出对话框中快速选择当前地图图层的空间参考,不设置也可以。
DoModalEdit函数,该函数是主函数,即弹出选择对话框。该函数的定义如下。
public ISpatialReference DoModalEdit ( ISpatialReference inputSpatialReference, bool hasXY, bool hasZ, bool hasM, bool coordPageReadOnly, bool domainPageReadOnly, int hParent);
第一个函数就是我们传入的要编辑的空间参考对象,接下来三个参数是指是否内包含xy、z和m,我一般设置为true,false,false。后面的参数分别设置coord选项卡是否只读,domain选项卡是否只读以及父窗体的标识,一般设置为false,false,0。
除了DoModalEdit函数外,还有DoModalCreate函数,该函数是创建一个新的空间参考,参数和DoModalEdit函数类似。
ISymbolSelector mySymbolSelector = new SymbolSelectorClass(); mySymbolSelector.AddSymbol(myLineSymbol as ISymbol); bool myIsOk = mySymbolSelector.SelectSymbol(0); if (myIsOk) { myLineSymbol = mySymbolSelector.GetSymbolAt(0) as ILineSymbol; }
主要用到的类是SymbolSelectorClass,通过AddSymbol函数,设置要编辑的样式对象,调用SelectSymbol函数,弹出样式选择和设置对话框,并返回是否点击确定按钮,如果点击了确定,可以通过GetSymbolAt函数获取选择或者编辑后的样式对象。
点击右侧的Edite Symbol按钮,可以弹出更详细的参设置对话框,如下图所示。
IColor myColor = new RgbColor() { Red = 255, Blue = 0, Green = 0 }; IColorBrowser myColorBrowser = new ColorBrowser() { Color = myColor }; if (myColorBrowser.DoModal(0)) { myColor = myColorBrowser.Color; }
IColor myColor = new RgbColor() { Red = 255, Blue = 0, Green = 0 }; IColorSelector myColorSelector = new ColorSelectorClass() { Color = myColor }; if (myColorSelector.DoModal(0)) { myColor = myColorSelector.Color; }
但一般情况下我们都会调用.Net或者第三方UI自带的颜色选择器,基本不怎么用ArcOObjects SDK的颜色设置对话框。
该对话框的主接口为IStyleSelector,我看下该接口的定义。
从帮助中可以看出,实现该接口的有背景选择器,边线选择器,图例元素、指北针、比例尺等。但实际测试的时候这些对话框并不弹出来,但看网上有人说是可以弹出来的,并贴出了图片。难道是因为我的UI是用的WPF的原因?研究了半天没搞明白,就放弃了,使用AxSymbologyControl,自己包装了一个对话框。
5、使用AxSymbologyControl自定义样式选择设置对话框
AxSymbologyControl是一个基于winform的UI,我们可以把这个UI放对话框中,自定义一个样式选择设置对话框。使用AxSymbologyControl有两个关键点,一是设置要显示的符号类型,二是要设置加载的ServerStyle文件。代码如下图所示。
this._AxSymbologyControl = new AxSymbologyControl(); this._AxSymbologyControl.BeginInit(); this.UI_WindowsFormsHost.Child = this._AxSymbologyControl; this._AxSymbologyControl.EndInit(); this._AxSymbologyControl.StyleClass = pSymbologyStyle; string myInstall = ESRI.ArcGIS.RuntimeManager.ActiveRuntime.Path; string myEsriStyleFile = myInstall + "\\Styles\\ESRI.serverstyle"; if (File.Exists(myEsriStyleFile)) { this._AxSymbologyControl.LoadStyleFile(myEsriStyleFile); }
AxSymbologyControl.StyleClass属性的类型为esriSymbologyStyleClass,该枚举的定义如下。
这说明AxSymbologyControl可以加载这么多类型,因为使用IStyleSelector不能弹出选择边框的对话框,那么我们就用在AxSymbologyControl上设置一下边框,也就是esriSymbologyStyleClass。弹出的对话框如下图所示。
这个对话框是我们自己定义的,里面放了AxSymbologyControl,右上角是一个符号预览UI。
这个接口直接翻译是属性页面的意思,实际上可以TabControl里面的一个选项卡,放到对话框中。通过查看有哪些类继承了该接口,我们可以了解到我们能直接用哪些UI。这些可以在帮助中查看。
我们查看帮助中,发现有一些和FeatureLayer有关的实现类,那么我们是不是可以把这些PropertyPage组合在一起,形成一个对话框呢?代码如下。
ILayer mySelectLayer = this.MapApplication.SelectTocObject as ILayer; if (mySelectLayer == null) { return; } ESRI.ArcGIS.Framework.IComPropertySheet myComPropertySheet = new ESRI.ArcGIS.Framework.ComPropertySheet(); myComPropertySheet.Title = mySelectLayer.Name + " - Properties"; ESRI.ArcGIS.esriSystem.UID myUID = new ESRI.ArcGIS.esriSystem.UIDClass(); myComPropertySheet.AddCategoryID(myUID); myComPropertySheet.AddPage(new ESRI.ArcGIS.CartoUI.GeneralLayerPropPageClass()); if (mySelectLayer is IFeatureLayer) { myComPropertySheet.AddPage(new ESRI.ArcGIS.CartoUI.FeatureLayerSourcePropertyPageClass()); myComPropertySheet.AddPage(new ESRI.ArcGIS.CartoUI.LayerFieldsPropertyPageClass()); myComPropertySheet.AddPage(new ESRI.ArcGIS.CartoUI.LayerDrawingPropertyPageClass()); myComPropertySheet.AddPage(new ESRI.ArcGIS.CartoUI.LayerLabelsPropertyPageClass()); myComPropertySheet.AddPage(new ESRI.ArcGIS.CartoUI.LayerDefinitionQueryPropertyPageClass()); } ESRI.ArcGIS.esriSystem.ISet mySet = new ESRI.ArcGIS.esriSystem.SetClass(); mySet.Add(mySelectLayer); mySet.Reset(); myComPropertySheet.ActivePage = 2; bool myIsOK = myComPropertySheet.EditProperties(mySet, 0); if (myIsOK == false) { return; } this.MapApplication.TOCControl.Update(); this.MapApplication.ActiveView.Refresh();
ComPropertySheet为我们定义的一个主对话框,通过AddPage函数,添加实现IPropertyPage接口的类。例如我们首先添加了GeneralLayerPropPageClass,判断如果是矢量图层,右增加了图层数据源、图层字段管理、图层渲染、标注以及默认查询等页面,,并默认激活第二个。弹出的对话框如下。
矢量图层的Page定义比较全,栅格数据的就比较少了,没有比较复杂的栅格数据渲染设置。这个问题咨询过Esri中国的技术支持,给的回复是确实没有定义。如果有能直接调用栅格图层渲染设置的面板的朋友,可以留言或私信告诉下,非常感谢。
INumberDialog myNumberDialog = new NumberDialogClass(); bool myIsOK = myNumberDialog.DoModal("输入数字", 1.00, 5, 0); if (myIsOK == true) { MessageBox.Show(myNumberDialog.Value.ToString()); }
IGetStringDialog myGetStringDialog = new GetStringDialogClass(); bool myIsOK = myGetStringDialog.DoModal("输入字符串", "字符串:", "初始的字符串", 0); if (myIsOK == true) { MessageBox.Show(myGetStringDialog.Value.ToString()); }
ICoordinateDialog myCoordinateDialog = new CoordinateDialogClass(); bool myIsOK = myCoordinateDialog.DoModal("输入坐标", 116, 42, 4, 0); if (myIsOK == true) { MessageBox.Show(myCoordinateDialog.X.ToString() + "," + myCoordinateDialog.Y.ToString()); }
不过这些对话框使用Winform或者WPF都比较容易实现,所以我们很少直接使用SDK里面定义的这些。
ArcObjects SDK中可以直接调用的对话框还有很多,我们可以在帮助中搜索例如Dialog、Window等这样的关键字,查看搜到的结果,根据名称判断是不是对话框,然后写代码测试下,就知道效果以及如何使用了。