zoukankan      html  css  js  c++  java
  • WPF自定义控件 —— 自绘篇

    一般来说控件主要是画面呈现、事件的处理、布局自动化,当然完善的控件还应该牵涉设计时、UI自动化测试的定义。

    首先我们来说最简单的画面的呈现。

    一.在自定义控件上画矩形

    增加一个自定义控件类:  

    image

    打开创建的类重载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, 
    nullnew Rect(005050));

            }

        }

    在Window1这个类中修改如下

        public partial class Window1 : Window
        {

            
    public Window1()
            {

                InitializeComponent();

                CustomerRender customerRender 
    = new CustomerRender();

                customerRender.Width 
    = 200;

                customerRender.Height 
    = 300;

                
    this.Content = customerRender;

            }

        }

    运行程序我们可以看到:

    image

    当然你还可以通过drawingContext来画圆圈、不规则矩形、圆角矩形和写文字等等。具体可以看DrawingContext 中的API介绍和MSDN文档。

    二.拖动矩形

          一般来说UI是数据的反应,UI的变化其实是后段数据的变化。我们一般在移动到方块上方后,按住鼠标开始拖动,那么在鼠标移动上去之后,我们首先判断此位置是否有矩形,点击鼠标的时候,我们记录点下的这个坐标为A,鼠标移动的时候我们根据移动时候鼠标所在坐标和原来的A坐标比较,然后把这个差值和矩形的开始坐标相加,通过InvalidateVisual()方法不断重画就达到了移动的效果。

    image

    如果你需要鼠标移动出窗口还可以移动该矩形请加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));

    效果如图:

    image

    这时你拖动方块可能会发现方块可以被移出背景,这在WPF下是允许的,但有时候这又不符合情理,我们需要把多余的部分裁减掉。

    image

            protected override void OnRender(DrawingContext drawingContext)
            {
                Rect rect 
    = new Rect(new Point(00), 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)

    剪切后的效果如下:

    image

    三.动画效果

          当然我们也可以做些拖动预览效果如下:

    image

    实现的原理无非是拖动的时候画一个假矩形,并把该矩形呈现的代码放在剪切的效果之外,拖动结束后把假的位置给真的调用重画一遍就实现了。

    我们能不能用动画效果使得矩形慢慢移动到指定位置,答案当然是肯定的。这里可以用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复合控件能完成大部分的需求——只要你能熟练定义样式,并了解可视树,逻辑树,以及各个控件的用法。

    本例代码下载 

    转载清注明出处

  • 相关阅读:
    BZOJ1001 狼抓兔子 终于过了!
    BZOJ 1901: Zju2112 Dynamic Rankings( 树状数组套主席树 )
    BZOJ 2302: [HAOI2011]Problem c( dp )
    BZOJ 1407: [Noi2002]Savage( 数论 )
    BZOJ 2661: [BeiJing wc2012]连连看( 费用流 )
    BZOJ 1021: [SHOI2008]Debt 循环的债务( dp )
    BZOJ 3170: [Tjoi 2013]松鼠聚会( sort )
    BZOJ 2301: [HAOI2011]Problem b( 数论 )
    BZOJ 2434: [Noi2011]阿狸的打字机( AC自动机 + DFS序 + 树状数组 )
    BZOJ 3231: [Sdoi2008]递归数列( 矩阵快速幂 )
  • 原文地址:https://www.cnblogs.com/Curry/p/1435778.html
Copyright © 2011-2022 走看看