从Flash转C#,很多内容一知半解,边摸索边前进,代码粗糙,权当留个脚印。
只是想得到一个基础的移动和缩放功能的界面,找了很久都是画线、画矩形等基础形状的代码,移动和缩放说的并不清晰,只能自己努力来解决一下。
素材准备:
WPF项目的屏幕上放一个Canvas控件,名称为canvas1。
代码如下:
1 using System; 2 using System.Windows; 3 using System.Windows.Media; 4 using System.Windows.Input; 5 using System.Windows.Shapes; 6 using System.Windows.Controls; 7 8 namespace WpfcanvasDrawing 9 { 10 /// <summary> 11 /// MainWindow.xaml 的交互逻辑 12 /// </summary> 13 public partial class MainWindow : Window 14 { 15 //移动标志 16 bool isMoving = false; 17 //鼠标按下去的位置 18 Point startMovePosition; 19 20 TranslateTransform totalTranslate = new TranslateTransform(); 21 TranslateTransform tempTranslate = new TranslateTransform(); 22 ScaleTransform totalScale = new ScaleTransform(); 23 Double scaleLevel = 1; 24 25 public MainWindow() 26 { 27 InitializeComponent(); 28 29 canvas1.Focusable = true;//重要:默认条件下不接收鼠标事件 30 31 DrawingLine(new Point(100, 100), new Point(300, 200)); 32 DrawingLine(new Point(100, 200), new Point(300, 100)); 33 } 34 35 private void Window_SizeChanged(object sender, SizeChangedEventArgs e) 36 { 37 //问题一:点击窗口最大化按钮时未能改变Canvas尺寸 38 //if (this.WindowState == WindowState.Maximized) {} 39 canvas1.Width = this.Width; 40 canvas1.Height = this.Height; 41 42 } 43 44 protected void DrawingLine(Point startPt, Point endPt) 45 { 46 LineGeometry myLineGeometry = new LineGeometry(); 47 myLineGeometry.StartPoint = startPt; 48 myLineGeometry.EndPoint = endPt; 49 50 Path myPath = new Path(); 51 myPath.Stroke = Brushes.Black; 52 myPath.StrokeThickness = 1; 53 myPath.Data = myLineGeometry; 54 55 canvas1.Children.Add(myPath); 56 } 57 58 private void canvas1_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) 59 { 60 // code A: 61 //FrameworkElement element = sender as FrameworkElement; 62 //startMovePosition = e.GetPosition(element); 63 // code B: 64 startMovePosition = e.GetPosition((Canvas)sender); 65 isMoving = true; 66 } 67 68 private void canvas1_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) 69 { 70 isMoving = false; 71 Point endMovePosition = e.GetPosition((Canvas)sender); 72 73 //为了避免跳跃式的变换,单次有效变化 累加入 totalTranslate中。 74 totalTranslate.X += (endMovePosition.X - startMovePosition.X)/scaleLevel; 75 totalTranslate.Y += (endMovePosition.Y - startMovePosition.Y)/scaleLevel; 76 } 77 78 private void canvas1_MouseMove(object sender, MouseEventArgs e) 79 { 80 if (isMoving) 81 { 82 Point currentMousePosition = e.GetPosition((Canvas)sender);//当前鼠标位置 83 84 Point deltaPt = new Point(0, 0); 85 deltaPt.X = (currentMousePosition.X - startMovePosition.X) /scaleLevel; 86 deltaPt.Y = (currentMousePosition.Y - startMovePosition.Y) /scaleLevel; 87 88 tempTranslate.X = totalTranslate.X + deltaPt.X; 89 tempTranslate.Y = totalTranslate.Y + deltaPt.Y; 90 91 adjustGraph(); 92 } 93 } 94 95 private void canvas1_MouseWheel(object sender, MouseWheelEventArgs e) 96 { 97 Point scaleCenter = e.GetPosition((Canvas)sender); 98 99 if (e.Delta > 0) 100 { 101 scaleLevel *= 1.08; 102 } 103 else 104 { 105 scaleLevel /= 1.08; 106 } 107 //Console.WriteLine("scaleLevel: {0}", scaleLevel); 108 109 totalScale.ScaleX = scaleLevel; 110 totalScale.ScaleY = scaleLevel; 111 totalScale.CenterX = scaleCenter.X; 112 totalScale.CenterY = scaleCenter.Y; 113 114 adjustGraph(); 115 } 116 117 private void adjustGraph() 118 { 119 TransformGroup tfGroup = new TransformGroup(); 120 tfGroup.Children.Add(tempTranslate); 121 tfGroup.Children.Add(totalScale); 122 123 foreach (UIElement ue in canvas1.Children) 124 { 125 ue.RenderTransform = tfGroup; 126 } 127 } 128 129 } 130 }
变量说明:
//移动标志 bool isMoving = false; //鼠标按下去的位置 Point startMovePosition; TranslateTransform totalTranslate = new TranslateTransform();//多次操作中需要对总的移动量进行统计。 TranslateTransform tempTranslate = new TranslateTransform();//单次移动过程中根据鼠标位置实时更新。 ScaleTransform totalScale = new ScaleTransform();//缩放变量 Double scaleLevel = 1;//缩放的级别
函数功能说明:
DrawingLine 在指定的Canvas控件中画线,用于测试。
Window_SizeChanged 屏幕大小变更时,调整Canvas的大小。
鼠标按下时,记录起始移动的位置点,标记拖动操作开始 isMoving = true。
鼠标移动过程中,对位置进行刷新,使用临时变量 tempTranslate 记录当前移动的距离。
鼠标抬起过程中,将有效的移动距离记录到总移动变量 totalTranslate 当中。
鼠标滚轮变化时,根据滚轮方向调整缩放级别。
不同缩放级别下,屏幕中移动相同的距离,对于Canvs内的图形来说距离不同,因此需要对鼠标移动的距离进行修正,即将移动距离除以缩放级别,这样可以得到相对精确的移动位置。
遗留问题:
1、缩放后移动时,仍会有较小的抖动,细节处理上还有瑕疵。
2、窗口最大化按钮点击后,无法捕获相关事件,导致canvas1不能同时放大,请各位高手帮忙指点一下,谢谢!