Silverlight 自定义鼠标
在現(xiàn)在的Silverlight項目中,客戶要求鼠標在可拖動面板上時為手形,拖動時為抓形。無奈Silverlight還不支持這個,只能自動動手做了。
自定義鼠標的思路就是把原始鼠標隱藏,然后做一個圖片,跟著鼠標的位置移動,并在事件中改變圖片,就是我們想要的自定義鼠標效果了。這個東西說起來簡單,做起來并不那么容易,思路總是不容易理清。特別是嵌套元素都自定義了鼠標樣式時,到底取誰的樣式就成了一個問題了,還要考慮效率問題。
參考了網(wǎng)上兩篇文章:
http://www.codeproject.com/KB/silverlight/SilverlightCustomCursors.aspx
http://www.cnblogs.com/dino623/archive/2010/04/01/1702260.html
看了codeproject上的那篇文章,發(fā)現(xiàn)在我們的項目中很合適,主要是簡單。 就是有些bug,比如在程序中改變鼠標樣式都不行,嵌套元素就出問題。 嵌套的問題當然是取最上層的那個元素了。主要代碼如下:
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中編輯之后發(fā)布,總是被改掉了,無法顯示。
源代碼下載
轉(zhuǎn)載于:https://www.cnblogs.com/xiaoxueliang/archive/2011/05/09/2040745.html
總結(jié)
以上是生活随笔為你收集整理的Silverlight 自定义鼠标的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: WPF中实现先登录后启动主程序的方法
- 下一篇: 引用用户控件图片无法