public delegate void FormClosedEventHandler();
public FormClosedEventHandler frmClosed = null;
public FormMeasureResult()
{
InitializeComponent();
}
public void setLabelText(string text)
{
label2.Text = text;
}
private void FormMeasureResult_FormClosed(object sender, FormClosedEventArgs e)
{
if (frmClosed != null)
frmClosed();
}
引言
Delegate是Dotnet1.0的时候已经存在的特性了,但由于在实际工作中一直没有机会使用Delegate这个特性,所以一直没有对它作整理。这两天,我再度翻阅了一些关于Delegate的资料,并开始正式整理这个C#中著名的特性。本文将由浅入深的谈一下Delegate这个特性。
一.Delegate是什么?
Delegate中文翻译为“委托”。Msdn中对Delegate的解释如下:
C#中的委托类似于C或C++中的函数指针。使用委托使程序员可以将方法引用封装在委托对象内。然后可以将该委托对象传递给可调用所引用方法的代码,而不必在编译时知道将调用哪个方法。与C或C++中的函数指针不同,委托是面向对象、类型安全的,并且是安全的。
如果你是第一次接触Delegate这个概念,你可能会对上面这段文字感觉不知所云,不过不要紧,你可以先把Delegate认为就是一个函数指针。
而当你面对一个虚无的概念时,最好的应对方法就是直接看实例。下面一个简单的Delegate使用例子。
class Program
{
static void OtherClassMethod(){
Console.WriteLine("Delegate an other class's method");
}
static void Main(string[] args)
{
var test = new TestDelegate();
test.delegateMethod = new TestDelegate.DelegateMethod(test.NonStaticMethod);
test.delegateMethod += new TestDelegate.DelegateMethod(TestDelegate.StaticMethod);
test.delegateMethod += Program.OtherClassMethod;
test.RunDelegateMethods();
}
}
class TestDelegate
{
public delegate void DelegateMethod(); //声明了一个Delegate Type
public DelegateMethod delegateMethod; //声明了一个Delegate对象
public static void StaticMethod()
{
Console.WriteLine("Delegate a static method");
}
public void NonStaticMethod()
{
Console.WriteLine("Delegate a non-static method");
}
public void RunDelegateMethods()
{
if(delegateMethod != null){
Console.WriteLine("---------");
delegateMethod.Invoke();
Console.WriteLine("---------");
}
}
}
上面是一个Delegate的使用例子,运行看看结果吧。下面我稍微解释一下:
【1】public delegate void DelegateMethod();这里声明了一个Delegate的类型,名为DelegateMethod,这种Delegate类型可以搭载:返回值为void,无传入参数的函数。
【2】public DelegateMethod delegateMethod;这里声明了一个DelegateMethod的对象(即,声明了某种Delegate类型的对象)。
区分:DelegateMethod是类型,delegateMethod是对象。
【3】为什么上面说Delegate可以看做是函数指针呢?看下面这段代码:
test.delegateMethod = new TestDelegate.DelegateMethod(test.NonStaticMethod);
test.delegateMethod += new TestDelegate.DelegateMethod(TestDelegate.StaticMethod);
test.delegateMethod += Program.OtherClassMethod;
这里delegateMethod搭载了3个函数,而且可以通过调用delegateMethod.Invoke();运行被搭载的函数。这就是Delegate可以看作为函数指针的原因。上面这段代码中,delegateMethod只能搭载:返回值为void,无传入参数的函数(见:NonStaticMethod,StaticMethod,OtherClassMethod的定义),这和Delegate类型声明有关(见DelegateMethod的声明:publicdelegate void DelegateMethod())。
【4】Delegate在搭载多个方法时,可以通过+=增加搭载的函数,也可以通过-=来去掉Delegate中的某个函数。
#region 地图量测
//显示地图量测结果
private FormMeasureResult frmMeasureResult = null;//量算结果窗体
private ESRI.ArcGIS.Display.INewLineFeedback pNewLineFeedback; //追踪线对象
private ESRI.ArcGIS.Display.INewPolygonFeedback pNewPolygonFeedback; //追踪面对象
private ESRI.ArcGIS.Geometry.IPoint pPointpt = null; //鼠标点击点位置
private ESRI.ArcGIS.Geometry.IPoint pMovePoint = null; //鼠标移动点位置
private double dToltalLength = 0.0; //量测总长度
private double dSegmentLength = 0.0; //片段距离
private ESRI.ArcGIS.Geometry.IPointCollection pAreaPointCol = new ESRI.ArcGIS.Geometry.MultipointClass();
private string sMapUnits = "UnKnow";
#endregion
private void axMapControl1_OnMouseMove(object sender, IMapControlEvents2_OnMouseMoveEvent e)
{
sMapUnits = GetMapUnit(axMapControl1.Map.MapUnits);
pMovePoint = (axMapControl1.Map as IActiveView).ScreenDisplay.DisplayTransformation.ToMapPoint(e.x, e.y);//屏幕坐标转换为地图坐标
//距离测量结果实时显示
if (pMouseOperate == "MeasureLength")
{
if (pNewLineFeedback != null)
{
pNewLineFeedback.MoveTo(pMovePoint);
}
double disX = 0.0; //两点之间X差值
double disY = 0.0; //两点之间Y差值
if ((pPointpt != null) && (pNewLineFeedback != null))
{
disX = pMovePoint.X - pPointpt.X;
disY = pMovePoint.Y - pPointpt.Y;
dSegmentLength = Math.Round(Math.Sqrt((disX * disX) + (disY * disY)), 3);
dToltalLength = dToltalLength + dSegmentLength;
if (frmMeasureResult != null)
{
frmMeasureResult.setLabelText(String.Format(
"当前线段长度:{0:.###}{1};\r\n总长度为: {2:.###}{1}",
dSegmentLength, sMapUnits, dToltalLength));
dToltalLength = dToltalLength - dSegmentLength; //鼠标移动到新点重新开始计算
}
frmMeasureResult.frmClosed += new FormMeasureResult.FormClosedEventHandler(frmMeasureResult_frmColsed);
}
}
//面积测量结果实时显示
if(pMouseOperate=="MeasureArea")
{
if(pNewPolygonFeedback!=null)
{
pNewPolygonFeedback.MoveTo(pMovePoint);
}
IPointCollection pPointCol=new Polygon();
IPolygon pPolygon=new PolygonClass();
IGeometry pGeo=null;
ITopologicalOperator pTopo=null;
for(int i=0;i<pAreaPointCol.PointCount;++i)
{
pPointCol.AddPoint(pAreaPointCol.get_Point(i));
}
pPointCol.AddPoint(pMovePoint);
if(pPointCol.PointCount<3) return;
pPolygon=pPointCol as IPolygon;
if(pPolygon!=null)
{
pPolygon.Close();
pGeo=pPolygon as IGeometry;
pTopo= pGeo as ITopologicalOperator;
//使几何图形的拓扑正确
pTopo.Simplify();
pGeo.Project(axMapControl1.Map.SpatialReference);
IArea pArea = pGeo as IArea;
frmMeasureResult.setLabelText( String.Format(
"总面积为:{0:.####}平方{1};\r\n总长度为:{2:.####}{1}",
pArea.Area, sMapUnits, pPolygon.Length));
pPolygon = null;
}
}
}
4、获取当前的距离单位,并将其改为汉字的单位。
private string GetMapUnit(esriUnits _esriMapUnit)
{
string sMapUnits = string.Empty;
switch (_esriMapUnit)
{
case esriUnits.esriCentimeters:
sMapUnits = "厘米";
break;
case esriUnits.esriDecimalDegrees:
sMapUnits = "十进制";
break;
case esriUnits.esriDecimeters:
sMapUnits = "分米";
break;
case esriUnits.esriFeet:
sMapUnits = "尺";
break;
case esriUnits.esriInches:
sMapUnits = "英寸";
break;
case esriUnits.esriKilometers:
sMapUnits = "千米";
break;
case esriUnits.esriMeters:
sMapUnits = "米";
break;
case esriUnits.esriMiles:
sMapUnits = "英里";
break;
case esriUnits.esriMillimeters:
sMapUnits = "毫米";
break;
case esriUnits.esriNauticalMiles:
sMapUnits = "海里";
break;
case esriUnits.esriPoints:
sMapUnits = "点";
break;
case esriUnits.esriUnitsLast:
sMapUnits = "UnitsLast";
break;
case esriUnits.esriUnknownUnits:
sMapUnits = "未知单位";
break;
case esriUnits.esriYards:
sMapUnits = "码";
break;
default:
break;
}
return sMapUnits;
}
5、单击距离计算按钮响应函数
private void MeasureLength_Click(object sender, EventArgs e)
{
axMapControl1.CurrentTool = null;
pMouseOperate = "MeasureLength";
axMapControl1.MousePointer = esriControlsMousePointer.esriPointerCrosshair;
if (frmMeasureResult == null || frmMeasureResult.IsDisposed)
{
frmMeasureResult = new FormMeasureResult();
frmMeasureResult.frmClosed += new FormMeasureResult.FormClosedEventHandler(frmMeasureResult_frmColsed);
frmMeasureResult.Text = "距离量测";
frmMeasureResult.setLabelText("");
frmMeasureResult.Show();
}
else
{
frmMeasureResult.Activate();
}
}
6、双击结束选择,得到最终距离量测结果
private void axMapControl1_OnDoubleClick(object sender, IMapControlEvents2_OnDoubleClickEvent e)
{
if (pMouseOperate == "MeasureLength")
{
if (frmMeasureResult != null)
{
frmMeasureResult.setLabelText("线段总长度为:" + dToltalLength + sMapUnits);
}
if (pNewLineFeedback != null)
{
pNewLineFeedback.Stop();
pNewLineFeedback = null;
//清空所画的线对象
(axMapControl1.Map as IActiveView).PartialRefresh(esriViewDrawPhase.esriViewForeground, null, null);
}
dToltalLength = 0;
dSegmentLength = 0;
}
if(pMouseOperate=="MeasureArea")
{
if (pNewPolygonFeedback != null)
{
pNewPolygonFeedback.Stop();
pNewPolygonFeedback = null;
//清空所画的线对象
(axMapControl1.Map as IActiveView).PartialRefresh(esriViewDrawPhase.esriViewForeground, null, null);
}
pAreaPointCol.RemovePoints(0, pAreaPointCol.PointCount); //清空点集中所有点
}
}
private void MeasureArea_Click(object sender, EventArgs e)
{
axMapControl1.CurrentTool = null;
pMouseOperate = "MeasureArea";
axMapControl1.MousePointer = esriControlsMousePointer.esriPointerCrosshair;
if (frmMeasureResult == null || frmMeasureResult.IsDisposed)
{
frmMeasureResult = new FormMeasureResult();
frmMeasureResult.frmClosed += new FormMeasureResult.FormClosedEventHandler(frmMeasureResult_frmColsed);
frmMeasureResult.setLabelText("");
frmMeasureResult.Text = "面积量测";
frmMeasureResult.Show();
}
else
{
frmMeasureResult.Activate(); //激活窗体
}
}
运行结果: