Silverlight中实现自定义Cursor

Silverlight不同于WPF,自定义Cursor需要通过其它方式实现。我们可以为一个元素定义一个CursorBehavior,建议使用自定义Cursor的Panel为Canvas,否则需要对自定义的Cursor做TranslateTransform。附件Behavior的时候,为Canvas添加一个Image元素,默认Visibility为Collapsed。Image元素的ZIndex值要较大,这样可以确保始终在其它元素前面。订阅Canvas的MouseMove和MouseLeave事件,MouseMove事件产生后用来定位Image的坐标,而MouseLeave事件产生后用来隐藏Image。CursorBehavior的ContentPropertyAttribute的Name为Cursor便于在XAML中声明:

<localcontrols:Tablet x:Name=”tablet”
              Background=”Transparent”
              ItemWidth=”40″
              ItemHeight=”40″>
  <interactivity:BehaviorService.Behavior>
    <interactivity:BehaviorGroup>
      <interactivity:CursorBehavior Cursor=”{StaticResource PenCursor}”
                         CursorWidth=”19″
                         CursorHeight=”20″ />
      </interactivity:BehaviorGroup>
  </interactivity:BehaviorService.Behavior>
</localcontrols:Tablet>

新增一个CursorService的静态类用来GetCursor、SetCursor,由于CursorBehavior的Cursor属性在产生变化的时候会产生OnCursorChanged以更新Image的Source属性。

  1 using System.Windows.ComponentModel;
  2 using System.Windows.Controls;
  3 using System.Windows.Input;
  4 using System.Windows.Markup;
  5 using System.Windows.Media;
  6 
  7 namespace System.Windows.Interactivity
  8 {
  9   /// <summary>
 10   /// 光标行为
 11   /// </summary>
 12   [ContentProperty("Cursor")]
 13   public sealed class CursorBehavior : MouseBehavior
 14   {
 15     /// <summary>
 16     /// 原缓存模式
 17     /// </summary>
 18     private CacheMode m_oldCacheMode;
 19     /// <summary>
 20     /// 原光标
 21     /// </summary>
 22     private Cursor m_oldCursor;
 23     /// <summary>
 24     /// 光标
 25     /// </summary>
 26     private Object m_cursor;
 27     /// <summary>
 28     /// 光标图片
 29     /// </summary>
 30     private Image m_cursorImage;
 31 
 32     /// <summary>
 33     /// 构造函数
 34     /// </summary>
 35     public CursorBehavior() { }
 36 
 37     /// <summary>
 38     /// 画布
 39     /// </summary>
 40     public Canvas Drawing
 41     {
 42       get
 43       {
 44         return (this.AssociatedObject as Canvas);
 45       }
 46     }
 47 
 48     /// <summary>
 49     /// 光标宽度
 50     /// </summary>
 51     public Double CursorWidth { get; set; }
 52 
 53     /// <summary>
 54     /// 光标高度
 55     /// </summary>
 56     public Double CursorHeight { get; set; }
 57 
 58     /// <summary>
 59     /// 鼠标
 60     /// </summary>
 61     public Object Cursor
 62     {
 63       get { return m_cursor; }
 64       set
 65       {
 66         if (m_cursor != value)
 67         {
 68           m_cursor = value;
 69 
 70           OnPropertyChanged(this, p => p.Cursor);
 71           OnCursorChanged(EventArgs.Empty);
 72         }
 73       }
 74     }
 75 
 76     /// <summary>
 77     /// 附加
 78     /// </summary>
 79     protected override void OnAttached()
 80     {
 81       base.OnAttached();
 82 
 83       Canvas canvas = this.Drawing;
 84       if ((canvas.CacheMode == null) || (canvas.CacheMode.GetType() != typeof(BitmapCache)))
 85       {
 86         m_oldCacheMode = canvas.CacheMode;
 87         canvas.CacheMode = new BitmapCache();
 88       }
 89 
 90       m_oldCursor = canvas.Cursor;
 91       canvas.Cursor = Cursors.None;
 92       m_cursorImage = new Image();
 93       m_cursorImage.Visibility = Visibility.Collapsed;
 94       m_cursorImage.Width = this.CursorWidth;
 95       m_cursorImage.Height = this.CursorHeight;
 96 
 97       OnCursorChanged(EventArgs.Empty);
 98       Canvas.SetZIndex(m_cursorImage, Int16.MaxValue);
 99       canvas.Children.Add(m_cursorImage);
100     }
101 
102     /// <summary>
103     /// 分离
104     /// </summary>
105     protected override void OnDetach()
106     {
107       base.OnDetach();
108 
109       Canvas canvas = this.Drawing;
110 
111       if (m_oldCacheMode != null)
112         canvas.CacheMode = m_oldCacheMode;
113 
114       canvas.Cursor = m_oldCursor;
115 
116       canvas.Children.Remove(m_cursorImage);
117     }
118 
119     /// <summary>
120     /// 鼠标离开
121     /// </summary>
122     /// <param name=”e”>事件参数</param>
123     protected override void OnMouseLeave(MouseEventArgs2 e)
124     {
125       m_cursorImage.Visibility = Visibility.Collapsed;
126     }
127 
128     /// <summary>
129     /// 鼠标移动
130     /// </summary>
131     /// <param name=”e”>事件参数</param>
132     protected override void OnMouseMove(MouseEventArgs2 e)
133     {
134       if (m_cursorImage.Visibility == Visibility.Collapsed)
135         m_cursorImage.Visibility = Visibility.Visible;
136 
137       Point pos = e.GetPosition(this.Drawing);
138 
139       Canvas.SetLeft(m_cursorImage, pos.X);
140       Canvas.SetTop(m_cursorImage, pos.Y – m_cursorImage.ActualHeight);
141     }
142 
143     /// <summary>
144     /// 鼠标变化
145     /// </summary>
146     /// <param name=”e”>事件参数</param>
147     private void OnCursorChanged(EventArgs e)
148     {
149       if (m_cursorImage != null)
150         m_cursorImage.Source = (this.Cursor as ImageSource);
151     }
152   }
153 }
 1 using System.Linq;
 2 
 3 namespace System.Windows.Interactivity
 4 {
 5   /// <summary>
 6   /// 光标服务
 7   /// </summary>
 8   public static class CursorService
 9   {
10     /// <summary>
11     /// 获得光标
12     /// </summary>
13     /// <param name=”d”>对象</param>
14     /// <returns>光标</returns>
15     public static Object GetCursor(DependencyObject d)
16     {
17       CursorBehavior cursorBehavior = GetBehavior(d);
18 
19       if (cursorBehavior != null)
20         return cursorBehavior.Cursor;
21 
22       return null;
23     }
24 
25     /// <summary>
26     /// 设置光标
27     /// </summary>
28     /// <param name=”d”>对象</param>
29     /// <param name=”value”>光标</param>
30     public static void SetCursor(DependencyObject d, Object value)
31     {
32       CursorBehavior cursorBehavior = GetBehavior(d);
33 
34       if (cursorBehavior != null)
35         cursorBehavior.Cursor = value;
36     }
37 
38     /// <summary>
39     /// 获取行为
40     /// </summary>
41     /// <param name=”d”>对象</param>
42     /// <returns>光标行为</returns>
43     private static CursorBehavior GetBehavior(DependencyObject d)
44     {
45       BehaviorBase behavior = BehaviorService.GetBehavior(d);
46       CursorBehavior cursorBehavior = (behavior as CursorBehavior);
47 
48       if (cursorBehavior == null)
49       {
50         BehaviorGroup group = (behavior as BehaviorGroup);
51 
52         cursorBehavior = group.Children.OfType<CursorBehavior>().FirstOrDefault();
53       }
54 
55       return cursorBehavior;
56     }
57   }
58 }
posted @ 2012-08-11 11:06  junchu25  阅读(597)  评论(0编辑  收藏  举报