主頁 > .NET開發 > 【WPF學習】第四十章 畫刷

【WPF學習】第四十章 畫刷

2020-09-11 05:20:37 .NET開發

  畫刷填充區域,不管是元素的背景色、前景色以及邊框,還是形狀的內部填充和筆畫(Stroke),最簡單的畫刷型別是SolidColorBrush,這種畫刷填充一種固定、連續的顏色,在XAML中設定形狀的Stroke或Fill屬性時,使用的是SolidColorBrush畫刷,他們在后臺完成繪制,

  下面是幾個與畫刷相關的更基本的方面:

  •   畫刷支持更改通知,因為他們繼承自Freezable類,因此,如果改變了畫刷,任何使用畫刷的元素都會自動重新繪制自身,
  •   畫刷支持部分透明,為此,只需要修改Opacity屬性,使背景能夠透過前面的內容進行顯示,
  •   通過SystemBrushes類可以訪問這樣的畫刷:此類畫刷使用Windows系統設定為當前計算機定義的首選顏色,

  SolidColorBrush畫刷無疑非常有用,但還有其他幾個繼承自System.Windows.Media.Brush的類,通過這些類可得到更新穎的效果,下表列出了所有這些類,

表 畫刷類

 一、SolidColorBrush畫刷

   在大多數控制元件中,通過設定Foreground屬性繪制文本顏色,并設定Background屬性繪制文本背后的空間,形狀使用類似但不同的屬性:Stroke屬性用于繪制形狀的邊框,而Fill屬性用于繪制形狀的內部,

  可在XAML中使用顏色名設定Stroke和Fill屬性,對于這種情況,WPF決議器自動創建匹配的SolidColorBrush物件,也可以使用代碼設定Stroke和Fill屬性,但需要顯示地創建SolidColorBrush物件,

//Create a brush from a named color:
cmd.Background=new SolidColorBrush(Colors.AliceBlue);

//Create a brush from a system color:
cmd.Background=SystemColors.ControlBrush;

//Create a brush from color values:
int red=0;int green=255; int blue=0;
cmd.Foreground=new SolidColorBrush(Color.FromRgb(red,green,blue));

二、LinearGradientBrush畫刷

  可通過LinearGradientBrush畫刷創建從一種顏色變化到另一種顏色的混合填充,

  下面可能是最簡單的漸變,該漸變從藍色(左上角)到白色(右下角)在對角線上對矩形進行著色,

<Rectangle Width="150" Height="100" Margin="5">
            <Rectangle.Fill>
                <LinearGradientBrush >
                    <GradientStop Color="Blue" Offset="0"/>
                    <GradientStop Color="White" Offset="1" />
                </LinearGradientBrush>
            </Rectangle.Fill>
        </Rectangle>

  為創建這種漸變效果,需要為每種顏色添加一個GradientStop物件,還需要在漸變中使用0~1的偏移值放置每種顏色,在該例中,用于藍色的GradientStop物件的偏移值為0,這意味著它被放在漸變的開頭,用于白色的GradientStop物件的偏移值為1,這意味著將它放在末尾,通過改變這些值,可調整漸變從一種顏色變化到另一種顏色的速度,例如,如果將白色的GradientStop設定為0.5,漸變就會在中間(兩個拐角的中點)從藍色(左上角)混合到白色,矩形的右邊將會是純白色的,

  上面的標記創建了從一個拐角拉伸到另一個拐角的物件填充漸變,然而,可能希望創建自上而下或從一邊向另一邊混合的漸變,或是使用不同的對角線角度,可使用LinearGradientBrush的StartPoint和EndPoint屬性控制這些細節,可以通過這些屬性選擇第一種顏色開始變化的點,以及最后一種顏色結束變化的點(中間的區域被漸變混合),但這里存在一個古怪的問題:用于開始點和結束點的坐標不是真實坐標,相反,LinearGradientBrush畫刷將點(0,0)指定為希望希望填充的區域的左上角,將點(1,1)指定為希望填充的區域的右下角,而不管該區域實際上有多高和多寬,

  為創建自上而下的橫向填充,可將用于左上角的(0,0)點作為開始點,并將(0,1)點作為結束點,該點表示左下角,為了創建從一邊到另一邊的垂直填充(不傾斜),可以使用點(0,0)作為開始點,并使用右上角的點(1,0)作為結束點,

  通過為漸變提供不是填充區域拐角點的開始點和結束點,可得到更靈活的漸變,例如,漸變可從點(0,0)拉伸到點(0,0.5),該點是左側邊緣上的中點,這會創建壓縮的線性漸變——一種顏色從頂部開始,在中間混合到第二種顏色,形狀的后半部分使用第二種顏色,但可用LinearGradientBrush.SpreadMethod屬性改變這種行為,默認情況下,該屬性使用Pad(這意味著漸變之外的區域使用恰當的純色填充),但也可使用Reflect(翻轉漸變,從第二種顏色反向漸變大偶第一種顏色)或Repeat(復制相同的顏色變化程序),

  LinearGradientBrush畫刷還可通過添加兩個以上的GradientStop物件,創建具有兩種以上的顏色漸變,例如,下面的漸變實作了彩虹效果:

<Rectangle Width="150" Height="100" Grid.Row="4" Margin="5">
            <Rectangle.Fill>
                <LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
                    <GradientStop Color="Yellow" Offset="0.0" />
                    <GradientStop Color="Red" Offset="0.25" />
                    <GradientStop Color="Blue" Offset="0.75" />
                    <GradientStop Color="LimeGreen" Offset="1.0" />
                </LinearGradientBrush>
            </Rectangle.Fill>
        </Rectangle>

  唯一的技巧是為每個GradientStop物件何止合適的偏移值,例如,如果希望變換經過5中顏色,可將第1中顏色的偏移值設定為0,第2中顏色的偏移值設定為0.25,將第3中顏色的偏移值設定為0.5,第4種顏色的偏移值設定為0.75,將第5中顏色的偏移值設定為1,或者如果希望開始時漸變速度較快,而在結束速度較慢,可將便宜值設定為0、0.1、0.2、0.4、0.6、1,

  下面是LinearGradientBrush畫刷的完整示例以及效果圖:

<Window x:Class="Drawing.Gradients"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Gradients" Height="587" Width="347">
    <Grid Margin="5">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition Height="Auto"></RowDefinition>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition></ColumnDefinition>
            <ColumnDefinition Width="Auto"></ColumnDefinition>
        </Grid.ColumnDefinitions>

        <Rectangle Width="150" Height="100" Margin="5">
            <Rectangle.Fill>
                <LinearGradientBrush >
                    <GradientStop Color="Blue" Offset="0"/>
                    <GradientStop Color="White" Offset="1" />
                </LinearGradientBrush>
            </Rectangle.Fill>
        </Rectangle>
        <TextBlock Grid.Column="1" VerticalAlignment="Center" Margin="5">Diagonal Linear Gradient</TextBlock>

        <Rectangle Width="150" Height="100" Margin="5" Grid.Row="1">
            <Rectangle.Fill>
                <LinearGradientBrush>
                    <GradientStop Color="Blue" Offset="0"/>
                    <GradientStop Color="White" Offset="0.5" />
                </LinearGradientBrush>
            </Rectangle.Fill>
        </Rectangle>
        <TextBlock Grid.Row="1" Grid.Column="1" VerticalAlignment="Center" Margin="5">With 0.5 Offset for White</TextBlock>

        <Rectangle Width="150" Height="100" Grid.Row="2" Margin="5">
            <Rectangle.Fill>
                <LinearGradientBrush StartPoint="0,0" EndPoint="0,1" >
                    <GradientStop Color="Blue" Offset="0"/>
                    <GradientStop Color="White" Offset="1" />
                </LinearGradientBrush>
            </Rectangle.Fill>
        </Rectangle>
        <TextBlock Grid.Row="2" Grid.Column="1" VerticalAlignment="Center" Margin="5">Horizontal Linear Gradient</TextBlock>

        <Rectangle Width="150" Height="100" Grid.Row="3" Margin="5">
            <Rectangle.Fill>
                <LinearGradientBrush StartPoint="0,0" EndPoint="0,0.5" SpreadMethod="Reflect">
                    <GradientStop Color="Blue" Offset="0"/>
                    <GradientStop Color="White" Offset="1" />
                </LinearGradientBrush>
            </Rectangle.Fill>
        </Rectangle>
        <TextBlock Grid.Row="3" Grid.Column="1" VerticalAlignment="Center" Margin="5">Reflected Gradient</TextBlock>

        <Rectangle Width="150" Height="100" Grid.Row="4" Margin="5">
            <Rectangle.Fill>
                <LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
                    <GradientStop Color="Yellow" Offset="0.0" />
                    <GradientStop Color="Red" Offset="0.25" />
                    <GradientStop Color="Blue" Offset="0.75" />
                    <GradientStop Color="LimeGreen" Offset="1.0" />
                </LinearGradientBrush>
            </Rectangle.Fill>
        </Rectangle>
        <TextBlock Grid.Row="4" Grid.Column="1" VerticalAlignment="Center" Margin="5">Multicolored Gradient</TextBlock>
    </Grid>
</Window>
Gradients

 

   漸變畫刷并不限于繪制形狀,可在使用SolidColorBrush畫刷的任何時候替代LinearGradientBrush——例如,填充元素的背景表面(使用Background屬性)、填充元素文本的前景色(使用Foreground屬性)或者填充邊框(使用BorderBrush屬性),如下示例所示:

<Window x:Class="Drawing.GradientText"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="GradientText" Height="300" Width="300">
    <Grid>
        <TextBlock Margin="5"  FontWeight="Bold" FontSize="65" TextWrapping="Wrap" TextAlignment="Center">
            <TextBlock.Text>This text uses a gradient.</TextBlock.Text>
            <TextBlock.Foreground>
                <LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
                    <GradientStop Color="Yellow" Offset="0.0" />
                    <GradientStop Color="Red" Offset="0.25" />
                    <GradientStop Color="Blue" Offset="0.75" />
                    <GradientStop Color="LimeGreen" Offset="1.0" />
                </LinearGradientBrush>
            </TextBlock.Foreground>
        </TextBlock>
    </Grid>
</Window>
GradientText

三、RadialGradientBrush畫刷

  RadialGradientBrush畫刷和LinearGradientBrush畫刷的作業方式類似,也使用一系列具有不同偏移值的顏色,與LinearGradientBrush畫刷一樣,可使用希望的任意多種顏色,區域是放置漸變的方式,

  為指定第一種顏色在漸變中的開始點,需要使用GradientOrigin屬性,默認情況下,漸變的開始點是(0.5,0.5),該點表示填充區域的中心,

  漸變從開始點以環形的方式向外輻射,漸變最終到達內部漸變圓的邊緣,這里是漸變的終點,根據所期望的效果,漸變圓的中心可能和漸變開始點對齊,也可能和漸變開始點不對齊,超出內部漸變圓的區域以及填充區域的最外側邊緣,使用在RadialGradientBrush.GradientStops集合中定義的最后一種顏色進行純色填充,

  可使用三個屬性設定內部漸變圓的邊界:Center、RadiusX和RadiusY,默認情況下,Center屬性被設定為(0.5,0.5),該設定將限定圓的中心放在填充區域的中央,并且該點同時也是漸變開始點,

  RadiusX和RadiusY屬性 決定了限定圓的尺寸,默認情況下著兩個屬性都被設定為0.5.這些值可能不夠直觀,因為他們根據填充區域的對角范圍(一條從填充區域的左上角延伸到右下角的假想線的長度)進行度量,這意味著半徑0.5定義了一個圓,該圓的半徑是對角線長度的一半,如果填充區域為正方形,使用勾股定理可計算出,該長度大約是填充區域寬度(或寬度)的0.7倍,因此,如果用默認設定填充正方形區域,漸變就從中心點開始,并拉伸大約正方形寬度0.7倍的距離到達最外側邊界,

  對于填充圓形形狀并創建發光效果,徑向漸變是非常好的選擇(水平高超的美工人員通過組合使用漸變創建具有光暈效果的按鈕),一種常見技巧是稍微偏移GradientOrigin點,為形狀創建深度感,

<Window x:Class="Drawing.RadialGradient"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="RadialGradient" Height="534" Width="480">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition></RowDefinition>
            <RowDefinition></RowDefinition>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition></ColumnDefinition>
            <ColumnDefinition Width="Auto"></ColumnDefinition>
        </Grid.ColumnDefinitions>
        <Ellipse Margin="5" Stroke="Black" StrokeThickness="1">
            <Ellipse.Fill>
                <RadialGradientBrush RadiusX="1" RadiusY="1" >
                    <GradientStop Color="White" Offset="0"/>
                    <GradientStop Color="Blue" Offset="1"/>
                </RadialGradientBrush>
            </Ellipse.Fill>
        </Ellipse>
        <TextBlock Grid.Column="1" VerticalAlignment="Center" Margin="5">A Radial Gradient</TextBlock>

        <Ellipse Margin="5" Grid.Row="1" Stroke="Black" StrokeThickness="1">
            <Ellipse.Fill>
                <RadialGradientBrush
             RadiusX="1" RadiusY="1" GradientOrigin="0.7,0.3"
            >
                    <GradientStop Color="White" Offset="0" />
                    <GradientStop Color="Blue" Offset="1" />
                </RadialGradientBrush>

            </Ellipse.Fill>
        </Ellipse>
        <TextBlock Grid.Row="1" Grid.Column="1" VerticalAlignment="Center" Margin="5" TextWrapping="Wrap">A Radial Gradient with an Offset Center</TextBlock>

    </Grid>
</Window>
RadialGradient

 

 四、ImageBrush畫刷

  可通過ImageBrush畫刷使用位圖填充區域,可使用最常見的檔案型別,包括BMP、PNG、GIF以及JPEG檔案,可通過設定ImageSource屬性來制定希望使用的影像,例如,下面的畫刷使用一幅名為logo.jpg的影像繪制Grid面板的背景,在程式集中作為資源包含了該影像:

<Grid>
        <Grid.Background>
            <ImageBrush  ImageSource="logo.jpg" />
        </Grid.Background>    
    </Grid>

  ImageBrush.ImageSource屬性和Image元素的Source屬性的作業方式相同,這意味著也可以使用指向資源、外部檔案或Web站點的URI設定ImageSource屬性,也可通過為ImageSource屬性提供DrawingImage物件,創建使用由XAML定義的矢量內容的ImageBrush畫刷,可通過這種方法降低開銷(通過避免使用更耗資源的Shape類的派生類),或使用矢量影像創建平鋪模式,

  在該例中,ImageBrush畫刷用于繪制單元格的背景,因此,為了適應填充區域,影像會被拉伸,如果Grid面板比影像的原始尺寸大,就會看到改變影像尺寸造成的顯示問題(如常見的模糊效果),如果Grid面板的形狀和影像的寬高比不匹配,為了適應Grid面板,影像會變形,

  為控制該行為,可修改ImageBrush.Stretch屬性,例如,可將該屬性設定為Uniform,從而為了適應縮放影像時保持影像的高寬比,或將該屬性設定為None,使用影像的自然尺寸繪制影像(對于這種情況,為適應容器,部分影像可能被裁減掉),

  如果繪制的影像比填充區域小,影像會根據AlignmentX和AlignmentY屬性進行對齊,未填充的區域保持透明,當使用Uniform設定進行縮放,并且填充區域的形狀不同時,就會出現這種情況,如果將Stretch屬性設定為None,并且填充區域比影像大,也會出現這種情況,

  還可使用Viewbox屬性從影像上裁剪有興趣使用的一小部分,為此,需要指定4個數值以描述希望從源圖上裁剪并使用的矩形部分,前連個數值指定矩形開始的左上角,而后兩個數值指定矩形的寬度和高度,唯一的問題是Viewbox屬性使用的是相對坐標系統,就像漸變畫刷使用的坐標系統那樣,這一坐標系統將影像上的左上角指定為(0,0),將右下角指定為(1,1),

  為理解Viewbox屬性的作業原理,分析下面的標記:

<ImageBrush ImageSource="logo.jpg" Stretch="Uniform"
    Viewbox="0.4 0.5 0.2 0.2"></ImageBrush>

  現在,Viewbox屬性從(0.4,0.5)開始,這差不多是用影像的一半出開始(從技術角度看,X坐標是寬度的0.4倍,Y坐標是高度的0.5倍),然后伸展矩形以填充一個20%寬度和20%高度的小方塊作為整幅影像(從技術角度看,矩形的長度為影像寬度的0.2倍,矩形的高度為影像高度的0.2倍),根據Stretch、AlignmentX以及AlignmentY屬性的設定,被裁剪下來的部分影像會被拉伸或劇中顯示,下圖顯示兩個使用不同ImageBrush物件填充自身的矩形,最上面的矩形顯示了整幅影像,下面的矩形使用Viewbox放大了影像中的一小部分,這兩個矩形都使用了純黑色的邊框,

<Window x:Class="Drawing.ImageBrushes"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="ImageBrushes" Height="389.6" Width="419.6">
    <Canvas>
        <Rectangle Canvas.Left="10" Canvas.Top="10"  Width="271" Height="100" Stroke="Black">
            <Rectangle.Fill>
                <ImageBrush ImageSource="logo.jpg" Stretch="Fill"></ImageBrush>
            </Rectangle.Fill>
        </Rectangle>
        <Rectangle Canvas.Left="10" Canvas.Top="120" Width="200" Height="200" Stroke="Black">
            <Rectangle.Fill>
                <ImageBrush ImageSource="logo.jpg" Stretch="Uniform"
    Viewbox="0.4 0.5 0.2 0.2"></ImageBrush>
            </Rectangle.Fill>
        </Rectangle>
    </Canvas>
</Window>
ImageBrushes

 

 五、平鋪的ImageBrush畫刷

  除普遍的ImageBrush畫刷外,還有其他令人更加激動的內容,可通過在畫刷的表面平鋪影像來得到一些有趣的效果,

  當平鋪影像時,有兩種選擇:

  •   按比例平鋪,填充區域始終具有相同數量的平鋪影像,為適應填充區域,平鋪的影像會擴展或收縮,
  •   按固定尺寸平鋪,平鋪影像始終具有相同的尺寸,填充區域的尺寸決定了顯示的平鋪影像的數量,

  為了平鋪一幅影像,需要設定ImageSource屬性(指定希望平鋪的影像)以及ViewPort、ViewportUnits與TitleMode屬性,后三個屬性決定了平鋪影像的尺寸和排列方式,

  可使用Viewport屬性設定每幅平鋪影像的尺寸,為使用按比例平鋪模式,必須將ViewportUnits屬性這是為RelativeToBoundingBox(默認值),然后使用在兩個方向上的坐標范圍都是從0到1的按比例坐標定義平鋪影像的尺寸,換句話說,如果一幅平鋪影像的左上角位于(0,0),右下角位于(1,1),就會占據整個填充區域,為得到平鋪模式,為Viewport屬性設定的值應當比整個填充區域的尺寸小,如下所示:

<ImageBrush ImageSource="tile.jpg" TileMode="Tile"
                     Viewport="0 0 0.5 0.5"></ImageBrush>

  上面的標記創建了一個從填充區域的左上角(0,0)開始,并拉伸到中間點(0.5,0.5)的Viewport方框,因此,不管填充區域的大小如何,填充區域始終包含4幅平鋪影像,這樣行為非常好,因為可確保平鋪影像不會在形狀的邊緣被裁減(當然,如果使用ImageBrush畫刷填充非矩形區域,影像仍會被裁剪),

  因為這個示例中的平鋪影像采用相對于填充區域的尺寸,所以更大的填充區域會使用更大的平鋪影像,并且因為改變了影像的尺寸,所以會造成一定的模糊效果,此外,如果填充區域不是完美的正方形,相對坐標系統會相應地進行行擠壓,從而每個平鋪的正方形都會變成矩形,

  可通過修改Stretch屬性(默認設定為Fill)改變這種行為,如果將該屬性設定為None,可保證平鋪影像永不變形,并且保持正確的形狀,然而,如果填充區域不是正方形,將在平鋪影像之間顯示空白空間,

  第三種選擇是將Stretch屬性設定為UniformToFill這種設定會根據需要裁減平鋪的影像,使用這種方式,平鋪影像會保持正確的縱橫比,而且平鋪的影像之間沒有空白空間,然而,如果填充的區域不是正方形,就不會看到完整的平鋪影像,

  自動改變平鋪影像的尺寸是一項非常有用的功能,但也是需要付出代價,有些位圖可能不能正確地改變其尺寸,在某種程度上,可通過提供比所需位圖更大的位圖,為應對這種情況做好準備,當當縮小影像時,這種技術就會導致更模糊的位圖,

  另一種定義平鋪影像的尺寸的方法是根據原始影像的尺寸使用絕對坐標,為此,將ViewportUnits屬性設定為Absolute,下面舉一個示例,該例將每幅平鋪影像定義為32X32單位大小,并從左上角開始平鋪:

<ImageBrush ImageSource="tile.jpg" TileMode="Tile"
                            ViewboxUnits="Absolute" Viewbox="0 0 32 32"/>

  這種模式的缺點就是填充區域的高度和寬度必須能被32整除,否則,在填充區域便于就會顯示部分平鋪影像,如果使用ImageBrush畫刷填充可改變尺寸的元素,就無法避免該問題,所以必須接受平鋪影像未必能與填充區域的邊緣對齊這種情況,

  下面是上面示例的完整XAML:

<Window x:Class="Drawing.TileTypes"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="TileTypes" Height="500" Width="296.8">
    <Grid Margin="5">
        <Grid.RowDefinitions>
            <RowDefinition></RowDefinition>
            <RowDefinition></RowDefinition>
            <RowDefinition></RowDefinition>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition />
        </Grid.ColumnDefinitions>

        <TextBlock Margin="3">固定尺寸<LineBreak></LineBreak>平鋪</TextBlock>
        <Rectangle Grid.Column="1" Stroke="Black">
            <Rectangle.Fill>
                <ImageBrush ImageSource="tile.jpg" TileMode="Tile"
                            ViewboxUnits="Absolute" Viewbox="0 0 32 32"/>
            </Rectangle.Fill>
        </Rectangle>

        <TextBlock Grid.Row="1" Margin="3">按比例<LineBreak></LineBreak>平鋪</TextBlock>
        <Rectangle Grid.Row="1" Grid.Column="1" Stroke="Black">
            <Rectangle.Fill>
                <ImageBrush ImageSource="tile.jpg" TileMode="Tile"
                     Viewport="0 0 0.5 0.5"></ImageBrush>
            </Rectangle.Fill>
        </Rectangle>

        <TextBlock Grid.Row="2" Margin="3">
      按比例<LineBreak></LineBreak>平鋪(無拉伸)
        </TextBlock>
        <Rectangle Grid.Row="2" Grid.Column="1" Stroke="Black">
            <Rectangle.Fill>
                <ImageBrush ImageSource="tile.jpg" TileMode="Tile" Stretch="None"
                    Viewport="0 0 0.5 0.5"></ImageBrush>
            </Rectangle.Fill>
        </Rectangle>
    </Grid>
</Window>
TileTypes

  下表列出了TileMode列舉值得所有選項.

表 TileMode列舉值

 

   如果需要 使平鋪影像更無縫地混合,翻轉行為通常是有用的,例如,如果使用FlipX,相鄰的平鋪影像總可以無縫地排列,下面舉例說明一下,

<Window x:Class="Drawing.TileFlip"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="TileFlip" Height="300" Width="300">
    <!-- Overlay labels by putting one UniformGrid on top of another. -->
    <Grid>
        <UniformGrid>
            <Rectangle Stroke="Black">
                <Rectangle.Fill>
                    <ImageBrush ImageSource="tile.jpg" TileMode="Tile" 
                    ViewportUnits="Absolute" Viewport="0 0 37 37"></ImageBrush>
                </Rectangle.Fill>
            </Rectangle>
            <Rectangle Stroke="Black">
                <Rectangle.Fill>
                    <ImageBrush ImageSource="tile.jpg" TileMode="FlipX"
                    ViewportUnits="Absolute" Viewport="0 0 37 37"></ImageBrush>
                </Rectangle.Fill>
            </Rectangle>
            <Rectangle Stroke="Black">
                <Rectangle.Fill>
                    <ImageBrush ImageSource="tile.jpg" TileMode="FlipY"
                    ViewportUnits="Absolute" Viewport="0 0 37 37"></ImageBrush>
                </Rectangle.Fill>
            </Rectangle>
            <Rectangle Stroke="Black">
                <Rectangle.Fill>
                    <ImageBrush ImageSource="tile.jpg" TileMode="FlipXY"
                    ViewportUnits="Absolute" Viewport="0 0 37 37"></ImageBrush>
                </Rectangle.Fill>
            </Rectangle>
        </UniformGrid>
        <UniformGrid>
            <UniformGrid.Resources>
                <Style TargetType="{x:Type TextBlock}">
                    <Setter Property="HorizontalAlignment" Value="Center"></Setter>
                    <Setter Property="VerticalAlignment" Value="Bottom"></Setter>
                    <Setter Property="FontSize" Value="25"></Setter>
                    <Setter Property="FontWeight" Value="Bold"></Setter>
                    <Setter Property="Margin" Value="3"></Setter>
                </Style>
            </UniformGrid.Resources>
            <TextBlock>Tile</TextBlock>
            <TextBlock>FlipX</TextBlock>
            <TextBlock>FlipY</TextBlock>
            <TextBlock>FlipXY</TextBlock>
        </UniformGrid>
    </Grid>
</Window>
TileFlip

 

 六、VisualBrush畫刷

  VisualBrush畫刷不常用,使用這種畫刷獲取元素的可視化內容,并使用該內容填充任意表面,例如,可使用VisualBrush畫刷將視窗中某個按鈕的外觀復制到同一個視窗中的其他位置,然而,復制的按鈕不能被單擊,也不能通過任何方式與其進行互動,在此就復制了元素的外觀,例如,下面的標記片段定義了一個按鈕和用于復制該按鈕的VisualBrush畫刷:

 <Button Name="cmd" Margin="3" Padding="5">Is this a real button?</Button>
        <Rectangle Margin="3" Height="{Binding ElementName=cmd,Path=ActualHeight}">
            <Rectangle.Fill>
                <VisualBrush Visual="{Binding ElementName=cmd}"></VisualBrush>
            </Rectangle.Fill>
</Rectangle>

  盡管可在VisualBrush本身定義希望使用的元素,但通常使用系結運算式參考當前視窗中的額元素,如本例所示,下圖顯示了原始按鈕(在視窗頂部)和幾個形狀不同的區域,這些區域是用基于按鈕的VisualBrush畫刷繪制的,完整XAML如下所示:

<Window x:Class="Drawing.VisualBrush"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="VisualBrush" Height="300" Width="300">
    <StackPanel Margin="3">
        <Button Name="cmd" Margin="3" Padding="5">Is this a real button?</Button>
        <Rectangle Margin="3" Height="{Binding ElementName=cmd,Path=ActualHeight}">
            <Rectangle.Fill>
                <VisualBrush Visual="{Binding ElementName=cmd}"></VisualBrush>
            </Rectangle.Fill>
        </Rectangle>
        <Rectangle Margin="3" Height="50">
            <Rectangle.Fill>
                <VisualBrush Visual="{Binding ElementName=cmd}"></VisualBrush>
            </Rectangle.Fill>
        </Rectangle>
        <Rectangle Margin="3" Height="150">
            <Rectangle.Fill>
                <VisualBrush Visual="{Binding ElementName=cmd}"></VisualBrush>
            </Rectangle.Fill>
        </Rectangle>
    </StackPanel>
</Window>
VisualBrush

 

   VisualBrush監視元素外觀的變化,例如,如果復制某個按鈕的可視化外觀,而且此外按鈕收到焦點,VisualBrush畫刷會使用新的可視化內容重新繪制填充區域——一個具有焦點的按鈕,VisualBrush類繼承自TileBrush類,因此,VisualBrush類也支持所有的裁剪、拉伸以及翻轉等特性,

七、BitmapCacheBrush畫刷

  BitmapCacheBrush畫刷在許多方面和VisualBrush畫刷類似,盡管VisualBrush類提供了用于參考其他元素的Visual屬性,但BitmapCacheBrush類提供了與此作用相同的Target屬性,

  兩者之間的關鍵區別是,BitmapCacheBrush畫刷采用可視化內容(這些內容以及通過變換、裁剪、效果以及透明設定進行了改變)并要求顯卡在顯存中存盤該內容,這樣一來,當需要時可快速地重新繪制內容,而不必要求WPF執行任何額外的作業,

  為配置位圖快取,設定BitmapCacheBrush.BitmapCache屬性(使用可預先確定的BitmapCache物件),下面是最簡單的用法:

<Button Name="cmd" Margin="3" Padding="5">Is this a real button?</Button>
        <Rectangle Margin="3" Height="{Binding ElementName=cmd,Path=ActualHeight}">
            <Rectangle.Fill>
                <BitmapCacheBrush Target="{Binding ElementName=cmd}">
                </BitmapCacheBrush>
            </Rectangle.Fill>
        </Rectangle>

  BitmapCacheBrush畫刷存在嚴重缺點:渲染位圖以及將其復制到顯存的初始化步驟需要比較短但可察覺到得額外時間,如果在視窗中使用BitmapCacheBrush畫刷,在視窗第一次繪制自身之前,當渲染BitmapCacheBrush并復制其位圖時,將會注意到延遲,因此,在傳統視窗中,BitmapCacheBrush起不到多大的幫助作用,

  然而,如果在用戶界面中大量使用影片,值得考慮使用位圖快取,這是因為影片會強制視窗在沒一秒內重新繪制多次,如果具有復雜的矢量內容,從快取位圖中繪制視窗內容比從頭重新繪制視窗要快,但即使是這種情況,也不應當立即使用BitmapCacheBrush畫刷,可能更愿意通過為每個希望快取的元素設定更高級的UIElement.CacheMode屬性來應用快取,對于這種情況,WPF在后臺使用BitmapCacheBrush畫刷獲取相同的效果,但需要做的作業更少,

  根據這些細節,BitmapCacheBrush畫刷本身好像不是很有用,然而,如果需要在幾個地方繪制單塊復雜的可視化內容,使用BitmapCacheBrush畫刷是合理的,對于這種情況,通過使用BitmapCacheBrush畫刷快取整個可視化內容比單獨快取每個元素更節省記憶體,在此輸出,這種節省可能得不償失,除非用戶界面還使用了影片,

 

轉載請註明出處,本文鏈接:https://www.uj5u.com/net/4466.html

標籤:WPF

上一篇:使用ASP.NET Core 3.x 構建 RESTful API - 3.4 內容協商

下一篇:【WPF學習】第四十一章 變換

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • WebAPI簡介

    Web體系結構: 有三個核心:資源(resource),URL(統一資源識別符號)和表示 他們的關系是這樣的:一個資源由一個URL進行標識,HTTP客戶端使用URL定位資源,表示是從資源回傳資料,媒體型別是資源回傳的資料格式。 接下來我們說下HTTP. HTTP協議的系統是一種無狀態的方式,使用請求/ ......

    uj5u.com 2020-09-09 22:07:47 more
  • asp.net core 3.1 入口:Program.cs中的Main函式

    本文分析Program.cs 中Main()函式中代碼的運行順序分析asp.net core程式的啟動,重點不是剖析原始碼,而是理清程式開始時執行的順序。到呼叫了哪些實體,哪些法方。asp.net core 3.1 的程式入口在專案Program.cs檔案里,如下。ususing System; us ......

    uj5u.com 2020-09-09 22:07:49 more
  • asp.net網站作為websocket服務端的應用該如何寫

    最近被websocket的一個問題困擾了很久,有一個需求是在web網站中搭建websocket服務。客戶端通過網頁與服務器建立連接,然后服務器根據ip給客戶端網頁發送資訊。 其實,這個需求并不難,只是剛開始對websocket的內容不太了解。上網搜索了一下,有通過asp.net core 實作的、有 ......

    uj5u.com 2020-09-09 22:08:02 more
  • ASP.NET 開源匯入匯出庫Magicodes.IE Docker中使用

    Magicodes.IE在Docker中使用 更新歷史 2019.02.13 【Nuget】版本更新到2.0.2 【匯入】修復單列匯入的Bug,單元測驗“OneColumnImporter_Test”。問題見(https://github.com/dotnetcore/Magicodes.IE/is ......

    uj5u.com 2020-09-09 22:08:05 more
  • 在webform中使用ajax

    如果你用過Asp.net webform, 說明你也算是.NET 開發的老兵了。WEBform應該是2011 2013左右,當時還用visual studio 2005、 visual studio 2008。后來基本都用的是MVC。 如果是新開發的專案,估計沒人會用webform技術。但是有些舊版 ......

    uj5u.com 2020-09-09 22:08:50 more
  • iis添加asp.net網站,訪問提示:由于擴展配置問題而無法提供您請求的

    今天在iis服務器配置asp.net網站,遇到一個問題,記錄一下: 問題:由于擴展配置問題而無法提供您請求的頁面。如果該頁面是腳本,請添加處理程式。如果應下載檔案,請添加 MIME 映射。 WindowServer2012服務器,添加角色安裝完.netframework和iis之后,運行aspx頁面 ......

    uj5u.com 2020-09-09 22:10:00 more
  • WebAPI-處理架構

    帶著問題去思考,大家好! 問題1:HTTP請求和回傳相應的HTTP回應資訊之間發生了什么? 1:首先是最底層,托管層,位于WebAPI和底層HTTP堆疊之間 2:其次是 訊息處理程式管道層,這里比如日志和快取。OWIN的參考是將訊息處理程式管道的一些功能下移到堆疊下端的OWIN中間件了。 3:控制器處理 ......

    uj5u.com 2020-09-09 22:11:13 more
  • 微信門戶開發框架-使用指導說明書

    微信門戶應用管理系統,采用基于 MVC + Bootstrap + Ajax + Enterprise Library的技術路線,界面層采用Boostrap + Metronic組合的前端框架,資料訪問層支持Oracle、SQLServer、MySQL、PostgreSQL等資料庫。框架以MVC5,... ......

    uj5u.com 2020-09-09 22:15:18 more
  • WebAPI-HTTP編程模型

    帶著問題去思考,大家好!它是什么?它包含什么?它能干什么? 訊息 HTTP編程模型的核心就是訊息抽象,表示為:HttPRequestMessage,HttpResponseMessage.用于客戶端和服務端之間交換請求和回應訊息。 HttpMethod類包含了一組靜態屬性: private stat ......

    uj5u.com 2020-09-09 22:15:23 more
  • 部署WebApi隨筆

    一、跨域 NuGet參考Microsoft.AspNet.WebApi.Cors WebApiConfig.cs中配置: // Web API 配置和服務 config.EnableCors(new EnableCorsAttribute("*", "*", "*")); 二、清除默認回傳XML格式 ......

    uj5u.com 2020-09-09 22:15:48 more
最新发布
  • C#多執行緒學習(二) 如何操縱一個執行緒

    <a href="https://www.cnblogs.com/x-zhi/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/2943582/20220801082530.png" alt="" /></...

    uj5u.com 2023-04-19 09:17:20 more
  • C#多執行緒學習(二) 如何操縱一個執行緒

    C#多執行緒學習(二) 如何操縱一個執行緒 執行緒學習第一篇:C#多執行緒學習(一) 多執行緒的相關概念 下面我們就動手來創建一個執行緒,使用Thread類創建執行緒時,只需提供執行緒入口即可。(執行緒入口使程式知道該讓這個執行緒干什么事) 在C#中,執行緒入口是通過ThreadStart代理(delegate)來提供的 ......

    uj5u.com 2023-04-19 09:16:49 more
  • 記一次 .NET某醫療器械清洗系統 卡死分析

    <a href="https://www.cnblogs.com/huangxincheng/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/214741/20200614104537.png" alt="" /&g...

    uj5u.com 2023-04-18 08:39:04 more
  • 記一次 .NET某醫療器械清洗系統 卡死分析

    一:背景 1. 講故事 前段時間協助訓練營里的一位朋友分析了一個程式卡死的問題,回過頭來看這個案例比較經典,這篇稍微整理一下供后來者少踩坑吧。 二:WinDbg 分析 1. 為什么會卡死 因為是表單程式,理所當然就是看主執行緒此時正在做什么? 可以用 ~0s ; k 看一下便知。 0:000> k # ......

    uj5u.com 2023-04-18 08:33:10 more
  • SignalR, No Connection with that ID,IIS

    <a href="https://www.cnblogs.com/smartstar/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/u36196.jpg" alt="" /></a>...

    uj5u.com 2023-03-30 17:21:52 more
  • 一次對pool的誤用導致的.net頻繁gc的診斷分析

    <a href="https://www.cnblogs.com/dotnet-diagnostic/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/3115652/20230225090434.png" alt=""...

    uj5u.com 2023-03-28 10:15:33 more
  • 一次對pool的誤用導致的.net頻繁gc的診斷分析

    <a href="https://www.cnblogs.com/dotnet-diagnostic/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/3115652/20230225090434.png" alt=""...

    uj5u.com 2023-03-28 10:13:31 more
  • C#遍歷指定檔案夾中所有檔案的3種方法

    <a href="https://www.cnblogs.com/xbhp/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/957602/20230310105611.png" alt="" /></a&...

    uj5u.com 2023-03-27 14:46:55 more
  • C#/VB.NET:如何將PDF轉為PDF/A

    <a href="https://www.cnblogs.com/Carina-baby/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/2859233/20220427162558.png" alt="" />...

    uj5u.com 2023-03-27 14:46:35 more
  • 武裝你的WEBAPI-OData聚合查詢

    <a href="https://www.cnblogs.com/podolski/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/616093/20140323000327.png" alt="" /><...

    uj5u.com 2023-03-27 14:46:16 more