WPF: обнаружение клика по изображению только на непрозрачной части - PullRequest
8 голосов
/ 26 января 2011

У меня есть элемент управления Image в WPF, который содержит изображение с большим количеством прозрачных пикселей. Прямо сейчас, событие MouseDown на Image срабатывает всякий раз, когда я щелкаю внутри полной прямоугольной области элемента управления Image. Я хотел бы каким-то образом определить, произошел ли щелчок мыши на непрозрачной части изображения.

Как лучше всего это сделать?

Ответы [ 2 ]

13 голосов
/ 26 января 2011

Используя технику из этого ответа , вы можете извлечь из Image, чтобы создать OpaqueClickableImage, который отвечает только на проверку попадания в достаточно непрозрачных областях изображения:

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

после добавления этого класса просто используйте его как обычное изображение:

<utils:OpaqueClickableImage Name="image" Source="http://entropymine.com/jason/testbed/pngtrans/rgb8_t_bk.png" Stretch="None"/>
3 голосов
/ 31 октября 2011
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);
    }
}
...