views:

463

answers:

2

I'm trying to make a color picker in Silverlight similar to this one but I'm having trouble implementing the cursor in the large square area. In order to keep track of the mouse state I have an _isMouseDown variable. On the MouseLeave event _isMouseDown is set to false, so that if a user drags out of the large square area, releases, and then moves the mouse back, the color picker cursor won't "jump" to the mouse and follow it (because _isMouseDown would still be true). However the MouseLeave event also seems to fire when the cursor is mouse is moved quickly, resulting in the color picker cursor being "dropped."

The following code is enough to replicate the problem. Try dragging the mouse quickly and the ellipse will be "dropped". When the MouseLeave event is removed the problem vanishes. Is there any way to fix this "dropping" problem, but still have the behavior I mentioned above?

XAML:

<UserControl x:Class="SilverlightApplication1.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"&gt;
    <Canvas x:Name="LayoutRoot" Width="800" Height="600">
        <Rectangle Width="800" Height="600" MouseLeftButtonDown="TestMouseDown"
            MouseLeftButtonUp="TestMouseUp" MouseMove="TestMouseMove"
            MouseLeave="TestMouseLeave">
            <Rectangle.Fill>
                <LinearGradientBrush>
                    <GradientStop Offset="0.00" Color="Crimson" />
                    <GradientStop Offset="1.00" Color="Azure" />
                </LinearGradientBrush>
            </Rectangle.Fill>
        </Rectangle>
        <Ellipse Name="TestEllipse" Width="50" Height="50" Fill="Green" />
    </Canvas>
</UserControl>

C# codebehind:

using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;

namespace SilverlightApplication1
{
    public partial class MainPage : UserControl
    {
        private bool _isMouseDown;

        public MainPage()
        {
            InitializeComponent();
        }

        private void TestMouseDown(object sender, MouseButtonEventArgs e)
        {
            _isMouseDown = true;
            UpdatePosition(e.GetPosition(LayoutRoot));
        }

        private void TestMouseUp(object sender, MouseButtonEventArgs e)
        {
            _isMouseDown = false;
        }

        private void TestMouseMove(object sender, MouseEventArgs e)
        {
            if (_isMouseDown)
                UpdatePosition(e.GetPosition(LayoutRoot));
        }

        private void TestMouseLeave(object sender, MouseEventArgs e)
        {
            _isMouseDown = false;
        }

        private void UpdatePosition(Point point)
        {
            Canvas.SetLeft(TestEllipse, point.X);
            Canvas.SetTop(TestEllipse, point.Y);
        }
    }
}
+2  A: 

You should take a look at the CaptureMouse method on UIElement. It should be helpful for you in this situation. With the mouse captured, you will continue to receive mouse events even when the mouse leave the element's area. You can then voluntarily release the mouse capture whenever that is appropriate.

KeithMahoney
A: 

Hi,

However the MouseLeave event also seems to fire when the cursor is mouse is moved quickly, resulting in the color picker cursor being "dropped."

the problem with your code is MouseLeave event fires not only at the time of mouse leaving the rectangle, this also fires when mouse enter the Ellipse.. because the mouse event is now routed to the ellipse control.. (not this fired when u move the mouse quickly)..

As KeithMahoney suggest, u can try CaptureMouse... or set _isMouseDown = true on the MouseEnter event of ellipse.. it may work.. i dint test ur code yet.. just telling u by seeing the code...

Cheers

Ramesh Vel

Ramesh Vel