代码之家  ›  专栏  ›  技术社区  ›  Palantir

没有画布作为根的Silverlight自定义鼠标光标?

  •  1
  • Palantir  · 技术社区  · 14 年前

    是否可以使用自定义鼠标指针(png图像), 没有 以画布作为根元素?以画布为根鼠标工作( like here

    谢谢! 真知晶球

    1 回复  |  直到 14 年前
        1
  •  3
  •   Murven    14 年前

    你不能逃避使用画布,但这并不意味着你必须遵守画布如何安排事情。

    我创造了一些对你有用的行为。

    第一种是:

    [TypeConstraint(typeof(Canvas))]
    public class MouseCursorAction : TargetedTriggerAction<UIElement>
    {
    
        protected override void Invoke(object parameter)
        {
        }
    
        protected override void OnAttached()
        {
            var canvas = AssociatedObject as Canvas;
            if (canvas == null) { return; }
            canvas.MouseMove += new MouseEventHandler(canvas_MouseMove);
            canvas.MouseEnter += new MouseEventHandler(canvas_MouseEnter);
            canvas.MouseLeave += new MouseEventHandler(canvas_MouseLeave);
        }
    
        void canvas_MouseLeave(object sender, MouseEventArgs e)
        {
            Target.Visibility = Visibility.Collapsed;
        }
    
        void canvas_MouseEnter(object sender, MouseEventArgs e)
        {
            Target.Visibility = Visibility.Visible;
        }
    
        void canvas_MouseMove(object sender, MouseEventArgs e)
        {
            var canvas = sender as Canvas;
            var positionInCanvas = e.GetPosition(canvas);
            Canvas.SetTop(Target, positionInCanvas.Y);
            Canvas.SetLeft(Target, positionInCanvas.X);
        }
    }
    

    通过这种行为,您可以转换鼠标光标中的任何UIElement。只需将其设置为画布并选择鼠标光标所需的目标。

    现在,为了解决布局问题,我创建了另一个行为:

    [TypeConstraint(typeof(Canvas))]
    public class FillCanvasAction : TargetedTriggerAction<FrameworkElement>
    {
    
        protected override void Invoke(object parameter)
        {
        }
    
        protected override void OnAttached()
        {
            var canvas = AssociatedObject as Canvas;
            if (canvas == null) { return; }
            canvas.SizeChanged += new SizeChangedEventHandler(Target_SizeChanged);
        }
    
        void Target_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            var element = Target;
            if (element == null) { return; }
    
            var canvas = sender as Canvas;
    
            element.Width = canvas.ActualWidth;
            element.Height = canvas.ActualHeight;
            Canvas.SetTop(element, 0);
            Canvas.SetLeft(element, 0);
        }
    }
    

    当附加到父画布时,此行为会将目标FrameworkElement(例如网格)的大小调整为父画布的大小。这意味着您可以在这个FrameworkElement中创建自己的自定义布局,而不必担心Canvas处理布局的方式。

    <Grid x:Name="LayoutRoot" Cursor="None">
        <Canvas x:Name="canvas" Background="Black">
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="MouseEnter">
                    <local:MouseCursorAction TargetObject="{Binding ElementName=cursorImage}"/>
                </i:EventTrigger>
                <i:EventTrigger>
                    <local:FillCanvasAction TargetObject="{Binding ElementName=grid}"/>
                </i:EventTrigger>
            </i:Interaction.Triggers>
            <Grid x:Name="grid" Background="White" Width="600" Height="400">
                <!-- Create your layout here -->
            </Grid>
            <Image x:Name="cursorImage" Height="50" Width="50" Source="mouse_cursor.png"/>
        </Canvas>
    </Grid>
    

    你可以从 here

    免责声明:严格来说,应该使用弱事件处理来实现此行为,以避免内存泄漏;但是,该实现超出了此答案的范围。你可以在这个网站上找到更多关于弱事件处理的信息,以及你的项目是否需要它。