using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace TestShapeControl { public partial class Form5 : Form { //mousedown start pos private int sx, sy; //count the number of times the movemove event is fired private int num_mousemove = 0; //sampling interval, record the coordinate after this number of mousemove private int sampling_interval = 1; //record the trail of the mousemove private string str_trail = ""; //animation delay per frame in ms; private int animation_delay = 0; public Form5() { InitializeComponent(); } private void ctrl1_MouseDown(object sender, MouseEventArgs e) { if (e.Button.Equals(MouseButtons.Left)) { sx = e.X; sy = e.Y; } } private void ctrl1_MouseMove(object sender, MouseEventArgs e) { if (e.Button.Equals(MouseButtons.Left)) { //num_mousemove is reset to 0 at each sampling interval num_mousemove = (num_mousemove + 1) % sampling_interval ; //we record the mouse cooridinate at each sampling interval //when num_mousemove is reset to 0 if (num_mousemove == 0) { int w=((Control)sender).Width; int h=((Control)sender).Height; int lastx=((Control)sender).Left + w/2 ; int lasty = ((Control)sender).Top +h/2; ((Control)sender).Left = ((Control)sender).Left + (e.X - sx); ((Control)sender).Top = ((Control)sender).Top + (e.Y - sy); ((Control)sender).Refresh(); Graphics.FromImage(this.panel1.BackgroundImage).DrawLine(new Pen(Color.White, 3), new Point(lastx, lasty), new Point(((Control)sender).Left + w / 2, ((Control)sender).Top + h / 2)); this.Refresh(); str_trail += lastx + "," + lasty + "|"; } } } private void ResetPanelBackground() { object o = global::TestShapeControl.Properties.Resources.ResourceManager.GetObject("bluesky"); this.panel1.BackgroundImage = new Bitmap(this.Width, this.Height, System.Drawing.Imaging.PixelFormat.Format24bppRgb); Graphics.FromImage(this.panel1.BackgroundImage).DrawImage((Bitmap)o, new Rectangle(0, 0, panel1.Width, panel1.Height), new Rectangle(0, 0, ((Bitmap)o).Width, ((Bitmap)o).Height), GraphicsUnit.Pixel); //uncomment line below if you just want a plane background // Graphics.FromImage(this.panel1.BackgroundImage).FillRectangle(new SolidBrush(Color.Green), 0, 0, this.Width, this.Height); string s="Drag the red dot on the aeroplane around the image to map out a trail for the areoplane.\nDouble click on red dot to start animation."; Graphics.FromImage(this.panel1.BackgroundImage).DrawString(s, new Font(FontFamily.GenericSansSerif,14,FontStyle.Bold), new SolidBrush(Color.White), 0, 0); } private void Form5_Load(object sender, EventArgs e) { this.panel1.Width = this.Width; this.panel1.Height = this.Height; this.panel1.Top =0; this.panel1.Left =0; this.DoubleBuffered = true; //invoke double buffer typeof(Panel).InvokeMember( "DoubleBuffered", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.SetProperty, null, panel1, new object[] { true }); ResetPanelBackground(); } private double RadianToDegree(double angle) { return angle * (180.0 / Math.PI); } //Land the butterfly private void Land(Point p0) { ctrlPlane.Left = p0.X - ctrlPlane.Width / 2; ctrlPlane.Top = p0.Y - ctrlPlane.Height / 2; ctrlPlane.Refresh(); } //Move the butterfly, changing it orientation private void Fly(Point p0, Point p1) { //calculate the angle to rotate so that the butterfly //will be in the correct orientation as the direction //of flight double deltaX=(p1.X - p0.X); double deltaY=(p1.Y - p0.Y); //may not be necessary as Atan2 function probably handle div by 0 //double epsilon = 0.00001f; //if (Math.Abs(deltaX) < epsilon && Math.Abs(deltaY) < epsilon) // return; double theta= Math.Atan2(deltaY,deltaX ); //if (theta == double.NaN) // return; double angle = RadianToDegree(theta); //redefine angle to be between -180 and 180 if (angle > 180) angle = angle - 360; else { if (angle < -180) angle = 360 + angle; } // System.Diagnostics.Debug.Print(""+ theta +"-->" + angle); //set the min angle change int deltaAngle = (int)Math.Abs(angle - ctrlPlane.ShapeImageRotation); if(deltaAngle>=5) ctrlPlane.ShapeImageRotation = (int)angle; //set the position and orientation of the butterfly ctrlPlane.Left = p0.X - ctrlPlane.Width / 2; ctrlPlane.Top = p0.Y - ctrlPlane.Height / 2; ctrlPlane.Refresh(); } //trace out the trail, moving the plane along it private void TraceTrail() { if(str_trail =="") return; ResetPanelBackground(); //note that v[v.Length-1], the last split part is always "" //as str_trail always end with "|" because we append "|" //after each set of x,y coordinates to str_trail in the mousemove event handler var v = str_trail.Split('|'); //we need at lest 5 points if (v.Length < 5) return; var v1=v[0].Split(','); //default dummy values for init purposes var v2 = v1; var v3 = v1; //p0 is start of trail segment Point p0 = new Point(int.Parse(v1[0]),int.Parse(v1[1])); Point p1 = Point.Empty;// new Point(int.Parse(v2[0]), int.Parse(v2[1])); Point p2 = Point.Empty; // new Point(int.Parse(v3[0]), int.Parse(v3[1])); //p3 is end of trail segment Point p3 = Point.Empty; for (int i = 1; i < v.Length - 4; i++) { v1= v[i].Split(','); v2 = v[i + 1].Split(','); v3 = v[i + 2].Split(','); p1 = new Point(int.Parse(v1[0]), int.Parse(v1[1])); p2 = new Point(int.Parse(v2[0]), int.Parse(v2[1])); p3 = new Point(int.Parse(v3[0]), int.Parse(v3[1])); Fly(p0, p3); //move to the next point p0 = new Point(p1.X, p1.Y); this.panel1.Refresh(); //manage the speed of animation System.Threading.Thread.Sleep(animation_delay); } Land(p1); //clear the trail str_trail = ""; } private void ctrl1_DoubleClick(object sender, EventArgs e) { TraceTrail(); } } }