Search code examples
c#wpfxamlzoomingpan

Get image coordinates from mouse cursor position on screen (WPF Image control)


I was looking for a solution to transparently add panning & zooming capability to a WPF Image control and I have found the solution https://stackoverflow.com/a/6782715/584180, developed by Wiesław Šoltés and Konrad Viltersten, which is outstanding.

Now I would like to add a 'mouse click' event to the control so that I can the coordinates of the clicked point in the original image coordinate system, so I can use them to retrieve the pixel color.

I understand there will be some rounding and if the image is zoomed out the color will not correspond to the actual one displayed on screen. I also understand that the user may click outside the image borders, in that case I expect a null Point or negative coords to be returned.

I am not an expert of the C# way of doing transforms and at the moment I am stuck with this (to be added inside the ZoomBorder.cs class):

public Point GetImageCoordsAt(MouseButtonEventArgs e)
{
    if (child != null)
    {
        var tt = GetTranslateTransform(child);
        var mousePos = e.GetPosition(this);
        var transformOrigin = new Point(tt.X, tt.Y);

        return mousePos; // Wrong: how do I transform this?
    }

    return null;
}

Solution

  • As mm8 suggests you can get the location you want using e.GetPosition(child); , there's no need to perform any transformations. For testing purposes I've overwritten the reset behaviour. Using the code from the link you provided, change

    void child_PreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e)
    {
        this.Reset();
    }
    

    to

    public Point GetImageCoordsAt(MouseButtonEventArgs e)
    {
        if (child != null && child.IsMouseOver)
        {
            return e.GetPosition(child);
        }
        return new Point(-1, -1);
    }
    
    void child_PreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e)
    {
        MessageBox.Show(GetImageCoordsAt(e).ToString());
    }
    

    If you rightclick at the same location in the image, you'll get (approximately) the same coordinates, regardless of the pan and zoom.