Canvas上批量创建可视对象(DrawingVisual)管理,获取鼠标悬浮图形状态,并控制鼠标右键快捷菜单等...

近期公司有个新的定制,先简要说明下:

窗口上有个播放区域,区域上悬浮了很多可视对象(DrawingVisual),全部是动态生成的....

现在的需求是在这些矩形框上需要添加右键快捷菜单...

 

需求知道了,懂wpf的都知道,DrawingVisual是极其简约的一个视图对象,是没有属性可以绑定鼠标右键菜单,所以我的思路是,在Canvas上绑定快捷菜单,通过鼠标位置判断当前是否在矩形框里面,如果是,则显示对于的菜单,否则就隐藏起来

 

好了,需求和解决方案整理完成,那么就开始吧!

先看下整体效果:

Canvas上批量创建可视对象(DrawingVisual)管理,获取鼠标悬浮图形状态,并控制鼠标右键快捷菜单等..._第1张图片

 1 "DrawingHelper.MainWindow"
 2         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 3         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 4         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
 5         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
 6         xmlns:local="clr-namespace:DrawingHelper"
 7         mc:Ignorable="d"
 8         Title="MainWindow" Height="450" Width="800">
 9 
10     
11         
12 
13             "right">
14                 "默认的" />
15                 "单击框" Style="{DynamicResource item}" Click="MenuItem_Click" />
16             
17 
18             
26             
27         
28     
29     
30         "grid" Margin="10">
31             "canvas" 
32                                 Background="#7d7d7d" 
33                                 ContextMenu="{StaticResource right}"  
34                                 MouseLeftButtonDown="canvas_MouseLeftButtonDown"
35                                 MouseMove="canvas_MouseMove"
36                                 MouseLeftButtonUp="canvas_MouseLeftButtonUp"/>
37         
38 
39         "Horizontal" VerticalAlignment="Top">
40             
UI前段代码
  1 using System;
  2 using System.Collections.Generic;
  3 using System.Diagnostics;
  4 using System.Linq;
  5 using System.Text;
  6 using System.Threading.Tasks;
  7 using System.Windows;
  8 using System.Windows.Controls;
  9 using System.Windows.Data;
 10 using System.Windows.Documents;
 11 using System.Windows.Input;
 12 using System.Windows.Media;
 13 using System.Windows.Media.Imaging;
 14 using System.Windows.Navigation;
 15 using System.Windows.Shapes;
 16 
 17 namespace DrawingHelper
 18 {
 19     /// 
 20     /// MainWindow.xaml 的交互逻辑
 21     /// 
 22     public partial class MainWindow : Window
 23     {
 24         List vsOver = new List();
 25         bool ismove = false;
 26         Visual slectedVisual;
 27         Vector vectorDownOffice;
 28 
 29         public MainWindow()
 30         {
 31             InitializeComponent();
 32 
 33             //注册事件
 34             //EventManager.RegisterClassHandler(typeof(CustomCanvas),
 35             //    CustomCanvas.RightContextMenuOpeningEvent,
 36             //    new RoutedEventHandler(RightContextMenuOpening), true);
 37 
 38             canvas.RightContextMenuOpening += RightContextMenuOpening;
 39         }
 40 
 41         /// 
 42         /// 是否悬浮在框上
 43         /// 
 44         public bool IsOverRect
 45         {
 46             get { return (bool)GetValue(IsOverRectProperty); }
 47             set { SetValue(IsOverRectProperty, value); }
 48         }
 49 
 50         public static readonly DependencyProperty IsOverRectProperty =
 51             DependencyProperty.Register("IsOverRect", typeof(bool), typeof(MainWindow), new PropertyMetadata(false));
 52 
 53         /// 
 54         /// 单击生成
 55         /// 
 56         /// 
 57         /// 
 58         private void Button_Click(object sender, RoutedEventArgs e)
 59         {
 60             Rect rect = new Rect();
 61             rect.Size = new Size(100, 100);
 62 
 63             Random r = new Random(DateTime.Now.Millisecond);
 64             var x = r.Next(0, (int)(canvas.ActualWidth - rect.Size.Width));
 65             var y = r.Next(0, (int)(canvas.ActualHeight - rect.Size.Width));
 66 
 67             rect.Location = new Point(x, y);
 68 
 69             canvas.AddVisual(rect);
 70         }
 71 
 72         /// 
 73         /// 单击鼠标悬浮的框时
 74         /// 
 75         /// 
 76         /// 
 77         private void MenuItem_Click(object sender, RoutedEventArgs e)
 78         {
 79             MessageBox.Show($"当前选中:{vsOver.Count}");
 80         }
 81 
 82         /// 
 83         /// 左键被按下时
 84         /// 
 85         /// 
 86         /// 
 87         private void canvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
 88         {
 89             ismove = true;
 90             var point = e.GetPosition(canvas);
 91 
 92             var vs = canvas.GetVisualByPoint(point);
 93             slectedVisual = vs.FirstOrDefault();
 94 
 95             if (slectedVisual is DrawingVisual drawing)
 96             {
 97                 vectorDownOffice = point - drawing.Drawing.Bounds.Location;
 98             }
 99         }
100 
101         /// 
102         /// 移动时
103         /// 
104         /// 
105         /// 
106         private void canvas_MouseMove(object sender, MouseEventArgs e)
107         {
108             if (ismove && slectedVisual != null)
109             {
110                 var point = e.GetPosition(canvas) - vectorDownOffice;
111 
112                 Rect rect = new Rect();
113                 rect.Size = new Size(100, 100);
114                 rect.X = point.X;
115                 rect.Y = point.Y;
116 
117                 canvas.MoveVisual(slectedVisual, rect);
118             }
119         }
120 
121         /// 
122         /// 左键被抬起时
123         /// 
124         /// 
125         /// 
126         private void canvas_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
127         {
128             ismove = false;
129             slectedVisual = null;
130         }
131 
132         /// 
133         /// 快捷菜单打开之前
134         /// 
135         /// 
136         /// 
137         void RightContextMenuOpening(object sender, RoutedEventArgs e)
138         {
139             //获取相对面板的位置
140             var point = Mouse.GetPosition(canvas);
141 
142             var vs = canvas.GetVisualByPoint(point);
143             vsOver = new List(vs);
144 
145             IsOverRect = vs.Length > 0;
146         }
147     }
148 
149 }
UI后端代码
  1 using System;
  2 using System.Collections.Generic;
  3 using System.Linq;
  4 using System.Text;
  5 using System.Threading.Tasks;
  6 using System.Windows;
  7 using System.Windows.Controls;
  8 using System.Windows.Media;
  9 
 10 namespace DrawingHelper
 11 {
 12     /// 
 13     /// 自定义面板
 14     /// 
 15     class CustomCanvas : Canvas
 16     {
 17         /// 
 18         /// 透明度
 19         /// 
 20         double opacity = 0.8;
 21 
 22         public CustomCanvas()
 23         {
 24             ContextMenuOpening += CustomCanvas_ContextMenuOpening;
 25         }
 26 
 27         /// 
 28         /// 菜单打开之前
 29         /// 
 30         /// 
 31         /// 
 32         private void CustomCanvas_ContextMenuOpening(object sender, ContextMenuEventArgs e)
 33         {
 34             //RaiseEvent(new RoutedEventArgs(RightContextMenuOpeningEvent, e));//事件推送
 35 
 36             RightContextMenuOpening?.Invoke(this, e);
 37         }
 38 
 39         /*
 40         /// 
 41         /// 声明自定义事件
 42         /// 
 43         public static readonly RoutedEvent RightContextMenuOpeningEvent =
 44             EventManager.RegisterRoutedEvent(
 45                             "RightContextMenuOpeningEvent",
 46                             RoutingStrategy.Direct,
 47                             typeof(EventHandler),
 48                             typeof(CustomCanvas));
 49 
 50         /// 
 51         /// Raised when the VideoCellContextMenuOpeningEvent changed.
 52         /// 
 53         public event RoutedEventHandler RightContextMenuOpening
 54         {
 55             add { AddHandler(RightContextMenuOpeningEvent, value); }
 56             remove { RemoveHandler(RightContextMenuOpeningEvent, value); }
 57         }
 58         */
 59 
 60         /// 
 61         /// 右键菜单打开之前
 62         /// 
 63         public event EventHandler RightContextMenuOpening;
 64 
 65         /// 
 66         /// 当前所有的图形
 67         /// 
 68         List vs = new List();
 69 
 70         /// 
 71         /// 边框画刷
 72         /// 
 73         Pen pen = new Pen(new SolidColorBrush(Colors.Black), 2);
 74 
 75         /// 
 76         /// 添加个图形
 77         /// 
 78         /// 
 79         public void AddVisual(Rect rect)
 80         {
 81             DrawingVisual dv = new DrawingVisual();
 82 
 83             using (var drawingContext = dv.RenderOpen())
 84             {
 85                 drawingContext.PushOpacity(opacity);
 86                 drawingContext.DrawRectangle(null, pen, rect);
 87             }
 88 
 89             vs.Add(dv);
 90 
 91             this.AddVisualChild(dv);
 92             this.AddLogicalChild(dv);
 93         }
 94 
 95         /// 
 96         /// 图形总数
 97         /// 
 98         protected override int VisualChildrenCount => vs.Count;
 99 
100         /// 
101         /// 
102         /// 
103         /// 
104         /// 
105         protected override Visual GetVisualChild(int index)
106         {
107             return vs[index];
108         }
109 
110         /// 
111         /// 根据坐标返回图形
112         /// 
113         /// 
114         /// 
115         public Visual[] GetVisualByPoint(Point point)
116         {
117             List vis = new List();
118             vs.ForEach(c =>
119             {
120                 if (c is DrawingVisual dv)
121                 {
122                     var dr = dv.Drawing;
123 
124                     var x = dr.Bounds.X;
125                     var y = dr.Bounds.Y;
126                     var w = dr.Bounds.Width;
127                     var h = dr.Bounds.Height;
128 
129                     if (point.X >= x && point.X <= x + w && point.Y >= y && point.Y <= y + h)
130                     {
131                         vis.Add(c);
132                     }
133                 }
134             });
135             return vis.ToArray();
136         }
137 
138         /// 
139         /// 移动指定的
140         /// 
141         /// 
142         /// 
143         public void MoveVisual(Visual visual, Rect rect)
144         {
145             if (visual is DrawingVisual drawing)
146             {
147                 using (var dc = drawing.RenderOpen())
148                 {
149                     dc.PushOpacity(opacity);
150                     dc.DrawRectangle(null, pen, rect);
151                 }
152             }
153         }
154     }
155 }
CustomCanvas 扩展类

有需要的朋友,也可以移步下载:点击下载

你可能感兴趣的:(Canvas上批量创建可视对象(DrawingVisual)管理,获取鼠标悬浮图形状态,并控制鼠标右键快捷菜单等...)