2009-11-05 20 views
6

Estoy tratando de aprender WPF, así que aquí está una pregunta simple, espero:Transformar las coordenadas de un control de imagen a la fuente de imagen en WPF

tengo una ventana que contiene un elemento de imagen con destino a una de datos independiente objeto con configurable por el usuario Stretch propiedad

<Image Name="imageCtrl" Source="{Binding MyImage}" Stretch="{Binding ImageStretch}" /> 

cuando el usuario mueve el ratón sobre la imagen, me gustaría para determinar las coordenadas del ratón con respecto a la imagen original (antes del estiramiento/recorte que se produce cuando se muestra en el control) y luego hacer algo con t coordenadas de la manguera (actualizar la imagen).

Sé que puedo agregar un controlador de eventos para el evento MouseMove sobre el Control de la imagen, pero no estoy seguro de cuál es la mejor para transformar las coordenadas:

void imageCtrl_MouseMove(object sender, MouseEventArgs e) 
{ 
    Point locationInControl = e.GetPosition(imageCtrl); 
    Point locationInImage = ??? 
    updateImage(locationInImage); 
} 

Ahora sé que podría comparar el tamaño de Source al ActualSize del control, y luego encienda imageCtrl.Stretch para calcular los escalares y las compensaciones en X e Y, y haga la transformación yo mismo. Pero WPF ya tiene toda la información, y esto parece una funcionalidad que podría estar integrada en las bibliotecas de WPF en alguna parte. Entonces me pregunto: ¿hay una solución corta y dulce? ¿O necesito escribir esto yo mismo?


EDITAR estoy añadiendo mi solución actual, no tan corto y dulce. No está tan mal, pero estaría sorprendido si algo WPF no proporcionaba esta funcionalidad de forma automática:

Point ImgControlCoordsToPixelCoords(Point locInCtrl, 
    double imgCtrlActualWidth, double imgCtrlActualHeight) 
{ 
    if (ImageStretch == Stretch.None) 
     return locInCtrl; 

    Size renderSize = new Size(imgCtrlActualWidth, imgCtrlActualHeight); 
    Size sourceSize = bitmap.Size; 

    double xZoom = renderSize.Width/sourceSize.Width; 
    double yZoom = renderSize.Height/sourceSize.Height; 

    if (ImageStretch == Stretch.Fill) 
     return new Point(locInCtrl.X/xZoom, locInCtrl.Y/yZoom); 

    double zoom; 
    if (ImageStretch == Stretch.Uniform) 
     zoom = Math.Min(xZoom, yZoom); 
    else // (imageCtrl.Stretch == Stretch.UniformToFill) 
     zoom = Math.Max(xZoom, yZoom); 

    return new Point(locInCtrl.X/zoom, locInCtrl.Y/zoom); 
} 
+0

Personalmente, probablemente lo haga exactamente como en su solución "no tan corta y dulce". No me encontré con una biblioteca integrada que hiciera esto. –

Respuesta

7

probablemente sería más fácil si se ha utilizado un ViewBox. Por ejemplo:

<Viewbox Stretch="{Binding ImageStretch}"> 
    <Image Name="imageCtrl" Source="{Binding MyImage}" Stretch="None"/> 
</Viewbox> 

Luego, cuando vaya y llame a GetPosition (..) WPF contabilizará automáticamente la escala.

void imageCtrl_MouseMove(object sender, MouseEventArgs e) 
{ 
    Point locationInControl = e.GetPosition(imageCtrl); 
} 
+0

Gracias. Descubrí que no era necesario configurar HorizontalAlignment, pero era importante establecer el DPI para la fuente de la imagen en 96 (estaba usando un mapa de bits no estándar). Ah, y la 'b' en 'Viewbox' es minúscula :) – Gabriel

+0

¡Asombroso! ¡Es increíble lo fácil que se puede hacer en WPF! Muchas gracias, salvó mi tiempo. – Fedor

Cuestiones relacionadas