C#控件开发相关笔记

来源:互联网 发布:数据库连接器 编辑:程序博客网 时间:2024/06/02 18:52

一:开发控件,采用依赖的关系进行处理,需要深入了解组件在呈现前的顺序。

以下是测试案例,了解在那里修饰组件最好。


public partial class UserControl1 : UserControl    {        public UserControl1()        {            InitializeComponent();        }        private void UserControl1_Layout(object sender, LayoutEventArgs e)        {            PrintStack();        }        private void PrintStack()        {            StackTrace st = new StackTrace(true);            var MethodName = st.GetFrame(1).GetMethod().Name.ToString();            Console.WriteLine(MethodName + "-> 宽度:" + Width + " 高度:" + Height);        }        private void UserControl1_Resize(object sender, EventArgs e)        {            PrintStack();        }        private void UserControl1_Scroll(object sender, ScrollEventArgs e)        {            PrintStack();        }        private void UserControl1_Load(object sender, EventArgs e)        {            PrintStack();        }        private void UserControl1_Paint(object sender, PaintEventArgs e)        {            PrintStack();        }        private void UserControl1_Validated(object sender, EventArgs e)        {            PrintStack();        }        private void UserControl1_Validating(object sender, CancelEventArgs e)        {            PrintStack();        }        private void UserControl1_ClientSizeChanged(object sender, EventArgs e)        {            PrintStack();        }        private void UserControl1_LocationChanged(object sender, EventArgs e)        {            PrintStack();        }        private void UserControl1_DockChanged(object sender, EventArgs e)        {            PrintStack();        }        private void UserControl1_SizeChanged(object sender, EventArgs e)        {            PrintStack();        }        protected override void OnPaint(PaintEventArgs e)        {            e.Graphics.FillRectangle(new SolidBrush(Color.Green), this.DisplayRectangle);            base.OnPaint(e);        }    }

调用顺序如下:

UserControl1_DockChanged-> 宽度:150 高度:150

==========================>
UserControl1_Layout-> 宽度:821 高度:351
UserControl1_Resize-> 宽度:821 高度:351
UserControl1_SizeChanged-> 宽度:821 高度:351
UserControl1_ClientSizeChanged-> 宽度:821 高度:351
UserControl1_Load-> 宽度:821 高度:351
UserControl1_Layout-> 宽度:821 高度:351
UserControl1_Paint-> 宽度:821 高度:351

==========================>


最小化后:

UserControl1_Layout-> 宽度:0 高度:0
UserControl1_Resize-> 宽度:0 高度:0
UserControl1_SizeChanged-> 宽度:0 高度:0
UserControl1_ClientSizeChanged-> 宽度:0 高度:0

恢复窗口:

UserControl1_Layout-> 宽度:821 高度:351
UserControl1_Resize-> 宽度:821 高度:351
UserControl1_SizeChanged-> 宽度:821 高度:351
UserControl1_ClientSizeChanged-> 宽度:821 高度:351
UserControl1_Paint-> 宽度:821 高度:351。

改变大小:

UserControl1_Layout-> 宽度:616 高度:426
UserControl1_Resize-> 宽度:616 高度:426
UserControl1_SizeChanged-> 宽度:616 高度:426
UserControl1_ClientSizeChanged-> 宽度:616 高度:426
UserControl1_Layout-> 宽度:615 高度:426
UserControl1_Resize-> 宽度:615 高度:426
UserControl1_SizeChanged-> 宽度:615 高度:426
UserControl1_ClientSizeChanged-> 宽度:615 高度:426
UserControl1_Layout-> 宽度:615 高度:425
UserControl1_Resize-> 宽度:615 高度:425
UserControl1_SizeChanged-> 宽度:615 高度:425
UserControl1_ClientSizeChanged-> 宽度:615 高度:425


二、关于处理类的值类型和对象指针类型。

 有时我们的类型很多就是结构体,例如Rectangle,Color等。

有些是对象类型,在克隆时很可能是指针引用,要小心。

using System;using System.Collections.Generic;using System.Text;using System.Reflection;namespace MyTest{    class TypeHelper    {        /// <summary>        /// 复制一个对象,只复制属性        /// 注意:此方法,对于对象型采用指针引用。        ///       可以复制基本类型,结构体(Rect,color)等。        /// </summary>        /// <param name="to"></param>        /// <param name="from"></param>        /// <returns></returns>        public static void CopyObject<T>(T to, T from)        {            //开始复制所有的属性            PropertyInfo[] properties = typeof(T).GetProperties();            foreach (PropertyInfo pi in properties)            {                if (pi.CanWrite)                {                    object value = pi.GetValue(from, null);                    pi.SetValue(to, value, null);                }            }        }        public static void CopyObject(object to, object from)        {            //开始复制所有的属性            Type t = to.GetType();            PropertyInfo[] properties = t.GetProperties();            foreach (PropertyInfo pi in properties)            {                if (pi.CanWrite)                {                    object value = pi.GetValue(from, null);                    pi.SetValue(to, value, null);                }            }        }    }}

测试代码:

测试类:

namespace MyTest{    abstract class Foo    {        public Color Color1 { get; set; }        public int Alpha { get; set; }        public Rectangle rect { get; set; }        public Sub Sub { get; set; }        public String Name { get; set; }        public Foo()        {            this.Sub = new Sub();        }        public override string ToString()        {            return Name +","+ Color1.ToString() + "," + rect.ToString() + "," + Alpha.ToString() +                   ",Sub="+Sub.ToString();        }        public virtual void Copy(object oo)        {            TypeHelper.CopyObject(this,oo);        }    }    class Sub    {        public Color Color2 { get; set; }        public int Alpha { get; set; }        public override string ToString()        {            return Color2.ToString() + "," + Alpha.ToString();        }    }    class FooX : Foo    {        public int Id { get; set; }        public override string ToString()        {            return "id:"+ Id +"=" + base.ToString();        }    }}

这里有个关键说明,如果父类是抽象,抽象有个重要的特征,就克隆会自动赋值子类的处理,抽象不是实在东西。

abstract 存在与否,结果是不同的。

测试代码如下:

public partial class Form1 : Form    {        public Form1()        {            InitializeComponent();        }        private void button1_Click(object sender, EventArgs e)        {            //原始对象            FooX aa = new FooX();            aa.Color1 = Color.Red;            aa.Alpha = 10;            aa.rect = new Rectangle(0, 0, 100, 100);            aa.Sub.Color2 = Color.Red;            aa.Sub.Alpha = 20;            aa.Name = "aa";            aa.Id = 1;            PrintLine(aa.ToString());            FooX bb = new FooX();            PrintLine("bb->"+bb.ToString());            bb.Copy(aa);            bb.Name = "bb";                                    PrintLine("bb->"+bb.ToString());            aa.Color1 = Color.Blue;            aa.Sub.Color2 = Color.Yellow;            PrintLine(Environment.NewLine);            PrintLine(aa);            PrintLine(bb);        }        private void PrintLine(Object text)        {            this.textBox1.AppendText(text.ToString() + Environment.NewLine);        }    }

是否存在abstract明显的出现不同结果。


第三:矩阵变换:

using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Text;using System.Windows.Forms;using System.Drawing.Drawing2D;namespace MartixDemo{    public partial class FormDemo1 : Form    {        public FormDemo1()        {            InitializeComponent();        }        private float _zoom = 1.0F;        private Point offset = new Point(0, 0);        private void button1_Click(object sender, EventArgs e)        {            //设置偏移                       Point p1 = new Point(100, 100);            PrintLn("原始坐标:"+BacktrackMouse(p1));            _zoom = 0.5F;            PrintLn("缩放坐标:"+BacktrackMouse(p1));            offset = new Point(10, 10);            PrintLn("平移坐标:"+BacktrackMouse(p1));            offset = new Point(20, 20);            PrintLn("平移坐标:" + BacktrackMouse(p1));            /*             * 原始坐标:{X=100,Y=100}                缩放坐标:{X=200,Y=200}                平移坐标:{X=180,Y=180}                平移坐标:{X=160,Y=160}            */        }        private void PrintLn(object obj)        {            this.textBox1.AppendText(obj + "" + Environment.NewLine);        }        /// <summary>        /// 回来跟踪鼠标        /// 描述:将当前坐标转换为画布坐标[Control->Canvas]        /// </summary>        /// <param name="e"></param>        /// <returns></returns>        protected Point BacktrackMouse(Point e)        {            //Creates the drawing matrix with the right zoom;            Matrix mx = new Matrix(_zoom, 0, 0, _zoom, 0, 0);            //pans it according to the scroll bars            mx.Translate(offset.X * (1.0f / _zoom), offset.Y * (1.0f / _zoom));            //inverts it            mx.Invert();            //uses it to transform the current mouse position            Point[] pa = new Point[] { new Point(e.X, e.Y) };            mx.TransformPoints(pa);            return pa[0];        }                protected Size BacktrackMouse(Size e)        {            //Creates the drawing matrix with the right zoom;            Matrix mx = new Matrix(_zoom, 0, 0, _zoom, 0, 0);            //pans it according to the scroll bars            mx.Translate(this.AutoScrollPosition.X * (1.0f / _zoom), this.AutoScrollPosition.Y * (1.0f / _zoom));            //inverts it            mx.Invert();            //uses it to transform the current mouse position            Point[] pa = new Point[] { new Point(e.Width, e.Height) };            mx.TransformPoints(pa);            Size si = new Size(pa[0].X, pa[0].Y);            return si;        }        /// <summary>        /// 按照平移和缩放进行变换后绘制。        /// </summary>        /// <param name="e"></param>        private void GraphicsTransform(System.Windows.Forms.PaintEventArgs e)        {            //Creates the drawing matrix with the right zoom;            Matrix mx = new Matrix(_zoom, 0, 0, _zoom, 0, 0);            //pans it according to the scroll bars            mx.Translate(offset.X * (1.0f / _zoom), offset.Y * (1.0f / _zoom));            //use it for drawing            e.Graphics.Transform = mx;        }    }}

第三:多线程并发开发。

很多时候,lock并不是万能良药。最小力度的方法块才是最小的力度的,实际测试静态方法和没有其他变量的实例方法是没有区别,都是安全的。

但是建议使用静态方法,避免多线程的隐含错误,当然没有区别,主要是防止你忘记了是否用了实例的变量,手误而已。


原创粉丝点击