Extensions in UWP Community Toolkit - Mouse Cursor
概述
UWP Community Toolkit Extensions 中有一个为 Mouse 提供的扩展 - Mouse Cursor Extensions,本篇我们结合代码详细讲解 Mouse Cursor Extensions 的实现。
Mouse Cursor Extensions 为 Framework element 提供了一种简单的设置鼠标悬浮时样式的方法,让开发者可以更容易的通过鼠标状态体现每个 Framework element 的状态。接下来看看官方示例的截图:
Doc: https://docs.microsoft.com/zh-cn/windows/uwpcommunitytoolkit/extensions/mousecursor
Namespace: Microsoft.Toolkit.Uwp.UI.Extensions; Nuget: Microsoft.Toolkit.Uwp.UI;
开发过程
代码分析
Mouse Cursor Extensions 的功能实现比较简单,在 Mouse.cs 类中;先看一下类的结构:
我们看到,类中定义了一个依赖属性:
Cursor - 光标属性,标记了 Framework element 对应的光标,默认值是 Arrow 光标,变化时触发 CursorChanged 事件;
获取和设置的方法是 GetCursor(FrameworkElement element) 和 SetCursor(FrameworkElement element, CoreCursorType value);根据 element 获取光标,和根据 element 设置光标;
除此之外,类中还定义了几个 static readonly 的变量:
_cursorLock - 为保证 cursor 的创建和处理是原子的,所以需要加锁
_defaultCursor - CoreCursor 类型,记录了鼠标进入 element 前的样式,这样可以在鼠标移出后恢复为原有样式;
_cursors - Dictionary 类型,记录了 element 间的光标类型和光标的键值对,在切换 element 时,根据这个值确定应该显示什么光标样式;
其中 CoreCursorType 是一个枚举类型,包括:
Arrow = 0, Cross = 1, Custom = 2, Hand = 3, Help = 4, IBeam = 5, SizeAll = 6, SizeNortheastSouthwest = 7, SizeNorthSouth = 8, SizeNorthwestSoutheast = 9, SizeWestEast = 10, UniversalNo = 11, UpArrow = 12, Wait = 13, Pin = 14, Person = 15
CoreCursorType 和 CoreCursor 都在 Windows.UI.Core 中,大家可以在这个 namespace 中详细查看,或者在 https://docs.microsoft.com/en-us/uwp/api/Windows.UI.Core.CoreCursor 中查看。
CursorChanged 事件的处理方法如下:
把 newValue 加入到 _cursors 字典中,用于 element 切换时获取对应的 Cursor,然后为 element 绑定 PointerEntered,PointerExited,Unloaded 事件。
private static void CursorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var element = d as FrameworkElement; if (element == null) { throw new NullReferenceException(nameof(element)); } var value = (CoreCursorType)e.NewValue; // lock ensures CoreCursor creation and event handlers attachment/detachment is atomic lock (_cursorLock) { if (!_cursors.ContainsKey(value)) { _cursors[value] = new CoreCursor(value, 1); } // make sure event handlers are not attached twice to element element.PointerEntered -= Element_PointerEntered; element.PointerEntered += Element_PointerEntered; element.PointerExited -= Element_PointerExited; element.PointerExited += Element_PointerExited; element.Unloaded -= ElementOnUnloaded; element.Unloaded += ElementOnUnloaded; } }
分别看一下这三个事件的处理方法:
Element_PointerEntered(s, e) 的处理就是通过 GetCursor(element) 方法获取 CoreCursorType,在 _cursors 字典中获取对应的光标,设置给 Window.Current.CoreWindow.PointerCursor;
private static void Element_PointerEntered(object sender, PointerRoutedEventArgs e) { CoreCursorType cursor = GetCursor((FrameworkElement)sender); Window.Current.CoreWindow.PointerCursor = _cursors[cursor]; }
Element_PointerExited(s, e) 的处理是判断光标移出后,新移入的元素是否为 Framework element,如果是,则获取它对应的 Cursor;如果不是,则恢复为默认的 Cursor;
private static void Element_PointerExited(object sender, PointerRoutedEventArgs e) { // when exiting change the cursor to the target Mouse.Cursor value of the new element CoreCursor cursor; if (e.OriginalSource is FrameworkElement newElement) { cursor = _cursors[GetCursor(newElement)]; } else { cursor = _defaultCursor; } Window.Current.CoreWindow.PointerCursor = cursor; }
ElementOnUnloaded(s, e) 的处理,就是把 Cursor 设置为默认值;
private static void ElementOnUnloaded(object sender, RoutedEventArgs routedEventArgs) { // when the element is programatically unloaded, reset the cursor back to default // this is necessary when click triggers immediate change in layout and PointerExited is not called Window.Current.CoreWindow.PointerCursor = _defaultCursor; }
调用示例
我们创建了两个按钮,Cursor 分别设置为 UniversalNo 和 Wait,可以看到光标分别进入这两个按钮时的显示,已经光标离开进去空白处时的显示,和预期是一致的;
<StackPanel Orientation="Horizontal" Padding="20"> <Button Content="Disabled" Width="200" extensions:Mouse.Cursor="UniversalNo"/> <Button Content="Loading" Width="200" extensions:Mouse.Cursor="Wait"/></StackPanel>
总结
到这里我们就把 UWP Community Toolkit Extensions 中的 Mouse Cursor Extensions 的源代码实现过程和简单的调用示例讲解完成了,希望能对大家更好的理解和使用这个扩展有所帮助。欢迎大家多多交流,谢谢!
最后,再跟大家安利一下 UWPCommunityToolkit 的官方微博:https://weibo.com/u/6506046490, 大家可以通过微博关注最新动态。
衷心感谢 UWPCommunityToolkit 的作者们杰出的工作,Thank you so much, UWPCommunityToolkit authors!!!
- 点赞
- 收藏
- 关注作者
评论(0)