下面是卷帘和图层闪烁的屏幕截图,下面来讲解一下如何实现卷帘和图层闪烁:
首先需要定义一个成员对象ILayerEffectProperties,这个对象用于维护命令环境,指定卷帘和闪烁的图层;其次我们需要侦听地图的添加和删除图层事件,因此还需要一个ActiveViewEvents事件的侦听对象,如下:
private ESRI.ArcGIS.Carto.IActiveViewEvents_Event MapActiveViewEvents;
private ILayerEffectProperties m_LayerEffectProperties;
private ICommand m_FlickCmd;
为了实现卷帘和闪烁,我们需要一个ComboBox维护一个图层列表,用于选中卷帘和闪烁的图层,也就是我们需要侦听地图的添加和删除图层事件,在这些事件发生时重新加载图层列表。对于地图的侦听事件,我们需要在窗体加载和OnMapReplaced时注册事件响应函数:
if (MapActiveViewEvents != null)
{
MapActiveViewEvents.ItemAdded -= new ESRI.ArcGIS.Carto.IActiveViewEvents_ItemAddedEventHandler(MapActiveViewEvents_ItemAdded);
MapActiveViewEvents.ItemDeleted -= new ESRI.ArcGIS.Carto.IActiveViewEvents_ItemDeletedEventHandler(MapActiveViewEvents_ItemDeleted);
MapActiveViewEvents.ItemReordered -= new ESRI.ArcGIS.Carto.IActiveViewEvents_ItemReorderedEventHandler(MapActiveViewEvents_ItemReordered);
}
IMap pMap = wndMap.ActiveView.FocusMap as IMap;
MapActiveViewEvents = pMap as ESRI.ArcGIS.Carto.IActiveViewEvents_Event;
MapActiveViewEvents.ItemAdded += new ESRI.ArcGIS.Carto.IActiveViewEvents_ItemAddedEventHandler(MapActiveViewEvents_ItemAdded);
MapActiveViewEvents.ItemDeleted += new ESRI.ArcGIS.Carto.IActiveViewEvents_ItemDeletedEventHandler(MapActiveViewEvents_ItemDeleted);
MapActiveViewEvents.ItemReordered += new ESRI.ArcGIS.Carto.IActiveViewEvents_ItemReorderedEventHandler(MapActiveViewEvents_ItemReordered);
在这些事件中,我们需要重新加载图层列表到我们的ComboBox里面去:
void MapActiveViewEvents_ItemReordered(object Item, int toIndex)
{
ReLoadLayerList();
}
void MapActiveViewEvents_ItemDeleted(object Item)
{
ReLoadLayerList();
}
void MapActiveViewEvents_ItemAdded(object Item)
{
ReLoadLayerList();
}
private void ReLoadLayerList()
{
wndLayerListImageComboBox.Items.Clear();
IMap pMap = wndMap.ActiveView.FocusMap;
for (int i = 0; i < pMap.LayerCount; i++)
{
ILayer pLayer = pMap.get_Layer(i);
int imageIdndex = 0;
if(pLayer is IGeoFeatureLayer)
{
IGeoFeatureLayer pGeoLayer = pLayer as IGeoFeatureLayer;
if(pGeoLayer.FeatureClass.ShapeType == esriGeometryType.esriGeometryPoint) imageIdndex =0;
else if(pGeoLayer.FeatureClass.ShapeType == esriGeometryType.esriGeometryPolyline) imageIdndex = 1;
else if(pGeoLayer.FeatureClass.ShapeType == esriGeometryType.esriGeometryPolygon) imageIdndex =2;
}
else if(pLayer is IRasterLayer) imageIdndex = 3;
wndLayerListImageComboBox.Items.Add(new DevExpress.XtraEditors.Controls.ImageComboBoxItem(pLayer.Name, pLayer, imageIdndex));
}
}
完成这些内容以后,我们还需要在每次选择卷帘和闪烁图层后,把选中的图层赋给LayerEffectProperties对象:
private void wndLayerListImageComboBox_SelectedIndexChanged(object sender, EventArgs e)
{
DevExpress.XtraEditors.ImageComboBoxEdit edit = sender as DevExpress.XtraEditors.ImageComboBoxEdit;
if (edit.Value != null && edit.Value is ILayer)
{
ILayer pLayer = edit.Value as ILayer;
m_LayerEffectProperties.SwipeLayer = pLayer;
m_LayerEffectProperties.FlickerLayer = pLayer;
m_LayerEffectProperties.TransparencyLayer = pLayer;
}
}
之后,就是工具响应了,具体如下:
/// <summary>
/// 卷帘工具
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void wndBtnLayerSwipe_ItemClick(object sender, ItemClickEventArgs e)
{
ICommand pCmd = new ControlsMapSwipeTool();
//只有MapControl支持卷帘,PageLayout不可以
if (wndTabMainView.SelectedTabPage == wndTabPageMapView)
{
pCmd.OnCreate(wndMap.Object);
wndMap.CurrentTool = pCmd as ITool;
}
}
/// <summary>
/// 图层闪烁频率
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void wndLayerFlickRateSpinEdit_EditValueChanged(object sender, EventArgs e)
{
if (m_LayerEffectProperties != null)
{
DevExpress.XtraEditors.SpinEdit edit = sender as DevExpress.XtraEditors.SpinEdit;
int rate = int.Parse(edit.Value.ToString());
m_LayerEffectProperties.FlickerRate = rate;
}
}
对于闪烁,这里一定要注意的一点是,一定要把这个命令声明为成员对象,否则会因为这个Command被析构而出现图层只会闪几下就不闪了的现象;另外还需要把它作为Tool设置给地图的CurrentTool,否则在鼠标点击地图或者移动时也会发生地图停止闪烁的问题。
/// <summary>
/// 图层闪烁
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void wndBtnLayerFlick_ItemClick(object sender, ItemClickEventArgs e)
{
if (m_FlickCmd != null) Marshal.ReleaseComObject(m_FlickCmd);
m_FlickCmd = new ControlsMapFlickerCommand();
if (wndTabMainView.SelectedTabPage == wndTabPageMapView)
{
m_FlickCmd.OnCreate(wndMap.Object);
wndMap.CurrentTool = m_FlickCmd as ITool; //设置为当前的Tool,否则移动鼠标就会使地图停止闪烁
m_FlickCmd.OnClick();
}
}
最后补充一点操作技巧,当地图在卷帘工具下,按住Ctr或者Shift键,就可以实现类似ENVI的图层闪烁功能,这个小技巧你知道吗?