Как наложить цвет на холст, а также добавить область исключения в WPF - PullRequest
1 голос
/ 26 февраля 2011

Итак, простой вопрос, я уверен, что вы более опытные люди из WPF, но у меня есть простое задание (в WinForms), что у меня возникли некоторые проблемы при реализации в WPF. Когда я сталкиваюсь с чем-то подобным в WPF, это обычно означает, что есть функция, о которой я не знаю, но я не смог найти никаких примеров. Вот проблема:

Представьте себе холст, на котором отображается изображение. Поверх этого изображения у меня есть прямоугольник большого размера, которым может манипулировать пользователь. Я хочу, чтобы вся область за пределами этого прямоугольника была замаскирована полупрозрачным цветом. В WinForms я бы просто переопределил OnPaint, добавил область исключения в мой объект Graphics, а затем залил объект Graphics моим полупрозрачным цветом.

Итак, мое первое желание было переопределить OnRender для моего Canvas и сделать то же самое, используя DrawingContext. Итак, я попробовал это в качестве теста:

protected override void OnRender( DrawingContext dc )
{
    base.OnRender( dc );
    var clipRect = new Rect( 128, 128, 1024, 462 );
    dc.PushClip( new RectangleGeometry( clipRect ) );
    var bounds = new Rect( 0, 0, this.ActualHeight, this.ActualWidth );
    dc.DrawRectangle( new SolidColorBrush( Colors.White.ApplyAlpha( 128 ) ), null, bounds );
}

Без кубиков; На самом деле OnRender никогда не стреляет.

По своему опыту работы с WPF (с большинством вещей на самом деле) я понял, что когда что-то, что кажется простым, на самом деле сложно, я делаю это неправильно. Итак, какой-нибудь совет, как установить цвет маски с областью клипа? Заранее спасибо.

1 Ответ

3 голосов
/ 26 февраля 2011

вы можете использовать маску непрозрачности с исключенной областью, например так:

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:Canvastest"
    x:Class="Canvastest.MainWindow"
    x:Name="Window"
    Title="MainWindow"
    Width="640" Height="480">

    <Grid x:Name="LayoutRoot">
        <Canvas Margin="8">
            <Image x:Name="image" Height="410" Width="592" Source="Koala.jpg" Stretch="UniformToFill"/>
            <Rectangle Fill="#FD9D5C5C" Width="{Binding ActualWidth, ElementName=image}" Height="{Binding ActualHeight, ElementName=image}" Name="rect">
                <Rectangle.OpacityMask>
                    <DrawingBrush Stretch="None">
                        <DrawingBrush.Drawing>                                                      
                            <GeometryDrawing Brush="#99ffffff">
                                <GeometryDrawing.Geometry>
                                    <CombinedGeometry GeometryCombineMode="Exclude">
                                        <CombinedGeometry.Geometry1>
                                            <RectangleGeometry>
                                                <RectangleGeometry.Rect>
                                                    <MultiBinding Converter="{local:RectConverter}">
                                                        <Binding Path="(Canvas.Left)" ElementName="image"/>
                                                        <Binding Path="(Canvas.Top)" ElementName="image"/>
                                                        <Binding Path="Width" ElementName="rect"/>
                                                        <Binding Path="Height" ElementName="rect"/>
                                                    </MultiBinding>
                                                </RectangleGeometry.Rect>
                                            </RectangleGeometry>
                                        </CombinedGeometry.Geometry1>
                                        <CombinedGeometry.Geometry2>
                                            <RectangleGeometry>
                                                <RectangleGeometry.Rect>
                                                    <MultiBinding Converter="{local:RectConverter}">
                                                        <Binding Path="(Canvas.Left)" ElementName="thumb"/>
                                                        <Binding Path="(Canvas.Top)" ElementName="thumb"/>
                                                        <Binding Path="Width" ElementName="thumb"/>
                                                        <Binding Path="Height" ElementName="thumb"/>
                                                    </MultiBinding>
                                                </RectangleGeometry.Rect>
                                            </RectangleGeometry>
                                        </CombinedGeometry.Geometry2>                                       
                                    </CombinedGeometry>                                 
                                </GeometryDrawing.Geometry>                             
                            </GeometryDrawing>
                        </DrawingBrush.Drawing>
                    </DrawingBrush>
                </Rectangle.OpacityMask>
            </Rectangle>
            <Thumb Name="thumb" DragDelta="Thumb_DragDelta" Width="50" Height="50" Background="Transparent" Cursor="SizeAll" Canvas.Left="50" Canvas.Top="50">
                <Thumb.Style>
                    <Style TargetType="Thumb">
                        <Setter Property="OverridesDefaultStyle" Value="True"/>
                        <Setter Property="Template">
                            <Setter.Value>
                                <ControlTemplate TargetType="Thumb">
                                    <Grid Background="Transparent">

                                    </Grid>                                    
                                </ControlTemplate>
                            </Setter.Value>
                        </Setter>
                    </Style>
                </Thumb.Style>
            </Thumb>
            <Grid Width="{Binding Width, ElementName=thumb}" Height="{Binding Height, ElementName=thumb}" Canvas.Left="{Binding (Canvas.Left), ElementName=thumb}" Canvas.Top="{Binding (Canvas.Top), ElementName=thumb}">
                <Thumb Width="5" Height="5" Cursor="SizeNWSE" DragDelta="Thumb_DragDelta_1" Background="Transparent" Margin="0,0,-5,-5" HorizontalAlignment="Right" VerticalAlignment="Bottom"/>
            </Grid>

        </Canvas>
    </Grid>
</Window>

с codebehind:

public partial class MainWindow : Window
    {
        public MainWindow()
        {
            this.InitializeComponent();

        }

        private void Thumb_DragDelta(object sender, DragDeltaEventArgs e)
        {
            var thumb = sender as Thumb;
            var left = (double)thumb.GetValue(Canvas.LeftProperty);
            var top = (double)thumb.GetValue(Canvas.TopProperty);

            if (double.IsNaN(left))
                left = 0.0;
            if (double.IsNaN(top))
                top = 0.0;
            left += e.HorizontalChange;
            top += e.VerticalChange;
            thumb.SetValue(Canvas.LeftProperty,left);
            thumb.SetValue(Canvas.TopProperty, top);
        }

        private void Thumb_DragDelta_1(object sender, DragDeltaEventArgs e)
        {            
            thumb.Width += e.HorizontalChange;
            thumb.Height += e.VerticalChange;
        }
    }

    public class RectConverter : MarkupExtension,IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            if (values == null || values.Length != 4 || values.OfType<double>().Count() != 4) return new Rect(0, 0, 0, 0);
            for (var i = 0; i < values.Length; i++)
                if (double.IsNaN((double)values[i]))
                    values[i] = 0.0;
            return new Rect((double)values[0], (double)values[1], (double)values[2], (double)values[3]);
        }

        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }

        public override object ProvideValue(IServiceProvider serviceProvider)
        {
            return new RectConverter();
        }
    }

РЕДАКТИРОВАТЬ: было немного больше удовольствия с этим, чтобы кодировать полный пример

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...