2009-11-05 9 views
6

Ich versuche WPF zu lernen, so ist hier eine einfache Frage, ich hoffe:Transforming-Koordinaten von einer Bildsteuerung auf der Bildquelle in WPF

ich ein Fenster haben, die ein Bildelement enthält auf einem separaten Daten gebunden Objekt mit vom Benutzer konfigurierbare Stretch Eigenschaft

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

wenn der Benutzer die Maus über das Bild bewegt, Ich mag würde die Koordinaten der Maus in Bezug auf die Originalbild (vor dem Recken/Zuschneiden bestimmen, die auftritt, wenn es wird in der Steuerung angezeigt) und dann etwas mit t tun Schlauchkoordinaten (Bild aktualisieren).

Ich weiß, dass ich einen Event-Handler an das Mousemove-Ereignis über die Bildsteuerung hinzuzufügen, aber ich bin nicht sicher, wie man am besten die Koordinaten zu transformieren:

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

Jetzt weiß ich, dass ich die Größe vergleichen könnte von Source an die ActualSize des Steuerelements, und schalten Sie dann imageCtrl.Stretch ein, um die Skalare und Offsets für X und Y zu berechnen und die Transformation selbst vorzunehmen. Aber WPF hat alle Informationen bereits, und das scheint wie Funktionalität, die irgendwo in die WPF-Bibliotheken eingebaut werden könnte. Ich frage mich also: Gibt es eine kurze und süße Lösung? Oder muss ich das selbst schreiben?


EDIT ich meine aktuelle, nicht-so-Kurz und süße Lösung anhängen. Es ist nicht so schlecht, aber ich etwas überrascht sein würde, wenn WPF diese Funktionalität nicht automatisch vorsah:

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

Ich persönlich würde es wahrscheinlich genau so machen, wie Sie es in Ihrer "nicht so-kurz-und-süß" -Lösung haben. Ich bin nicht in eine eingebaute Bibliothek gelaufen, die das tun würde. –

Antwort

7

Es wäre wahrscheinlich einfacher, wenn Sie einen ViewBox verwendet. Zum Beispiel:

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

Dann, wenn Sie gehen und GetPosition aufrufen (..) WPF wird automatisch für die Skalierung.

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

Danke. Ich habe festgestellt, dass ich die horizontale Ausrichtung nicht einstellen musste, aber es war wichtig, die DPI für die Bildquelle auf 96 zu setzen (ich verwendete eine nicht standardmäßige Bitmap). Oh, und das "b" in "Viewbox" ist Kleinbuchstaben :) – Gabriel

+0

Erstaunlich! Es ist einfach unglaublich, wie einfach es in WPF gemacht werden kann! Vielen Dank, sparte meine Zeit. – Fedor