2011-01-26 10 views
8

Ho un controllo Image in WPF che contiene un'immagine con molti pixel trasparenti. In questo momento, l'evento MouseDown su Image viene attivato ogni volta che faccio clic all'interno dell'area rettangolare completa del controllo Image. Mi piacerebbe un modo per rilevare se il clic del mouse si è verificato su una porzione non trasparente dell'immagine.WPF: Rileva immagine solo su una parte non trasparente

Quale sarebbe il modo migliore per farlo?

risposta

13

Utilizzando la tecnica in this answer è possibile derivare da Image per creare un OpaqueClickableImage che risponde solo a colpire test nelle aree sufficientemente non trasparenti dell'immagine:

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); 
    } 
} 

dopo l'aggiunta di questa classe, basta usarlo come un'immagine normale:

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

Grazie! Questo funziona perfettamente. Devo aver perso quell'altro post. – Bradley

+0

Awsome! Molte grazie! :) – CainKellye

+0

In realtà ho visto questo fallire perché 'x' o' y' sarà al di fuori del 'PixelWidth' o' PixelHeight' del 'source'. Potrebbe arrotondare il calcolo, o dire, se '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); 
    } 
} 
Problemi correlati