2011-01-26 16 views
8

Tengo un control Image en WPF que contiene una imagen con muchos píxeles transparentes. En este momento, el evento MouseDown en Image se dispara cada vez que hago clic dentro de la región rectangular completa del control Image. Me gustaría alguna forma de detectar si el clic del mouse ocurrió en una porción no transparente de la imagen.WPF: Detectar imagen haga clic solo en la parte no transparente

¿Cuál sería la mejor manera de hacerlo?

Respuesta

13

Utilizando la técnica de this answer se puede derivar de Image para crear un OpaqueClickableImage que sólo responde a golpear pruebas en zonas suficientemente no transparentes de la imagen:

public class OpaqueClickableImage : Image 
{ 
    protected override HitTestResult HitTestCore(PointHitTestParameters hitTestParameters) 
    { 
     var source = (BitmapSource)Source; 

     // Get the pixel of the source that was hit 
     var x = (int)(hitTestParameters.HitPoint.X/ActualWidth * source.PixelWidth); 
     var y = (int)(hitTestParameters.HitPoint.Y/ActualHeight * source.PixelHeight); 

     // Copy the single pixel into a new byte array representing RGBA 
     var pixel = new byte[4]; 
     source.CopyPixels(new Int32Rect(x, y, 1, 1), pixel, 4, 0); 

     // Check the alpha (transparency) of the pixel 
     // - threshold can be adjusted from 0 to 255 
     if (pixel[3] < 10) 
      return null; 

     return new PointHitTestResult(this, hitTestParameters.HitPoint); 
    } 
} 

después de la adición de esta clase, sólo lo utilizan como una imagen normal:

<utils:OpaqueClickableImage Name="image" Source="http://entropymine.com/jason/testbed/pngtrans/rgb8_t_bk.png" Stretch="None"/> 
+1

Gracias! Esto funciona perfectamente Debo haber perdido esa otra publicación. – Bradley

+0

¡Increíble! ¡Muchas gracias! :) – CainKellye

+0

De hecho, he visto este error porque 'x' o' y' estarán fuera de 'PixelWidth' o' PixelHeight' de 'source'. Podría redondear el cálculo, o decir, si 'x> = PixelWidth: x = PixelWidth' –

3
public class OpaqueClickableImage : Image 
{ 
    protected override HitTestResult HitTestCore(PointHitTestParameters hitTestParameters) 
    { 
     var source = (BitmapSource)Source; 
     var x = (int)(hitTestParameters.HitPoint.X/ActualWidth * source.PixelWidth); 
     var y = (int)(hitTestParameters.HitPoint.Y/ActualHeight * source.PixelHeight); 
     if (x == source.PixelWidth) 
      x--; 
     if (y == source.PixelHeight) 
      y--; 
     var pixels = new byte[4]; 
     source.CopyPixels(new Int32Rect(x, y, 1, 1), pixels, 4, 0); 
     if (pixels[3] < 1) return null; 
     return new PointHitTestResult(this, hitTestParameters.HitPoint); 
    } 
}