Silverlight 自定义鼠标

本文介绍了一种在Silverlight项目中实现自定义鼠标样式的方法,通过创建图像跟随鼠标移动来模拟不同形状的光标,如手形和抓形。文章提供了具体的实现代码,并讨论了在元素嵌套情况下如何正确应用自定义鼠标的解决方案。

在现在的Silverlight项目中,客户要求鼠标在可拖动面板上时为手形,拖动时为抓形。无奈Silverlight还不支持这个,只能自动动手做了。

自定义鼠标的思路就是把原始鼠标隐藏,然后做一个图片,跟着鼠标的位置移动,并在事件中改变图片,就是我们想要的自定义鼠标效果了。这个东西说起来简单,做起来并不那么容易,思路总是不容易理清。特别是嵌套元素都自定义了鼠标样式时,到底取谁的样式就成了一个问题了,还要考虑效率问题。

参考了网上两篇文章:

http://www.codeproject.com/KB/silverlight/SilverlightCustomCursors.aspx

http://www.cnblogs.com/dino623/archive/2010/04/01/1702260.html

看了codeproject上的那篇文章,发现在我们的项目中很合适,主要是简单。 就是有些bug,比如在程序中改变鼠标样式都不行,嵌套元素就出问题。 嵌套的问题当然是取最上层的那个元素了。主要代码如下:

ContractedBlock.gif ExpandedBlockStart.gif View Code

   
public class CursorSet
{
const string ImagePath = " /Resources/Cursors/ " ;

internal static Point ? mousePoint;
internal static Popup Popup;
internal static Canvas AdornerLayer;
internal static List < string > IDs;
internal static Dictionary < FrameworkElement, ContentControl > ActiveElements;
internal static UIElement currentElement;
internal static Point currentPoint;

#region public string ID (attached)

public static string GetID(DependencyObject d)
{
return ( string )d.GetValue(IDProperty);
}

public static void SetID(DependencyObject d, string id)
{
d.SetValue(IDProperty, id);
}

public static readonly DependencyProperty IDProperty = DependencyProperty.RegisterAttached(
" ID " ,
typeof ( string ),
typeof (CursorSet),
new PropertyMetadata( new PropertyChangedCallback(OnIDPropertyChanged)));

static void OnIDPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
FrameworkElement element
= d as FrameworkElement;
string oldId = e.OldValue as string ;
string newId = e.NewValue as string ;
Cursor cursor;

if (e.OldValue != null )
{
AdornerLayer.Children.Clear();
}

if (IsValidID(newId))
{
if (IsSystemType(newId, out cursor))
{
element.Cursor
= cursor;
if (ActiveElements.ContainsKey(element))
ActiveElements[element]
= null ;
else
{
ActiveElements.Add(element,
null );
AddMouseEventHandlers(element);
}
}
else
{
ContentControl customCursor
= CreateControl(newId);
if (ActiveElements.ContainsKey(element))
ActiveElements[element]
= customCursor;
else
{
ActiveElements.Add(element, customCursor);
AddMouseEventHandlers(element);
}

if (mousePoint.HasValue)
{
ShowCursor(element, mousePoint.Value);
}
}
}
else
{
element.Cursor
= null ;
RemoveMouseEventHandlers(element);
if (ActiveElements.ContainsKey(element))
ActiveElements.Remove(element);
}
}

#endregion

static CursorSet()
{
IDs
= new List < string > ();
ActiveElements
= new Dictionary < FrameworkElement, ContentControl > ();

IDs.Add(
" Cross " );
IDs.Add(
" SizeAll " );
IDs.Add(
" Fist " );
IDs.Add(
" Palm " );

Application.Current.Host.Content.Resized
+= OnContentResized;
}

static ContentControl CreateControl( string id)
{
if ( string .IsNullOrEmpty(id) || IDs == null || ! IDs.Contains(id))
return new ContentControl();

Image image
= new Image()
{
Margin
= new Thickness( - 12 , - 12 , 0 , 0 ),
Source
= new BitmapImage(
new Uri( string .Format( " /{0};component{1}{2}.png " , typeof (CursorSet).Namespace, ImagePath, id), UriKind.Relative))
};

Canvas canvas
= new Canvas();
canvas.Children.Add(image);

return new ContentControl { Content = canvas };
}

static bool IsValidID( string id)
{
Cursor cursor;

if (IsSystemType(id, out cursor))
return true ;

return IDs.Contains(id);
}

static bool IsSystemType( string id, out Cursor cursor)
{
cursor
= null ;

if ( string .IsNullOrEmpty(id))
return true ;

switch (id)
{
case " Arrow " :
cursor
= Cursors.Arrow;
return true ;
case " Eraser " :
cursor
= Cursors.Eraser;
return true ;
case " Hand " :
cursor
= Cursors.Hand;
return true ;
case " IBeam " :
cursor
= Cursors.IBeam;
return true ;
case " None " :
cursor
= Cursors.None;
return true ;
case " SizeNS " :
cursor
= Cursors.SizeNS;
return true ;
case " SizeWE " :
cursor
= Cursors.SizeWE;
return true ;
case " Stylus " :
cursor
= Cursors.Stylus;
return true ;
case " Wait " :
cursor
= Cursors.Wait;
return true ;
}

return false ;
}

static void OnContentResized( object sender, EventArgs e)
{
if (AdornerLayer != null )
{
AdornerLayer.Width
= Application.Current.Host.Content.ActualWidth;
AdornerLayer.Height
= Application.Current.Host.Content.ActualHeight;
}
}

static void EnsurePopup()
{
if (Popup == null || AdornerLayer == null )
{
AdornerLayer
= new Canvas()
{
IsHitTestVisible
= false ,
Width
= Application.Current.Host.Content.ActualWidth,
Height
= Application.Current.Host.Content.ActualHeight
};

Popup
= new Popup
{
IsHitTestVisible
= false ,
Child
= AdornerLayer
};
}
}

static void AddMouseEventHandlers(FrameworkElement element)
{
element.MouseEnter
+= OnElementMouseEnter;
element.MouseMove
+= OnElementMouseMove;
element.MouseLeave
+= OnElementMouseLeave;
}

static void RemoveMouseEventHandlers(FrameworkElement element)
{
element.MouseEnter
-= OnElementMouseEnter;
element.MouseMove
-= OnElementMouseMove;
element.MouseLeave
-= OnElementMouseLeave;
}

static void OnElementMouseEnter( object sender, MouseEventArgs e)
{
ShowCursor(sender
as FrameworkElement, e.GetPosition( null ));
}

static void OnElementMouseMove( object sender, MouseEventArgs e)
{
FrameworkElement element
= sender as FrameworkElement;
Point newPoint
= e.GetPosition( null );
// Debug.WriteLine(string.Format("{0}:{1} - {2}", element.Name, CursorSet.GetID(element), newPoint));

if (newPoint != currentPoint)
{
currentPoint
= newPoint;
currentElement
= VisualTreeHelper.FindElementsInHostCoordinates(newPoint, element).Where(f => { return ! string .IsNullOrEmpty(CursorSet.GetID(f)); }).FirstOrDefault();
}

if (currentElement == element)
{
ShowCursor(element, newPoint);
}
}

static void OnElementMouseLeave( object sender, MouseEventArgs e)
{
FrameworkElement element
= sender as FrameworkElement;
ContentControl control
= ActiveElements[element];
if (control == null ) return ;

element.Cursor
= null ;
AdornerLayer.Children.Remove(control);

Popup.IsOpen
= false ;
mousePoint
= null ;
}

static void ShowCursor(FrameworkElement element, Point point)
{
ContentControl customCursor
= ActiveElements[element];
if (customCursor == null ) return ;

EnsurePopup();
element.Cursor
= Cursors.None;
if ( ! AdornerLayer.Children.Contains(customCursor))
{
AdornerLayer.Children.Clear();
AdornerLayer.Children.Add(customCursor);
}

Canvas.SetTop(customCursor, point.Y);
Canvas.SetLeft(customCursor, point.X);

Popup.IsOpen
= true ;
mousePoint
= point;
}
}

不知道博客园的silveright demo 是如何插入的,我在html中编辑之后发布,总是被改掉了,无法显示。

源代码下载

转载于:https://www.cnblogs.com/xiaoxueliang/archive/2011/05/09/2040745.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值