0

The task: I have a simple task to perform: move a needle inside an ellipse around ellipse's center. It is to become an angle gauge indicator/control.

The status:

I want to move this needle according to the mouse position, when the left button is down inside the ellipse.

This is OK.

I want to stop it moving if the left mouse button is released.

This is OK.

My problem:

But the problem is that if I quit the ellipse area with the left mouse button down (i.e. by accident, when moving the needle), then it is "hold". If you ever come back in the ellipse with the mouse left button UP, needle will move as if it was clicked. So what I need is to disable "drag" when my mouse leaves the ellipse, whether mouse left button is clicked or not. At the time, if the needle is "locked", you need to get outside the ellipse, click left mouse button, and keep it pressed by entering ellipse area. If you release the left mouse click now, it will come back to its normal/wanted behavior.

Here is my XAML "code":

<Window x:Class="test_gauge.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid MouseLeftButtonUp="Grid_MouseLeftButtonUp">
        <Ellipse Name="ellipse1" Fill="#FFF4F4F5" HorizontalAlignment="Left" Height="100" Stroke="Black" VerticalAlignment="Top" Width="100" Canvas.Left="0" Canvas.Top="0" Margin="280,180,0,0" MouseMove="onEllipseMouseMove" MouseLeftButtonDown="onEllipseMouseLeftPressed" MouseLeftButtonUp="onEllipseMouseLeftReleased" MouseLeave="onEllipseMouseLeave"/>
        <Canvas Margin="257,145,10,10" MouseLeftButtonUp="Canvas_MouseLeftButtonUp_1">
            <Thumb Name="myThumb" Canvas.Left="73" Canvas.Top="85" RenderTransformOrigin="0,0">
                <Thumb.RenderTransform>
                    <RotateTransform/>
                </Thumb.RenderTransform>
                <Thumb.Template>
                    <ControlTemplate>
                        <Line Name="needle_line" X1="0" Y1="0" X2="50" Y2="0" StrokeThickness="2" Stroke="Black" MouseLeave="needle_line_MouseLeave"/>
                    </ControlTemplate>
                </Thumb.Template>
            </Thumb>
            <TextBox Name="txtbxAngle" Height="23" Canvas.Left="168" TextWrapping="Wrap" Text="TextBox" Canvas.Top="25" Width="72"/>
        </Canvas>
    </Grid>
</Window>

Then the C# "code":

public partial class MainWindow : Window
{
    /* Angle control stuff */
    public bool bNeedlePressed = false;
    public double refreshedAngle = 0;

    public MainWindow()
    {
        InitializeComponent();
    }

    private void onEllipseMouseMove(object sender, MouseEventArgs e)
    {
        if (bNeedlePressed)
        {
            // This will get the mouse cursor relative to the upper left corner of your ellipse.
            // Note that nothing will happen until you are actually inside of your ellipse.
            Point curPoint = e.GetPosition(ellipse1);

            // Assuming that your ellipse is actually a circle.
            Point center = new Point(ellipse1.Width / 2, ellipse1.Height / 2);

            // A bit of math to relate your mouse to the center...
            Point relPoint = new Point(curPoint.X - center.X, curPoint.Y - center.Y);

            /* Process new angle */
            refreshedAngle = Math.Atan2(relPoint.Y, relPoint.X) * 180 / Math.PI;
            txtbxAngle.Text = ((int)(refreshedAngle)).ToString();

            /* Apply new angle */
            var transform = myThumb.RenderTransform as RotateTransform;
            transform.Angle = refreshedAngle;
        }
    }

    private void onEllipseMouseLeftPressed(object sender, MouseButtonEventArgs e)
    {
        bNeedlePressed = true;
    }
    private void Canvas_MouseLeftButtonUp_1(object sender, MouseButtonEventArgs e)
    {
        bNeedlePressed = false;
    }

    private void onEllipseMouseLeftReleased(object sender, MouseButtonEventArgs e)
    {
        bNeedlePressed = false;
    }

    private void onEllipseMouseLeave(object sender, MouseEventArgs e)
    {
        //bNeedlePressed = false;
    }

    private void needle_line_MouseLeave(object sender, MouseEventArgs e)
    {
        //bNeedlePressed = false;
    }

    private void Grid_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
    {
        bNeedlePressed = false;
    }
}

As you can see, it to use different events, but none do the trick. Well, I believe that at least one does, but I do not know which one.

If you have an idea, please feel free to answer :)

RBT
  • 24,161
  • 21
  • 159
  • 240
jinkoyata
  • 3
  • 3

1 Answers1

0

You can manage the mouse leaving event

    private void Grid_MouseLeave(object sender, MouseEventArgs e)
    {
        bNeedlePressed = false;
    }

declared in the XAML

<Grid MouseLeftButtonUp="Grid_MouseLeftButtonUp" MouseLeave="Grid_MouseLeave" MouseEnter="Grid_MouseEnter">

and mouse entering

    private void Grid_MouseEnter(object sender, MouseEventArgs e)
    {
        bNeedlePressed = e.LeftButton == MouseButtonState.Pressed;
    }
  • Glad it helped. Oh... it's more elegant if we use `MouseButtonState.Pressed` (when mouse enters) –  Sep 02 '16 at 11:22