填充矩形的外部

时间:2021-08-31 12:05:14

I would like to draw a rectangle in WPF (by code) and to fill the outside of it.

我想在WPF(代码)中绘制一个矩形,并填充它的外部。

Here is an example :

这里有一个例子:

填充矩形的外部

The outside of the rectangle is grey (with low opacity), and the fill of the rectangle is trasparent.

矩形的外部为灰色(低透明度),矩形的填充为trasparent。

4 个解决方案

#1


5  

You may also overlay your image with a semi-transparent Path element that uses a CombinedGeometry which combines one very large outer rectangle with an inner rectangle:

你也可以用一个半透明的路径元素覆盖你的图像,它使用一个组合几何体,它结合一个非常大的外矩形和一个内矩形:

<Grid>
    <Image Name="image" Source="C:\Users\Public\Pictures\Sample Pictures\Koala.jpg"/>
    <Path Fill="#AAFFFFFF">
        <Path.Data>
            <CombinedGeometry GeometryCombineMode="Xor">
                <CombinedGeometry.Geometry1>
                    <RectangleGeometry Rect="0,0,10000,10000"/>
                </CombinedGeometry.Geometry1>
                <CombinedGeometry.Geometry2>
                    <RectangleGeometry x:Name="transparentRect" Rect="150,100,200,100"/>
                </CombinedGeometry.Geometry2>
            </CombinedGeometry>
        </Path.Data>
    </Path>
</Grid>

You would now programatically adjust the Rect property of the transparentRect member as needed.

您现在可以根据需要编程调整透明成员的Rect属性。

#2


2  

You can use UIElement.Clip property:

您可以使用UIElement。夹属性:

<Window x:Class="So17720970_RectangularBoublik.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        SizeToContent="WidthAndHeight">
    <Grid Width="500" Height="500">
        <Image Source="http://i.stack.imgur.com/Py65S.jpg"/>  <!-- image -->
        <Rectangle Fill="#AA000000">                          <!-- selection -->
            <Rectangle.Clip>
                <GeometryGroup FillRule="Nonzero">            <!-- selection clip: -->
                    <RectangleGeometry Rect="0 0 500 200"/>   <!--   top -->
                    <RectangleGeometry Rect="0 0 100 500"/>   <!--   left -->
                    <RectangleGeometry Rect="0 300 500 200"/> <!--   bottom -->
                    <RectangleGeometry Rect="400 0 100 500"/> <!--   right -->
                </GeometryGroup>
            </Rectangle.Clip>
        </Rectangle>
        <Rectangle StrokeThickness="1" Stroke="Black" StrokeDashArray="1 2" SnapsToDevicePixels="True"
                Margin="100 200 100 200"/>                    <!-- "ants" -->
    </Grid>
</Window>

#3


2  

You can use a combination of OpacityMask and DrawingBrush:

您可以使用一种组合光罩和拉拔刷:

XAML:

XAML:

<Grid Background="Gray">
    <Image Name="image"Source="...">
        <Image.OpacityMask>
            <DrawingBrush x:Name="mask"/>
        </Image.OpacityMask>
    </Image>
</Grid>

Code-behind:

后台代码:

    private void UpdateOpactiyMask()
    {
        Point topLeft = new Point();
        Point bottomRight = new Point(image.ActualWidth, image.ActualHeight);

        GeometryDrawing left = new GeometryDrawing();
        left.Brush = borderBrush;
        left.Geometry = new RectangleGeometry(new Rect(topLeft, new Point(SelectedArea.Left, bottomRight.Y)));

        GeometryDrawing right = new GeometryDrawing();
        right.Brush = borderBrush;
        right.Geometry = new RectangleGeometry(new Rect(new Point(SelectedArea.Right, topLeft.Y), bottomRight));

        GeometryDrawing top = new GeometryDrawing();
        top.Brush = borderBrush;
        top.Geometry = new RectangleGeometry(new Rect(new Point(SelectedArea.Left, topLeft.Y), new Point(SelectedArea.Right, SelectedArea.Top)));

        GeometryDrawing bottom = new GeometryDrawing();
        bottom.Brush = borderBrush;
        bottom.Geometry = new RectangleGeometry(new Rect(new Point(SelectedArea.Left, SelectedArea.Bottom), new Point(SelectedArea.Right, bottomRight.Y)));

        GeometryDrawing center = new GeometryDrawing();
        center.Brush = selectionBrush;
        center.Geometry = new RectangleGeometry(SelectedArea);

        DrawingGroup drawing = new DrawingGroup();
        drawing.Children.Add(left);
        drawing.Children.Add(right);
        drawing.Children.Add(top);
        drawing.Children.Add(bottom);
        drawing.Children.Add(center);

        mask.Drawing = drawing;
    }

SelectedArea is a Rect.

SelectedArea是一个矩形。

#4


1  

This is a variation on the solution using OpacityMask. Instead of doing it in the code, it is done in XAML. Also, it reverses the logic: instead of drawing 4 border rectangles, it draws 2 rectangles on top of each other. Finally, the important property of this solution is that the size of the central transparent rectangle is relative to the image size (rather than in absolute pixels). You do not need to know the actual image size or how it is stretched/positioned (particularly important for Stretch="Uniform"). Here, I have specified the image size (maskRect) as 1,1 and used fractional numbers as relative mask size and position (transpRect). You may as well specify the image size as 100,100 and use percentage values for the mask (or, even use the actual pixel values).

这是使用OpacityMask的溶液的变化。它不是在代码中执行,而是在XAML中执行。此外,它还颠倒了逻辑:它不是绘制4个边框,而是在每个边框上画2个矩形。最后,这个解决方案的重要特性是,*透明矩形的大小相对于图像大小(而不是绝对像素)。您不需要知道实际的图像大小或它是如何拉伸/定位的(对Stretch="Uniform"尤其重要)。在这里,我指定了图像大小(maskRect)为1,1,并使用小数作为相对掩码大小和位置(transpRect)。您也可以将图像大小指定为100,100,并对掩码使用百分比值(甚至使用实际的像素值)。

          <Grid Background="#FFF4F4F5" >
            <Image Name="PhotoImage" Source="...">
                <Image.OpacityMask>
                    <DrawingBrush>
                        <DrawingBrush.Drawing>
                            <DrawingGroup>
                                <GeometryDrawing>
                                    <GeometryDrawing.Geometry>
                                        <RectangleGeometry x:Name="maskRect" Rect="0,0,1,1"/>
                                    </GeometryDrawing.Geometry>
                                    <GeometryDrawing.Brush>
                                        <SolidColorBrush Color="#60000000" />
                                    </GeometryDrawing.Brush>
                                </GeometryDrawing>
                                <GeometryDrawing>
                                    <GeometryDrawing.Geometry>
                                        <RectangleGeometry x:Name="transpRect" Rect=".25,.20,.40,.40"/>
                                    </GeometryDrawing.Geometry>
                                    <GeometryDrawing.Brush>
                                        <SolidColorBrush Color="Black" />
                                    </GeometryDrawing.Brush>
                                </GeometryDrawing>
                            </DrawingGroup>
                        </DrawingBrush.Drawing>
                    </DrawingBrush>
                </Image.OpacityMask>
            </Image>
        </Grid>

#1


5  

You may also overlay your image with a semi-transparent Path element that uses a CombinedGeometry which combines one very large outer rectangle with an inner rectangle:

你也可以用一个半透明的路径元素覆盖你的图像,它使用一个组合几何体,它结合一个非常大的外矩形和一个内矩形:

<Grid>
    <Image Name="image" Source="C:\Users\Public\Pictures\Sample Pictures\Koala.jpg"/>
    <Path Fill="#AAFFFFFF">
        <Path.Data>
            <CombinedGeometry GeometryCombineMode="Xor">
                <CombinedGeometry.Geometry1>
                    <RectangleGeometry Rect="0,0,10000,10000"/>
                </CombinedGeometry.Geometry1>
                <CombinedGeometry.Geometry2>
                    <RectangleGeometry x:Name="transparentRect" Rect="150,100,200,100"/>
                </CombinedGeometry.Geometry2>
            </CombinedGeometry>
        </Path.Data>
    </Path>
</Grid>

You would now programatically adjust the Rect property of the transparentRect member as needed.

您现在可以根据需要编程调整透明成员的Rect属性。

#2


2  

You can use UIElement.Clip property:

您可以使用UIElement。夹属性:

<Window x:Class="So17720970_RectangularBoublik.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        SizeToContent="WidthAndHeight">
    <Grid Width="500" Height="500">
        <Image Source="http://i.stack.imgur.com/Py65S.jpg"/>  <!-- image -->
        <Rectangle Fill="#AA000000">                          <!-- selection -->
            <Rectangle.Clip>
                <GeometryGroup FillRule="Nonzero">            <!-- selection clip: -->
                    <RectangleGeometry Rect="0 0 500 200"/>   <!--   top -->
                    <RectangleGeometry Rect="0 0 100 500"/>   <!--   left -->
                    <RectangleGeometry Rect="0 300 500 200"/> <!--   bottom -->
                    <RectangleGeometry Rect="400 0 100 500"/> <!--   right -->
                </GeometryGroup>
            </Rectangle.Clip>
        </Rectangle>
        <Rectangle StrokeThickness="1" Stroke="Black" StrokeDashArray="1 2" SnapsToDevicePixels="True"
                Margin="100 200 100 200"/>                    <!-- "ants" -->
    </Grid>
</Window>

#3


2  

You can use a combination of OpacityMask and DrawingBrush:

您可以使用一种组合光罩和拉拔刷:

XAML:

XAML:

<Grid Background="Gray">
    <Image Name="image"Source="...">
        <Image.OpacityMask>
            <DrawingBrush x:Name="mask"/>
        </Image.OpacityMask>
    </Image>
</Grid>

Code-behind:

后台代码:

    private void UpdateOpactiyMask()
    {
        Point topLeft = new Point();
        Point bottomRight = new Point(image.ActualWidth, image.ActualHeight);

        GeometryDrawing left = new GeometryDrawing();
        left.Brush = borderBrush;
        left.Geometry = new RectangleGeometry(new Rect(topLeft, new Point(SelectedArea.Left, bottomRight.Y)));

        GeometryDrawing right = new GeometryDrawing();
        right.Brush = borderBrush;
        right.Geometry = new RectangleGeometry(new Rect(new Point(SelectedArea.Right, topLeft.Y), bottomRight));

        GeometryDrawing top = new GeometryDrawing();
        top.Brush = borderBrush;
        top.Geometry = new RectangleGeometry(new Rect(new Point(SelectedArea.Left, topLeft.Y), new Point(SelectedArea.Right, SelectedArea.Top)));

        GeometryDrawing bottom = new GeometryDrawing();
        bottom.Brush = borderBrush;
        bottom.Geometry = new RectangleGeometry(new Rect(new Point(SelectedArea.Left, SelectedArea.Bottom), new Point(SelectedArea.Right, bottomRight.Y)));

        GeometryDrawing center = new GeometryDrawing();
        center.Brush = selectionBrush;
        center.Geometry = new RectangleGeometry(SelectedArea);

        DrawingGroup drawing = new DrawingGroup();
        drawing.Children.Add(left);
        drawing.Children.Add(right);
        drawing.Children.Add(top);
        drawing.Children.Add(bottom);
        drawing.Children.Add(center);

        mask.Drawing = drawing;
    }

SelectedArea is a Rect.

SelectedArea是一个矩形。

#4


1  

This is a variation on the solution using OpacityMask. Instead of doing it in the code, it is done in XAML. Also, it reverses the logic: instead of drawing 4 border rectangles, it draws 2 rectangles on top of each other. Finally, the important property of this solution is that the size of the central transparent rectangle is relative to the image size (rather than in absolute pixels). You do not need to know the actual image size or how it is stretched/positioned (particularly important for Stretch="Uniform"). Here, I have specified the image size (maskRect) as 1,1 and used fractional numbers as relative mask size and position (transpRect). You may as well specify the image size as 100,100 and use percentage values for the mask (or, even use the actual pixel values).

这是使用OpacityMask的溶液的变化。它不是在代码中执行,而是在XAML中执行。此外,它还颠倒了逻辑:它不是绘制4个边框,而是在每个边框上画2个矩形。最后,这个解决方案的重要特性是,*透明矩形的大小相对于图像大小(而不是绝对像素)。您不需要知道实际的图像大小或它是如何拉伸/定位的(对Stretch="Uniform"尤其重要)。在这里,我指定了图像大小(maskRect)为1,1,并使用小数作为相对掩码大小和位置(transpRect)。您也可以将图像大小指定为100,100,并对掩码使用百分比值(甚至使用实际的像素值)。

          <Grid Background="#FFF4F4F5" >
            <Image Name="PhotoImage" Source="...">
                <Image.OpacityMask>
                    <DrawingBrush>
                        <DrawingBrush.Drawing>
                            <DrawingGroup>
                                <GeometryDrawing>
                                    <GeometryDrawing.Geometry>
                                        <RectangleGeometry x:Name="maskRect" Rect="0,0,1,1"/>
                                    </GeometryDrawing.Geometry>
                                    <GeometryDrawing.Brush>
                                        <SolidColorBrush Color="#60000000" />
                                    </GeometryDrawing.Brush>
                                </GeometryDrawing>
                                <GeometryDrawing>
                                    <GeometryDrawing.Geometry>
                                        <RectangleGeometry x:Name="transpRect" Rect=".25,.20,.40,.40"/>
                                    </GeometryDrawing.Geometry>
                                    <GeometryDrawing.Brush>
                                        <SolidColorBrush Color="Black" />
                                    </GeometryDrawing.Brush>
                                </GeometryDrawing>
                            </DrawingGroup>
                        </DrawingBrush.Drawing>
                    </DrawingBrush>
                </Image.OpacityMask>
            </Image>
        </Grid>