C#+AE开发TOCControl右键菜单打开属性表/图层目录右键功能

文章转载自网易云博客,最初原创博客链接已失效,不再给出。仅给出转载链接:

C# AE开发 TOCControl 右键打开图层属性表  

致谢!

////////////////////////////////////////华丽丽的分割线/////////////////////////////////////////////////////

在ArcMap中,单击图层右键菜单中的“Open Attribute Table”命令,便可弹出属性数据表。本讲将完成类似的功能。

数据表显示,我们用了DataGridView控件。DataGridView 控件提供一种强大而灵活的以表格形式显示数据的方式。可以使用 DataGridView 控件来显示少量数据的只读视图,也可以对其进行缩放以显示特大数据集的可编辑视图。我们可以很方便地把一个DataTable作为数据源绑定到DataGridView控件中。

本讲的思路大体如下:首先根据图层属性中的字段创建一个空的DataTable,然后根据数据内容一行行填充DataTable数据,再将DataTable绑定到DataGridView控件,最后调用并显示属性表窗体。

创建属性表窗体

新建一个Windows窗体,命名为“AttributeTableFrm.cs”。

从工具箱拖一个DataGridView控件到窗体,并将其Dock属性设置为“Fill”。

添加如下引用:

using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Controls;
using ESRI.ArcGIS.esriSystem;
using ESRI.ArcGIS.SystemUI;
using ESRI.ArcGIS.Geometry;
using ESRI.ArcGIS.Geodatabase;

创建空DataTable

首先传入ILayer,再查询到ITable,从ITable中的Fileds中获得每个Field,再根据Filed设置DataTable的DataColumn,由此创建一个只含图层字段的空DataTable。实现函数如下:

/// <summary>
/// 根据图层字段创建一个只含字段的空DataTable
/// </summary>
/// <param name="pLayer"></param>
/// <param name="tableName"></param>
/// <returns></returns>
private static DataTable CreateDataTableByLayer(ILayer pLayer, string tableName)
{
	//创建一个DataTable表
	DataTable pDataTable = new DataTable(tableName);
	//取得ITable接口
	ITable pTable = pLayer as ITable;
	IField pField = null;
	DataColumn pDataColumn;
	//根据每个字段的属性建立DataColumn对象
	for (int i = 0; i < pTable.Fields.FieldCount; i++)
	{
	    pField = pTable.Fields.get_Field(i);
	    //新建一个DataColumn并设置其属性
	    pDataColumn = new DataColumn(pField.Name);
	    if (pField.Name == pTable.OIDFieldName)
	    {
	        pDataColumn.Unique = true;//字段值是否唯一
	    }
	    //字段值是否允许为空
	    pDataColumn.AllowDBNull = pField.IsNullable;
	    //字段别名
	    pDataColumn.Caption = pField.AliasName;
	    //字段数据类型
	    pDataColumn.DataType = System.Type.GetType(ParseFieldType(pField.Type));
	    //字段默认值
	    pDataColumn.DefaultValue = pField.DefaultValue;
	    //当字段为String类型是设置字段长度
	    if (pField.VarType == 8)
	    {
	        pDataColumn.MaxLength = pField.Length;
	    }
	    //字段添加到表中
	    pDataTable.Columns.Add(pDataColumn);
	    pField = null;
	    pDataColumn = null;
	}
	return pDataTable;
}

因为GeoDatabase的数据类型与.NET的数据类型不同,故要进行转换。转换函数如下:

/// <summary>
/// 将GeoDatabase字段类型转换成.Net相应的数据类型
/// </summary>
/// <param name="fieldType">字段类型</param>
/// <returns></returns>
public static string ParseFieldType(esriFieldType fieldType)
{
	switch (fieldType)
	{
	    case esriFieldType.esriFieldTypeBlob:
	        return "System.String";
	    case esriFieldType.esriFieldTypeDate:
	        return "System.DateTime";
	    case esriFieldType.esriFieldTypeDouble:
	        return "System.Double";
	    case esriFieldType.esriFieldTypeGeometry:
	        return "System.String";
	    case esriFieldType.esriFieldTypeGlobalID:
	        return "System.String";
	    case esriFieldType.esriFieldTypeGUID:
	        return "System.String";
	    case esriFieldType.esriFieldTypeInteger:
	        return "System.Int32";
	    case esriFieldType.esriFieldTypeOID:
	        return "System.String";
	    case esriFieldType.esriFieldTypeRaster:
	        return "System.String";
	    case esriFieldType.esriFieldTypeSingle:
	        return "System.Single";
	    case esriFieldType.esriFieldTypeSmallInteger:
	        return "System.Int32";
	    case esriFieldType.esriFieldTypeString:
	        return "System.String";
	    default:
	        return "System.String";
	}
}

装载DataTable数据

从上一步得到的DataTable还没有数据,只有字段信息。因此,我们要通过ICursor从ITable中逐一取出每一行数据,即IRow。再创建DataTable中相应的DataRow,根据IRow设置DataRow信息,再将所有的DataRow添加到DataTable中,就完成了DataTable数据的装载。

为保证效率,一次最多只装载2000条数据到DataGridView。函数代码如下:

/// <summary>
/// 填充DataTable中的数据
/// </summary>
/// <param name="pLayer"></param>
/// <param name="tableName"></param>
/// <returns></returns>
public static DataTable CreateDataTable(ILayer pLayer, string tableName)
{
	//创建空DataTable
	DataTable pDataTable = CreateDataTableByLayer(pLayer, tableName);
	//取得图层类型
	string shapeType = getShapeType(pLayer);
	//创建DataTable的行对象
	DataRow pDataRow = null;
	//从ILayer查询到ITable
	ITable pTable = pLayer as ITable;
	ICursor pCursor = pTable.Search(null, false);
	//取得ITable中的行信息
	IRow pRow = pCursor.NextRow();
	int n = 0;
	while (pRow != null)
	{
	    //新建DataTable的行对象
	    pDataRow = pDataTable.NewRow();
	    for (int i = 0; i < pRow.Fields.FieldCount; i++)
	    {
	        //如果字段类型为esriFieldTypeGeometry,则根据图层类型设置字段值
	        if (pRow.Fields.get_Field(i).Type == esriFieldType.esriFieldTypeGeometry)
	        {
	            pDataRow[i] = shapeType;
	        }
	        //当图层类型为Anotation时,要素类中会有esriFieldTypeBlob类型的数据,
	        //其存储的是标注内容,如此情况需将对应的字段值设置为Element
	        else if (pRow.Fields.get_Field(i).Type == esriFieldType.esriFieldTypeBlob)
	        {
	            pDataRow[i] = "Element";
	        }
	        else
	        {
	            pDataRow[i] = pRow.get_Value(i);
	        }
	    }
	    //添加DataRow到DataTable
	    pDataTable.Rows.Add(pDataRow);
	    pDataRow = null;
	    n++;
	    //为保证效率,一次只装载最多条记录
	    if (n == 2000)
	    {
	        pRow = null;
	    }
	    else
	    {
	        pRow = pCursor.NextRow();
	    }
	}
	return pDataTable;
}

上面的代码中涉及到一个获取图层类型的函数getShapeTape,此函数是通过ILayer判断图层类型的,代码如下:

/// <summary>
/// 获得图层的Shape类型
/// </summary>
/// <param name="pLayer">图层</param>
/// <returns></returns>
public static string getShapeType(ILayer pLayer)
{
	IFeatureLayer pFeatLyr = (IFeatureLayer)pLayer;
	switch (pFeatLyr.FeatureClass.ShapeType)
	{
	    case esriGeometryType.esriGeometryPoint:
	        return "Point";
	    case esriGeometryType.esriGeometryPolyline:
	        return "Polyline";
	    case esriGeometryType.esriGeometryPolygon:
	        return "Polygon";
	    default:
	        return "";
	}
}

绑定DataTable到DataGridView

通过以上步骤,我们已经得到了一个含有图层属性数据的DataTable。现定义一个AttributeTableFrm类的成员变量:

public DataTable attributeTable;

通过以下函数,我们很容易将其绑定到DataGridView控件中:

/// <summary>
/// 绑定DataTable到DataGridView
/// </summary>
/// <param name="player"></param>
public void  CreateAttributeTable(ILayer player)
{
	string tableName;
	tableName = getValidFeatureClassName(player .Name );
	attributeTable  = CreateDataTable(player,tableName );
	this.dataGridView1 .DataSource  = attributeTable ;
	this.Text = "属性表[" + tableName + "]  " + "记录数:"+attributeTable.Rows.Count .ToString();
}
	因为DataTable的表名不允许含有“.”,因此我们用“_”替换。函数如下:
/// <summary>
/// 替换数据表名中的点
/// </summary>
/// <param name="FCname"></param>
/// <returns></returns>
public static string getValidFeatureClassName(string FCname)
{
	int dot = FCname.IndexOf(".");
	if (dot != -1)
	{
	    return FCname.Replace(".", "_");
	}
	return FCname;
}

调用属性表窗体

通过1-4步骤,我们封装了一个AttributeTableFrm类,此类能够由ILayer显示图层中的属性表数据。那怎么调用AttributeTableFrm呢?

前面已经提到,我们是在TOCControl选中图层的右键菜单中弹出属性表窗体的,因此我们需要添加一个菜单项到TOCControl中Layer的右键菜单。而在第六讲中,我们采用的是AE中的IToolbarMenu实现右键菜单的,故我们还需自定义一个Command,实现打开属性表的功能。

以ArcGIS的Base Command为模板新建项“OpenAttributeTable.cs”。

注意:新建Base Command模板时,会弹出一个对话框让我们选择模板适用对象,这时我们要选择MapControl、PageLayoutControl,即选择第二项或者倒数第二项。

添加如下引用:

using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Display;
using ESRI.ArcGIS.esriSystem;

添加成员变量:

private ILayer m_pLayer;

修改构造函数为:

public OpenAttributeTable(ILayer pLayer)
{
	//
	// TODO: Define values for the public properties
	//
	base.m_category = ""; //localizable text
	base.m_caption = "打开属性表";  //localizable text
	base.m_message = "打开属性表";  //localizable text 
	base.m_toolTip = "打开属性表";  //localizable text 
	base.m_name = "打开属性表";   //unique id, non-localizable (e.g. "MyCategory_MyCommand")
	m_pLayer = pLayer;

	try
	{
	    //
	    // TODO: change bitmap name if necessary
	    //
	    string bitmapResourceName = GetType().Name + ".bmp";
	    base.m_bitmap = new Bitmap(GetType(), bitmapResourceName);
	}
	catch (Exception ex)
	{
	    System.Diagnostics.Trace.WriteLine(ex.Message, "Invalid Bitmap");
	}
}

再在On_Click函数中添加如下代码,以创建并打开属性表窗体。

/// <summary>
/// Occurs when this command is clicked
/// </summary>
public override void OnClick()
{
	// TODO: Add OpenAttributeTable.OnClick implementation
	AttributeTableFrm attributeTable = new AttributeTableFrm();
	attributeTable.CreateAttributeTable(m_pLayer);
	attributeTable.ShowDialog();
}

至此,我们完成了OpenAttributeTable命令。显然,我们要在TOCControl的OnMouseDown事件中调用此命令。

因为,当前选中的图层参数,即ILayer是通过OpenAttributeTable的构造函数传入的,而选中的ILayer是动态变化的,所以我们无法在窗体初始化的Form1_Load事件中就添加OpenAttributeTable菜单项到右键菜单。但我们可以在OnMouseDown事件中动态添加OpenAttributeTable菜单项。

要注意的是,最后我们必须移除添加的OpenAttributeTable菜单项,不然每次按下右键都会添加此菜单项,将造成右键菜单中含有多个OpenAttributeTable菜单项。修改TOCControl的OnMouseDown事件的部分代码如下:

private void axTOCControl1_OnMouseDown(object sender, ITOCControlEvents_OnMouseDownEvent e)
{
	//……
	//弹出右键菜单
	if (item == esriTOCControlItem.esriTOCControlItemMap)
		m_menuMap.PopupMenu(e.x, e.y, m_tocControl.hWnd);
	if (item == esriTOCControlItem.esriTOCControlItemLayer)
	{
		//动态添加OpenAttributeTable菜单项
		m_menuLayer.AddItem(new OpenAttributeTable(layer), -1, 2, true, esriCommandStyles.esriCommandStyleTextOnly);
		m_menuLayer.PopupMenu(e.x, e.y, m_tocControl.hWnd);
		//移除OpenAttributeTable菜单项,以防止重复添加
		m_menuLayer.Remove(2);
	}
}

//////////////////////////////////////////华丽丽的分割线///////////////////////////////////////////////////////

 
根据作者的源码,我做了小小的修改,将所有函数直接添加进主程序窗口代码,函数前面的 public static 也改成 private
一下是我的代码:
/////////////////////////////////////////////////华丽丽的分割线/////////////////////////////////////////////////////////////////////////////
#region 右键打开属性表
 
 
///菜单点击事件函数,其中SelectedLayer_TOC是TOCControl窗口当前选中的图层
        private void OpenAttribute_toolStripMenuItem1_Click(object sender, EventArgs e)
        {
            CreateAttributeTable(SelectedLayer_TOC);
            dataGridView1.Width = 300;
        }
 
        public DataTable attributeTable;
        /// <summary>
        /// 首先传入ILayer,再查询到ITable,从ITable中的Fileds中获得每个Field,再根据Filed设置DataTable的DataColumn,由此创建一个只含图层字段的空DataTable。
        /// </summary>
        /// <param name="pLayer"></param>
        /// <param name="tableName"></param>
        /// <returns></returns>
        private DataTable CreateDataTableByLayer(ILayer pLayer, string tableName)
        {
            //创建一个DataTable表
            DataTable pDataTable = new DataTable(tableName);
            //取得ITable接口
            ITable pTable = pLayer as ITable;
            IField pField = null;
            DataColumn pDataColumn;
            //根据每个字段的属性建立DataColumn对象
            for (int i = 0; i < pTable.Fields.FieldCount; i++)
            {
                pField = pTable.Fields.get_Field(i);
                //新建一个DataColumn并设置其属性
                pDataColumn = new DataColumn(pField.Name);
                if (pField.Name == pTable.OIDFieldName)
                {
                    pDataColumn.Unique = true;//字段值是否唯一
                }
                //字段值是否允许为空
                pDataColumn.AllowDBNull = pField.IsNullable;
                //字段别名
                pDataColumn.Caption = pField.AliasName;
                //字段数据类型
                pDataColumn.DataType = System.Type.GetType(ParseFieldType(pField.Type));
                //字段默认值
                pDataColumn.DefaultValue = pField.DefaultValue;
                //当字段为String类型是设置字段长度
                if (pField.VarType == 8)
                {
                    pDataColumn.MaxLength = pField.Length;
                }
                //字段添加到表中
                pDataTable.Columns.Add(pDataColumn);
                pField = null;
                pDataColumn = null;
            }
            return pDataTable;
        }
 
        ///因为GeoDatabase的数据类型与.NET的数据类型不同,故要进行转换。转换函数如下:
        /// <summary>
        /// 将GeoDatabase字段类型转换成.Net相应的数据类型
        /// </summary>
        /// <param name="fieldType">字段类型</param>
        /// <returns></returns>
        private string ParseFieldType(esriFieldType fieldType)
        {
            switch (fieldType)
            {
                case esriFieldType.esriFieldTypeBlob:
                    return "System.String";
                case esriFieldType.esriFieldTypeDate:
                    return "System.DateTime";
                case esriFieldType.esriFieldTypeDouble:
                    return "System.Double";
                case esriFieldType.esriFieldTypeGeometry:
                    return "System.String";
                case esriFieldType.esriFieldTypeGlobalID:
                    return "System.String";
                case esriFieldType.esriFieldTypeGUID:
                    return "System.String";
                case esriFieldType.esriFieldTypeInteger:
                    return "System.Int32";
                case esriFieldType.esriFieldTypeOID:
                    return "System.String";
                case esriFieldType.esriFieldTypeRaster:
                    return "System.String";
                case esriFieldType.esriFieldTypeSingle:
                    return "System.Single";
                case esriFieldType.esriFieldTypeSmallInteger:
                    return "System.Int32";
                case esriFieldType.esriFieldTypeString:
                    return "System.String";
                default:
                    return "System.String";
            }
        }
 
        /// <summary>
        /// 填充DataTable中的数据
        /// </summary>
        /// <param name="pLayer"></param>
        /// <param name="tableName"></param>
        /// <returns></returns>
        private DataTable CreateDataTable(ILayer pLayer, string tableName)
        {
            //创建空DataTable
            DataTable pDataTable = CreateDataTableByLayer(pLayer, tableName);
            //取得图层类型
            string shapeType = getShapeType(pLayer);
            //创建DataTable的行对象
            DataRow pDataRow = null;
            //从ILayer查询到ITable
            ITable pTable = pLayer as ITable;
            ICursor pCursor = pTable.Search(null, false);
            //取得ITable中的行信息
            IRow pRow = pCursor.NextRow();
            int n = 0;
            while (pRow != null)
            {
                //新建DataTable的行对象
                pDataRow = pDataTable.NewRow();
                for (int i = 0; i < pRow.Fields.FieldCount; i++)
                {
                    //如果字段类型为esriFieldTypeGeometry,则根据图层类型设置字段值
                    if (pRow.Fields.get_Field(i).Type == esriFieldType.esriFieldTypeGeometry)
                    {
                        pDataRow[i] = shapeType;
                    }
                    //当图层类型为Anotation时,要素类中会有esriFieldTypeBlob类型的数据,
                    //其存储的是标注内容,如此情况需将对应的字段值设置为Element
                    else if (pRow.Fields.get_Field(i).Type == esriFieldType.esriFieldTypeBlob)
                    {
                        pDataRow[i] = "Element";
                    }
                    else
                    {
                        pDataRow[i] = pRow.get_Value(i);
                    }
                }
                //添加DataRow到DataTable
                pDataTable.Rows.Add(pDataRow);
                pDataRow = null;
                n++;
                //为保证效率,一次只装载最多条记录
                if (n == 2000)
                {
                    pRow = null;
                }
                else
                {
                    pRow = pCursor.NextRow();
                }
            }
            return pDataTable;
        }
 
        /// <summary>
        /// 获得图层的Shape类型
        /// </summary>
        /// <param name="pLayer">图层</param>
        /// <returns></returns>
        private string getShapeType(ILayer pLayer)
        {
            IFeatureLayer pFeatLyr = (IFeatureLayer)pLayer;
            switch (pFeatLyr.FeatureClass.ShapeType)
            {
                case esriGeometryType.esriGeometryPoint:
                    return "Point";
                case esriGeometryType.esriGeometryPolyline:
                    return "Polyline";
                case esriGeometryType.esriGeometryPolygon:
                    return "Polygon";
                default:
                    return "";
            }
        }
 
        /// <summary>
        /// 绑定DataTable到DataGridView
        /// </summary>
        /// <param name="player"></param>
        public void CreateAttributeTable(ILayer player)
        {
            string tableName;
            tableName = getValidFeatureClassName(player.Name);
            attributeTable = CreateDataTable(player, tableName);
            this.dataGridView1.DataSource = attributeTable;
            this.Text = "属性表[" + tableName + "]  " + "记录数:" + attributeTable.Rows.Count.ToString();
        }
        /// 因为DataTable的表名不允许含有“.”,因此我们用“_”替换。函数如下:
        /// <summary>
        /// 替换数据表名中的点
        /// </summary>
        /// <param name="FCname"></param>
        /// <returns></returns>
        private string getValidFeatureClassName(string FCname)
        {
            int dot = FCname.IndexOf(".");
            if (dot != -1)
            {
                return FCname.Replace(".", "_");
            }
            return FCname;
        }
 
 
        #endregion
/////////////////////////////////////////////////  分割线 【本博客补充】 ////////////////////////////////////////////////////////////
作一点补充,两种方式打开右键菜单。也可以不创建OpenAttribute.cs类。
或者

TOCControl控件右键显示图层属性

http://blog.sina.com.cn/s/blog_84f7fbbb01013ozt.html


 1 //实现控件的右键菜单项
 2  private void axTOCControl1_OnMouseDown(object sender, ITOCControlEvents_OnMouseDownEvent e)
 3 {
 4     if (e.button != 2) return;
 5     esriTOCControlItem pItem = esriTOCControlItem.esriTOCControlItemNone;
 6     IBasicMap pMap = null;
 7     ILayer pLayer = null;
 8     object unk=null,data=null;
 9     //内容表控件中的这个方法是根据鼠标的点击位置返回内容表中的项
10  axTOCControl1.HitTest(e.x,e.y,ref pItem,ref pMap,ref pLayer,ref unk,ref data);
11  //下面是判断鼠标选中的项是什么类型的项目(通过esriTOCControlItem的枚举值我们可以知道,针对不同的类型项可以添加不同的右键菜单(图层、Map对象、图例对象))
12    if (pItem == esriTOCControlItem.esriTOCControlItemLayer)
13    {
14        /*第一种方法:使用contextMenuStrip控件
15        //下面的这个point是获得鼠标的点击位置。
16        System.Drawing.Point point = new System.Drawing.Point();
17         //设置这个点的位置为鼠标的点击位置
18        point.X = e.x;
19        point.Y = e.y;
20        //显示右键菜单
21        contextMenuStrip1.Show(axTOCControl1, point);
22        show方法的两个参数:一个是右键菜单要关联的控件(或者是要显示右键菜单的控件)。另一个是:鼠标的点击位置
23        //该位置也是右键菜单四个角中,左上的这个位置*/
24        //第二种方法:使用ToolbarMenu
25        IToolbarMenu pToolbarMenu = new ToolbarMenuClass();//创建工具条菜单类实例,相当与创建了一个菜单
26        //给菜单添加项目
27        pToolbarMenu.AddItem(new ControlsMapViewMenuClass () ,-1,-1,false,esriCommandStyles.esriCommandStyleIconAndText);
28        //设置菜单所关联的控件
29        pToolbarMenu.SetHook(axTOCControl1);
30        //根据鼠标的点击位置,弹出菜单
31        pToolbarMenu.PopupMenu(e.x,e.y,axTOCControl1.hWnd);
32    }
33 }

第二位博主的代码

//添加一个上下文菜单,添加一个新的Form窗体,在这个新的窗体上添加GridView控件,并在TOCControl控件的OnMouseDown事件下添加如下代码(pGlobalFeatureLayer是我定义的一个全局变量):
private void axTOCControl1_OnMouseDown(object sender, ESRI.ArcGIS.Controls.ITOCControlEvents_OnMouseDownEvent e)
{

    if (axMapControl1.LayerCount > 0)
    {
        esriTOCControlItem pItem = new esriTOCControlItem();
        pGlobalFeatureLayer = new FeatureLayerClass();
        IBasicMap pBasicMap = new MapClass();
        object pOther = new object();
        object pIndex = new object();
        axTOCControl1.HitTest(e.x, e.y, ref pItem, ref pBasicMap, ref pGlobalFeatureLayer, ref pOther, ref pIndex);
    }
    if (e.button == 2)
    {
        context.Show(axTOCControl1, e.x, e.y);
    }
}
//在上下文菜单的打开属性表的Click事件中添加如下代码:
private void 打开属性表ToolStripMenuItem_Click(object sender, EventArgs e)
{
    FormTable Ft = new FormTable(pGlobalFeatureLayer as IFeatureLayer);

    Ft.Show();

}

//在新的窗体中添加一个将属性表显示到GridView控件中的函数,如下:
public void Itable2Dtable()
{
    IFields pFields;
    pFields = pFeatureLayer.FeatureClass.Fields;

    dtGridView.ColumnCount = pFields.FieldCount;
    for (int i = 0; i < pFields.FieldCount;i++ )
    {
             string  fldName = pFields.get_Field(i).Name;
        dtGridView.Columns[i].Name = fldName;

       dtGridView.Columns[i].ValueType = System.Type.GetType(ParseFieldType(pFields.get_Field(i).Type));
    }         
    IFeatureCursor pFeatureCursor;
    pFeatureCursor = pFeatureLayer.FeatureClass.Search(null, false);
    IFeature pFeature;
    pFeature = pFeatureCursor.NextFeature();
    while (pFeature != null)
    {
        string[] fldValue = new string[pFields.FieldCount];

        for (int i = 0; i < pFields.FieldCount; i++)
        {
            string fldName;
            fldName = pFields.get_Field(i).Name;
            if (fldName==pFeatureLayer .FeatureClass .ShapeFieldName)
            {
                fldValue[i] = Convert.ToString(pFeature.Shape.GeometryType);
            }
            else
                fldValue[i] = Convert.ToString(pFeature.get_Value(i));
        }               
        dtGridView.Rows.Add(fldValue);
        pFeature = pFeatureCursor.NextFeature();
    }
}

 其他可参考 http://blog.csdn.net/zhushuaibing/article/details/40114309

1 //实现控件的右键菜单项
2   private void axTOCControl1_OnMouseDown(object sender, ITOCControlEvents_OnMouseDownEvent e)
3 {
4 if (e.button != 2) return;
5 esriTOCControlItem pItem = esriTOCControlItem.esriTOCControlItemNone;
6 IBasicMap pMap = null;
7 ILayer pLayer = null;
8 object unk=null,data=null;
9 //内容表控件中的这个方法是根据鼠标的点击位置返回内容表中的项
10 axTOCControl1.HitTest(e.x,e.y,ref pItem,ref pMap,ref pLayer,ref unk,ref data);
11 //下面是判断鼠标选中的项是什么类型的项目(通过esriTOCControlItem的枚举值我们可以知道,针对不同的类型项可以添加不同的右键菜单(图层、Map对象、图例对象))
12 if (pItem == esriTOCControlItem.esriTOCControlItemLayer)
13 {
14 /*第一种方法:使用contextMenuStrip控件
15 //下面的这个point是获得鼠标的点击位置。
16 System.Drawing.Point point = new System.Drawing.Point();
17 //设置这个点的位置为鼠标的点击位置
18 point.X = e.x;
19 point.Y = e.y;
20 //显示右键菜单
21 contextMenuStrip1.Show(axTOCControl1, point);
22 show方法的两个参数:一个是右键菜单要关联的控件(或者是要显示右键菜单的控件)。另一个是:鼠标的点击位置
23 //该位置也是右键菜单四个角中,左上的这个位置*/
24
25
26
27 //第二种方法:使用ToolbarMenu
28 IToolbarMenu pToolbarMenu = new ToolbarMenuClass();//创建工具条菜单类实例,相当与创建了一个菜单
29 //给菜单添加项目
30 pToolbarMenu.AddItem(new ControlsMapViewMenuClass () ,-1,-1,false,esriCommandStyles.esriCommandStyleIconAndText);
31 //设置菜单所关联的控件
32 pToolbarMenu.SetHook(axTOCControl1);
33 //根据鼠标的点击位置,弹出菜单
34 pToolbarMenu.PopupMenu(e.x,e.y,axTOCControl1.hWnd);
35
 

原文地址:https://www.cnblogs.com/marvelousone/p/7337566.html