CCreateLine类实现了ICommand接口,用于描述交互绘制直线段时对鼠标事件的响应。类中需要定义3个局部变量:m_Step记录鼠标左键的单击次数,每单击一次,它的值就增加1;m_Begin和m_End记录直线段的起点和动态变化的终点。
首先是第1次单击鼠标左键的操作,将当前鼠标单击点定义为直线段起点,同时将直线段的终点也初始化为鼠标单击点。然后是移动鼠标时的操作,在后面 MouseMove 方法中描述。
第2次单击鼠标左键时,确定直线段终点的位置,它就是当前单击点aPos的位置。此时,需要首先从屏幕上清除最后一条橡皮线的位置,用拖曳模式重绘它就可以了。然后用正常模式绘制当前位置的直线段, 并将它添加到图元集合类中去。绘制完成以后,要将m_Step的值归0,准备下一条直线段的绘制。
public class CCreateLine:ICommand
{
private int m_Step;
private PointF m_Begin;
private PointF m_End;
public CCreateLine()
{
//
// TODO: 在此处添加构造函数逻辑
//
}
public void LButtonDown(Graphics g,PointF aPos,ArrayList ges,ArrayList geSels){
PointF prePos=new PointF();
//记录鼠标左键的单击次数
m_Step+=1;
switch(m_Step)
{
case 1:
m_Begin=aPos;
m_End=aPos;
break;
case 2:
//重绘并删除前一位置的直线段
prePos=m_Begin;
CLine tempLine=new CLine(m_Begin,m_End);
tempLine.Draw(g,DrawMode.Drag);
tempLine=null;
//绘当前位置的直线段
m_Begin=prePos;
m_End=aPos;
CLine newLine=new CLine(m_Begin,m_End);
newLine.Draw(g,DrawMode.Normal);
ges.Add(newLine);
m_Step=0;
break;
}
}
}
第1次单击鼠标左键后,鼠标在绘图区移动,寻找直线段终点的位置。这个过程用橡皮线描述。绘制橡皮线需要删除前一位置的直线段,并绘制当前位置的直线段,所以要记录直线段终点在前一位置和当前位置的坐标。前一位置的坐标用prePos了象记录,当前位置的坐标用curPos对象记录。直线段终点在前一位置的坐标总是由m_End指定,而在当前位置的坐标总是由鼠标移动结束时光标所处的点aPos指定。所以,首先要将m_End和aPos分别赋给prePos和curPos。有了直线段起点坐标m_Begin和前一位置的终点坐标prePos以后,就可以暂时创建一条直线段,并用拖曳模式绘制它,实际上也就是在屏幕上删除它。由于是暂时使用的直线段,绘完图后注销它,以减少内存消耗。然后绘当前位置的直线段。由于当前直线段的终点在绘制下一位置的直线段时变成了前一位置直线段的终点,所以将curPos赋给m End。
public void MouseMove(Graphics g,PointF aPos)
{
switch(m_Step)
{
case 1:
PointF prePos=new PointF();
PointF curPos=new PointF();
prePos=m_End;
curPos=aPos;
CLine tempLine1=new CLine(m_Begin,prePos);
tempLine1.Draw(g,DrawMode.Drag);
tempLine1=null;
//绘当前位置的直线段
CLine tempLine2=new CLine(m_Begin,curPos);
m_End=curPos;
tempLine2.Draw(g,DrawMode.Drag);
tempLine2=null;
break;
}
}
第1次单击鼠标左键以后,如果发现点的位置有错,或者现在不想绘制它,则通过单击鼠标右键可以取消当前操作。取消操作需要从屏幕上删除最后一条橡皮线,用拖曳模式重绘它,实现删除。完成后将m_Step归0。程序如下:
//单击鼠标右键的绘图行为
public void RButtonDown(Graphics g,PointF aPos)
{
if(m_Step==1)
{
CLine tempLine=new CLine(m_Begin,m_End);
tempLine.Draw(g,DrawMode.Drag);
tempLine=null;
}
m_Step=0;
}