程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> WPF自定義控件 - 自繪篇

WPF自定義控件 - 自繪篇

編輯:關於.NET

首先我們來說最簡單的畫面的呈現。

一.在自定義控件上畫矩形

增加一個自定義控件類:

打開創建的類重載OnRender函數並注釋掉靜態構造函數,代碼如下

public class CustomerRender : Control
    {

        //static CustomerRender()

        //{

        // DefaultStyleKeyProperty.OverrideMetadata(typeof (CustomerRender), new FrameworkPropertyMetadata(typeof (CustomerRender)));

        //}

        protected override void OnRender(DrawingContext  drawingContext)
        {

            drawingContext.DrawRectangle(Brushes.Bisque,  null, new Rect(0, 0, 50, 50));

        }

    }

在Window1這個類中修改如下

public  partial class Window1 : Window
    {

        public Window1()
        {

            InitializeComponent();

            CustomerRender customerRender = new  CustomerRender();

            customerRender.Width = 200;

            customerRender.Height = 300;

            this.Content = customerRender;

        }

    }

運行程序我們可以看到:

當然你還可以通過drawingContext來畫圓圈、不規則矩形、圓角矩形 和寫文字等等。具體可以看DrawingContext 中的API介紹和MSDN文檔。

二.拖動矩形

一般來說UI是數據的反應,UI的變化其實是後段數據的變化 。我們一般在移動到方塊上方後,按住鼠標開始拖動,那麼在鼠標移動上去之後 ,我們首先判斷此位置是否有矩形,點擊鼠標的時候,我們記錄點下的這個坐標 為A,鼠標移動的時候我們根據移動時候鼠標所在坐標和原來的A坐標比較,然後 把這個差值和矩形的開始坐標相加,通過InvalidateVisual()方法不斷重畫就達 到了移動的效果。

如果你需要鼠標移動出窗口還可以移動該矩形請加CaptureMouse()來 鎖定當前鼠標,但不要忘記在鼠標放開的時候把它給釋放掉 ReleaseMouseCapture()。

我們在window類中為我們的控件賦上底色

InitializeComponent();

CustomerRender customerRender = new CustomerRender();

customerRender.Width = 200;

customerRender.Height = 300;

customerRender.Background = Brushes.Green;

this.Content = customerRender;

並在控件的OnRender函數中 加入

drawingContext.DrawRectangle(Background, null,new Rect(new Point(0,0),this.RenderSize));

效果如圖:

這時你拖動方塊可能會發現方塊可以被移出背景,這在WPF下是允許的 ,但有時候這又不符合情理,我們需要把多余的部分裁減掉。

protected override void OnRender(DrawingContext  drawingContext)
        {
            Rect rect = new Rect(new Point(0, 0),  this.RenderSize);

            drawingContext.DrawRectangle(Background,  null, rect);

            //創建一個填充色為Bisque邊框色為Orange,橫坐標 為2,縱坐標為3,寬度為80,長度為50的矩形

            Pen pen = new Pen(Brushes.Orange, 1);

            pen.Freeze();//凍結可以加快呈現速度

            RectangleGeometry rectangleGeometry = new  RectangleGeometry(rect);
            rectangleGeometry.Freeze();

            drawingContext.PushClip(rectangleGeometry);

            drawingContext.DrawRectangle(Brushes.Bisque,  pen, _rectangle);

            drawingContext.Pop();
        }

主要注意drawingContext.PushClip (rectangleGeometry);到drawingContext.Pop();之間是剪切的有效范圍。

Pop()結束符不僅僅用於剪切,還適用於遮幕,Effect效果等有Push開頭 的那些玩藝。(關於GuidelineSet推薦一個網址: http://www.wpftutorial.net/DrawOnPhysicalDevicePixels.html)

剪切 後的效果如下:

三.動畫效果

當然我們也可以做些拖動預覽效果如 下:

實現的原理無非是拖動的時候畫一個假矩形,並把該矩形呈現的代碼 放在剪切的效果之外,拖動結束後把假的位置給真的調用重畫一遍就實現了。

我們能不能用動畫效果使得矩形慢慢移動到指定位置,答案當然是肯定 的。這裡可以用System.Windows.Media.Animation命名空間下的一些方法來實現

RectAnimation rectAnimation = new RectAnimation

(_rectangle,_preivewRectangle,new Duration(TimeSpan.FromMilliseconds (600)));

drawingContext.DrawRectangle(Brushes.Bisque, pen,  _rectangle,rectAnimation.CreateClock());

你也可以用來做顏 色的變換,大小的變化等等。

四.多個矩形

有多個矩形可以把矩 形放到一個集合中依次判斷,層疊的話就是後段數據存放的先後順序問題,UI顯 示的快慢和後段數據查找有直接的聯系,這個也是算法的價值體現。

小 結

這裡講的做法也是winform裡的大多數實現方式,只不過WPF使得我們 對像素處理關心的更少,自繪在WPF的應用中相對winform要少了很多,除非用在 大數據量的地方,WPF復合控件能完成大部分的需求——只要你能熟 練定義樣式,並了解可視樹,邏輯樹,以及各個控件的用法。

本文配套源碼

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved