WPF:使用XAML仅在非透明部分上单击“创建图像按钮”

时间:2019-07-10 12:45:56

标签: c# wpf button

好的,我正在尝试使用.png图像制作图像按钮,但是我只需要使用XAML即可单击不透明部分即可。

我使用自定义图像类尝试了很多,但是这些尝试都没有对我起作用。

这是我正在使用的png图像的示例。

Image1

这是我的xaml图像按钮的示例代码。

<Style x:Key="Home1_Unlocked" TargetType="Button">
        <Setter Property="Width" Value="611"/>
        <Setter Property="Height" Value="541"/>
        <Setter Property="ClickMode" Value="Press"/>
        <Setter Property="Focusable" Value="False"/>
        <Setter Property="HorizontalAlignment" Value="Left"/>
        <Setter Property="VerticalAlignment" Value="Top"/>
        <Setter Property="Margin" Value="100,50,0,0"/>
        <Setter Property="UIElement.SnapsToDevicePixels" Value="True"/>
        <Setter Property="Control.Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Button}">
                    <Grid Name="WholeButton" Background="Transparent">
                        <ui:MapObject x:Name="Home" Stretch="Uniform" Source="/Resources/Game/map/but1_dim.png">
                            <!--<ui:MapObject.RenderTransformOrigin>
                                <Point X="0.5" Y="0.5"/>
                            </ui:MapObject.RenderTransformOrigin>
                            <ui:MapObject.RenderTransform>
                                <ScaleTransform ScaleX="0.5" ScaleY="0.5" />
                            </ui:MapObject.RenderTransform>-->
                        </ui:MapObject>
                        <Grid Margin="0,0,0,150" HorizontalAlignment="Center" VerticalAlignment="Bottom">
                            <TextBlock Text="0 of 0 STARS" Style="{DynamicResource Riffic}" Margin="130,0,00,0" Foreground="White" VerticalAlignment="Center" HorizontalAlignment="Right" FontSize="40">
                                <TextBlock.Effect>
                                    <DropShadowEffect Color="Black"/>
                                </TextBlock.Effect>
                            </TextBlock>
                            <Image Grid.Column="0" Source="/Resources/Game/map/wmapenable.png" HorizontalAlignment="Left" Margin="10,0,0,0" Stretch="None"/>
                            <Image Grid.Column="0" Source="/Resources/Game/map/big1.png" HorizontalAlignment="Left" Margin="40,0,0,0" Stretch="None"/>
                        </Grid>
                        <ContentPresenter Name="MyContentPresenter" Content="{TemplateBinding ContentControl.Content}" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,0,0,0"/>
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter TargetName="Home" Property="Source" Value="/Resources/Game/map/but1.png"/>
                        </Trigger>
                        <Trigger Property="ButtonBase.IsPressed" Value="True">
                            <Setter TargetName="WholeButton" Property="RenderTransform">
                                <Setter.Value>
                                    <ScaleTransform ScaleX="1.01" ScaleY="1.01" />
                                </Setter.Value>
                            </Setter>
                            <Setter TargetName="WholeButton" Property="RenderTransformOrigin">
                                <Setter.Value>
                                    <Point X="0.5" Y="0.5"/>
                                </Setter.Value>
                            </Setter>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

这是自定义图像类...

public class MapObject : 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);
        }
    }

有人可以帮我吗?

1 个答案:

答案 0 :(得分:0)

我需要注意以下几点:

  • 确认检测到的像素是您认为的像素。看起来您已经知道DPI缩放比例,但即使如此,也很容易错过某些内容(例如,Y轴反转,从WPF坐标到像素坐标的错误映射...)。
  • 是否还有其他东西也在处理鼠标单击。也许对图像的命中测试可以正常工作,但是后面的按钮仍然可以处理鼠标在透明区域上的单击?
  • 如果无法在图像级别使用它,则可以定义一个涵盖与图像相同区域的Geometry,并针对该几何进行命中测试。当然,如果您有很多图像,这可能不是合适的解决方案。
  • 请考虑WPF是否适合该工作。 WPF主要是一个用户界面框架。虽然您可以肯定地使用它来制作较低级别的图形,但是使用按钮意味着您最终将拥有许多您可能不希望使用的UI功能:用户可以使用Tab键选择按钮或使用键盘提交按钮,视觉亮点,低帧频(因为各种事件都是在后台进行的,您实际上并不在意,但是会使用宝贵的资源),等等。可能有一些更合适的工具可用于您要执行的操作。我建议您看一下UnityMonoGame之类的游戏框架,它们都可以与C#一起使用,并且可以为您提供很多特定于游戏的功能,而无需花很多钱UI框架随身携带。