2013-07-18 46 views
8

Chciałbym narysować prostokąt w WPF (według kodu) i wypełnić go na zewnątrz.Wypełnij zewnętrzną część prostokąta.

Oto przykład:

enter image description here

zewnętrzna prostokąta jest szary (o niskiej nieprzezroczystości) i wypełnienie prostokąta jest trasparent.

+0

Istnieje właściwość Klip, którą można manipulować w celu uzyskania pożądanego rezultatu. – Nitesh

Odpowiedz

5

Można również nałożyć obraz z półprzezroczystym Path elementu, który wykorzystuje CombinedGeometry które łączy jeden bardzo duży zewnętrzny prostokąt z wewnętrznym prostokąta:

<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> 

Teraz można programowo dostosować właściwość Rect elementu transparentRect w razie potrzeby.

+0

Twoja odpowiedź używa podświetlania składni C#. Jest to niepoprawne, ponieważ XAML to XML. Jednym z oczywistych problemów jest to, że elementy i atrybuty mają ten sam kolor. – Athari

2

Można użyć kombinacji OpacityMask i DrawingBrush:

XAML:

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

Code-tył:

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 jest Rect.

2

Można użyć UIElement.Clip właściwość:

<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> 
1

Jest to odmiana rozwiązania wykorzystująca OpacityMask. Zamiast robić to w kodzie, robi się to w XAML. Ponadto odwraca logikę: zamiast rysować 4 prostokąty obramowania, rysuje 2 prostokąty jeden na drugim. Wreszcie, ważną właściwością tego rozwiązania jest to, że rozmiar centralnego, przezroczystego prostokąta jest zależny od rozmiaru obrazu (a nie od bezwzględnych pikseli). Nie musisz znać rzeczywistego rozmiaru obrazu ani sposobu jego rozciągania/ustawiania (szczególnie ważne w przypadku Rozciągnięcia = "Jednolite"). Tutaj określiłem rozmiar obrazu (maskRect) jako 1,1 i użyłem liczb ułamkowych jako względnego rozmiaru i pozycji maski (transpRect). Równie dobrze możesz określić rozmiar obrazu jako 100,100 i użyć wartości procentowych maski (lub nawet użyć rzeczywistych wartości pikseli).

  <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>