1. 程式人生 > >WPF學習(14)-效果和視覺化物件

WPF學習(14)-效果和視覺化物件

       前面學過的形狀,包括Path構建複雜的圖形,當然可以完成我們的需求,可是有一個問題,當我們的內容元素又成百上千的形狀等組合起來的時候,這個會顯得非常讓人不可接受,特別是效能方面,所以自然而然就出現了視覺化物件。

        視覺化物件(Visual)這是一個抽象類,所以一般構建例項使用DrawingVisual這個類,特別需要說明的是,DrawingVisual必須提供宿主,不然他是沒有辦法顯示的,而這個宿主必須繼承自UIElement,這個就有很多了,比如Panel等都是他的子類,我們就可以去實現自己的宿主,宿主換句話解釋就是容器,視覺化物件,他是一個物件,要在前臺顯示,就需要一個容器。

       比如下面這個類就是我們實現的一個可以裝DrawingVisual物件的容器。

    

    class dwvisual:Panel
    {
        private List<Visual> visuals=new List<Visual>();
        protected override int VisualChildrenCount
        {
            get
            {
               // return base.VisualChildrenCount;
               return visuals.Count;
            
            }
        }
        protected override Visual GetVisualChild(int index)
        {
           // return base.GetVisualChild(index);
            return visuals[index];
        }
        public void AddVisual(Visual visual)
        {
            visuals.Add(visual);
            base.AddVisualChild(visual);
            base.AddLogicalChild(visual);

        }
        public void DeleteVisual(Visual visual)
        {
            visuals.Remove(visual);
            base.RemoveVisualChild(visual);
            base.RemoveLogicalChild(visual);
        }
        public DrawingVisual GetVisual(Point point)
        {
            HitTestResult hitResualt = VisualTreeHelper.HitTest(this, point);
            return hitResualt.VisualHit as DrawingVisual;
        }
    }

     裡面有幾個基本的方法和過載的欄位,其實也很好理解,就是加 DrawingVisual,刪DrawingVisual,找DrawingVisual,其中特別需要注意的是VisualChildrenCount和GetVisualChild,裡面有兩行被註釋掉的是VS給我們自動生成的,一定要自己寫完,不然前臺是顯示不了的。

     現在前臺就可以放一些物件啦,為了對比,我放一些普通控制元件然後普通形狀對比下視覺化控制元件。

     

    <Grid>
        <StackPanel>
            <DockPanel>
                <Button DockPanel.Dock="Left" Width="50" Content="Button" Click="Button_Click"/>
                <Button Content="Button" Width="50" Click="Button_Click_1"/>
            </DockPanel>
            <local:dwvisual x:Name="cvs" Height="200" ClipToBounds="True" Background="White" Visibility="Visible" ></local:dwvisual>
            <Canvas Name="cvs2" ></Canvas>
        </StackPanel>
    </Grid>

    點選按鈕畫圖,效果如下

      

     框框是DrawingVisual物件,線條是普通形狀。後臺程式碼如下

      

        private void Button_Click_1(object sender, RoutedEventArgs e)
        {
           DrawingVisual visual = new DrawingVisual();
           Brush brush = Brushes.LightGoldenrodYellow;
            using (DrawingContext dc = visual.RenderOpen())
            {
               
                Pen drawingPen = new Pen(Brushes.Red, 3);

                dc.DrawRectangle(brush, drawingPen,
                    new Rect(new Point(100, 100), new Size(50, 50)));
                dc.DrawText(new FormattedText("Hello, World!", CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface("Arial"), 10, Brushes.CornflowerBlue), new Point(0, 0));
            }
            cvs.AddVisual(visual);

        }


     private void Button_Click(object sender, RoutedEventArgs e)
        {
            Line l = new Line();
            l.X1 = 20;
            l.Y1 = 0;
            l.X2 = 100;
            l.Y2 = 100;
            l.Stroke = Brushes.Red;
            l.StrokeThickness = 10;
            cvs2.Children.Add(l);

        }

     對於普通的圖形介面,我覺得還是用形狀繪圖,然後封裝成控制元件使用,在裡面定義依賴屬性,封裝行為,基本已經夠用了,而有大量元素組成的圖形,包括需要數學運算的或者其他複雜需求的,那麼就用視覺化影象,比較效率在那。

     接下來就是效果,舉兩個例子,書裡面的。

               <Button Content="Button" Width="50" >
                    <Button.Effect>
                        <BlurEffect Radius="2"></BlurEffect>
                    </Button.Effect>
                </Button>
                <TextBlock>
                    <TextBlock.Effect>
                        <DropShadowEffect></DropShadowEffect>
                    </TextBlock.Effect>
                    奔騮科技真棒
                </TextBlock>

      一個是模糊效果,一個是陰影效果,很好理解,調他的引數就可以設定不同的效果了

       至於其他更復雜的效果,需要使用高階著色語言去弄了,這個就屬於DirectX的範疇了