【问题标题】:WPF: Detect Image click only on non-transparent portionWPF:仅在不透明部分检测图像点击
【发布时间】:2011-06-15 14:17:33
【问题描述】:

我在 WPF 中有一个 Image 控件,其中包含一个具有大量透明像素的图像。现在,每当我在Image 控件的整个矩形区域内单击时,Image 上的MouseDown 事件就会触发。我想要一些方法来检测鼠标点击是否发生在图像的不透明部分。

最好的方法是什么?

【问题讨论】:

    标签: wpf image wpf-controls


    【解决方案1】:

    使用this answer 中的技术,您可以从Image 派生出一个OpaqueClickableImage,该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"/>
    

    【讨论】:

    • 谢谢!这完美地工作。我一定错过了其他帖子。
    • 我实际上已经看到了这个失败,因为 xy 将在 sourcePixelWidthPixelHeight 之外。可以对计算进行四舍五入,或者说,如果x&gt;= PixelWidth: x = PixelWidth
    • CopyPixels 抛出 System.ArgumentException (越界)。有什么问题?
    【解决方案2】:
    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);
            
            return (pixels[3] < 1) ? null : new PointHitTestResult(this, hitTestParameters.HitPoint);
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-01-05
      • 1970-01-01
      • 1970-01-01
      • 2013-08-04
      • 1970-01-01
      • 1970-01-01
      • 2012-02-24
      • 2014-08-08
      相关资源
      最近更新 更多