分享

C#下自定义控件的制作 一

 googo 2011-07-18

C#下自定义控件的制作 一 - [C# Programming]

分类:C# Programming | 2009-02-26

版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明http://wynfeeisolate./logs/35782738.html

很久没有写Blog,以后这样的时候还会更多...因为要考研....

一直很喜欢.Net,虽然有些人很鄙视它,我也一直不明白为什么,实际上JDK+JVM和.NET几乎是一个样子,没有什么大的区别,不是我没有使 用过Java,用Java开发程序我也做过...虽然不多,但是至少写过一些,差别真的不大,要真有差别,就是Java封装的函数少了点,要自己多写写, 实际上要是用二者都做了程序会发现,实际上.NET中要是不知道那些封装的函数,你还是要自己写...

好了,废话不说,还是看一下我们如何写一个自定义的控件...

发个效果图...

<-><-><->

动态效果哦!!!

明确开发环境:Visual Studio 2008 Team Suite语言:C#   

阅读要求:熟悉C# 2.0及之后的版本和Visual Studio 2005及之后的版本,了解GDI+

小提示:如果懂得Photoshop或者Fireworks作图,可以理解本程序更加快一些

由于我们自定义绘制一个Button,所以我们要对它增加一些引用库:

using System.Drawing.Drawing2D

这个是为我们绘制Button所做的铺垫,

然后我们首先新建一个项目,然后选择Windows控件库,然后创建一个新的目录,就叫VistaButton好了,名字也叫 VistaButton,和我的代码统一起来...这里需要提示的是不要把控件库的输出位置放置在带#的结尾的目录中,为什么呢?因为我在输出的时候遇到 这个问题,当我输出一个控件在路径:C:/WinterVacation Create/C#/VistaButton时,会提示找不到该路径,而且提示出故障的路径中多了一个"C5",不知道是什么原因,是Vista的原因 么?不晓得,总之不要输出在带#的路径里面就对了。

然后我们首先在Designer中添加我们需要代码:

private void InitializeComponent()
        {
            this.Name = "VistaButton";//控件名
            this.Size = new System.Drawing.Size(100, 32);//控件的默认大小
            this.Paint += new System.Windows.Forms.PaintEventHandler(this.VistaButton_Paint);//控件的Paint事件
            this.KeyUp += new System.Windows.Forms.KeyEventHandler(this.VistaButton_KeyUp);
            this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.VistaButton_KeyDown);
            this.MouseEnter += new System.EventHandler(this.VistaButton_MouseEnter);
            this.MouseLeave += new System.EventHandler(this.VistaButton_MouseLeave);
            this.MouseUp += new MouseEventHandler(VistaButton_MouseUp);
            this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.VistaButton_MouseDown);
            this.GotFocus += new EventHandler(VistaButton_MouseEnter);
            this.LostFocus += new EventHandler(VistaButton_MouseLeave);
            this.mFadeIn.Tick += new EventHandler(mFadeIn_Tick);
            this.mFadeOut.Tick += new EventHandler(mFadeOut_Tick);
            this.Resize += new EventHandler(VistaButton_Resize);
            //设置一些针对这个控件的事件
        }

事实上你完全可以在编辑器中完成这个工作,只需要点击鼠标就可以完成设置,但是我在做控件的时候常常喜欢直接写代码,自我感觉这样会比较保险...如果你不确定你写的函数存在,那么还是用编辑器作比较合适,比如你不确定Resize函数存不存在一样...

 

然后我们回到正题,开始写些代码

如果你的和我写的一模一样,或者你干脆就知道构造函数的位置,那么就可以写一下我们的设计要求,如下:

public VistaButton()
        {
            InitializeComponent();
            #region 相关优化设置
            this.SetStyle(ControlStyles.UserPaint, true);
            this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            //该设置忽略WM_ERASEBKGND系统消息来减少闪烁(true),WM_ERASEBKGND是操作系统指示整个窗体被擦除的时候才被调用
            //那么,这段话主要就是要求在双缓存中绘制图形,然后再显示到Screen上,这个要求USERPaint是开启(true)的状态
            this.SetStyle(ControlStyles.DoubleBuffer, true);
            //这个就是为绘制开启双缓存,前提就是上面的设置,因为要使用双缓存必须启用WM_Paint...,则要求所有的绘制都在WM_Paint中,那么就是ALLPaintInWm_Paint
            this.SetStyle(ControlStyles.ResizeRedraw, true);
            //这个标签是通知系统,当控件大小发生改变的时候应该进行重绘
            this.SetStyle(ControlStyles.Selectable, true);
            //通知系统该控件接受焦点,即可以被选中....
            this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
            //通知系统该控件支持透明的背景色,其启用条件是USERPaint为true,且其父控件派生自Control才可以,我们这个控件是派生自Button,所以是可以使用的
            //this.SetStyle(ControlStyles.UserPaint, true);
            this.BackColor = Color.Transparent;
            //设置本空间的的背景色为透明...
            mFadeIn.Interval = 30;
            mFadeOut.Interval = 30;
            //这里有两个特殊的变量,这两个变量是Timer类型的,Timer类型就是按照用户定义类型来引发事件的计时器
            #endregion
        }

如果你是用设计器编辑的话,那么建议你创建2个Timer控件,然后把名字改成mFadeIn和mFadeOut,这样会比较直观,因为我全部是用 代码写的,所以缺失了两个控件的显示(这两个Timer)使得编辑器里无法显示这个按钮的样子...真不幸...不过好在如果你把它作为一个控件库引入到 一个Windows Form中,就可以显示出来了...主要问题在于我们这里是绘制的,不是单纯的拖控件组合...所以...那控件编辑器制作本程序的估计也看不出什么,因 为我写的时候压根没有想到使用编辑器....

然后让我们设置两个可能出现的枚举:

        enum State { None, Hover, Pressed };//设置控件的状态....主要是针对鼠标...正如英文所说的那样...没有鼠标影响、鼠标悬停,和鼠标按下三个状态,当然,也可以设置更多,完全是用户自己的事情

        public enum Style//设置控件的Style属性,有flat和默认两种
        {
            Default,//本例中正常绘制的外观即为Default
            Flat//本例中为绘制Flat效果设置的外观
        };

我的程序只是个Demo,所以没有什么特别深厚的设计,很简单实现某个功能而已,如果想增加什么功能或者完善,请读者自便...

之后设置一些私有变量:

        #region 一些程序需要的私有变量

        private bool calledbykey = false;
        private State mButtonState = State.None;
        private Timer mFadeIn = new Timer();
        private Timer mFadeOut = new Timer();
        private int mGlowAlpha = 0;

        #endregion

我想我的变量名字起的很好理解...我就不解释了...

然后设置一些我们所能操作的变量,以属性的形式给予赋值...至于Category这个标签,就是我们看到的IDE中显示为文本、布局之类的名称, 即标的我们当前设置的属性应该在那个Category中显示出来,没有特殊规定的,会从Control继承...所以,大胆的开发吧...

#region 在Text(即文本)这个分类中包含的属性和设置其初始值....

        private string mText;
        [Category("Text"),
         Description("The text that is displayed on the button.")]
        //定义属性...buttonText
        public string ButtonText
        {
            get { return mText; }//控件所设置的文本时可以获取的....
            set { mText = value; this.Invalidate(); }//一旦对ButtonText设置了新的文字,则对控件重绘...
        }

        //设置mForeColor属性....,默认值为白色
        private Color mForeColor = Color.White;
        [Category("Text"),
         Browsable(true),//该属性是不是显示在IDE属性窗口中
         DefaultValue(typeof(Color), "White"),
         Description("The color with which the text is drawn.")]
        public override Color ForeColor//改写Control的Forecolor属性为mForeColor,以此影响Forecolor的取值,一旦变化了,立即重绘控件
        {
            get { return mForeColor; }
            set { mForeColor = value; this.Invalidate(); }
        }


        //设置文字的默认对齐方式
        private ContentAlignment mTextAlign = ContentAlignment.MiddleCenter;
        [Category("Text"),
         DefaultValue(typeof(ContentAlignment), "MiddleCenter"),
         Description("The alignment of the button text " +
                     "that is displayed on the control.")]
        public ContentAlignment TextAlign
        {
            get { return mTextAlign; }
            set { mTextAlign = value; this.Invalidate(); }
        }

        #endregion

        #region 允许用户在控件上添加图片的Images分类

        private Image mImage;
        [Category("Image"),
         DefaultValue(null),
         Description("The image displayed on the button that " +
                     "is used to help the user identify" +
                     "it's function if the text is ambiguous.")]
        //下面的Images才是真正在属性菜单上显示的数据,mImage只是为Images获取参数而设置的
        public Image Image
        {
            get { return mImage; }
            set { mImage = value; this.Invalidate(); }
        }

        private ContentAlignment mImageAlign = ContentAlignment.MiddleLeft;
        /// <summary>
        /// The alignment of the image
        /// in relation to the button.
        /// </summary>
        [Category("Image"),
         DefaultValue(typeof(ContentAlignment), "MiddleLeft"),
         Description("The alignment of the image " +
                     "in relation to the button.")]
        public ContentAlignment ImageAlign
        {
            get { return mImageAlign; }
            set { mImageAlign = value; this.Invalidate(); }
        }

        private Size mImageSize = new Size(24, 24);
        /// <summary>
        /// The size of the image to be displayed on the
        /// button. This property defaults to 24x24.
        /// </summary>
        [Category("Image"),
         DefaultValue(typeof(Size), "24, 24"),
         Description("The size of the image to be displayed on the" +
                     "button. This property defaults to 24x24.")]
        public Size ImageSize
        {
            get { return mImageSize; }
            set { mImageSize = value; this.Invalidate(); }
        }

        #endregion

        #region 设置Button的外观

        private Style mButtonStyle = Style.Default;
        ///设置当鼠标不再客户区的时候,button的背景是不是被绘制,
        [Category("Appearance"),
         DefaultValue(typeof(Style), "Default"),
         Description("Sets whether the button background is drawn " +
                     "while the mouse is outside of the client area.")]
        public Style ButtonStyle
        {
            get { return mButtonStyle; }
            set { mButtonStyle = value; this.Invalidate(); }
        }

        private int mCornerRadius = 8;
        //设置button的圆角的弧度,弧度越大,越光滑...,弧度的大小不超过Button高的一半
        [Category("Appearance"),
         DefaultValue(8),
         Description("The radius for the button corners. The " +
                     "greater this value is, the more 'smooth' " +
                     "the corners are. This property should " +
                     "not be greater than half of the " +
                     "controls height.")]
        public int CornerRadius
        {
            get { return mCornerRadius; }
            set { mCornerRadius = value; this.Invalidate(); }
        }


        private Color mHighlightColor = Color.White;
        //设置高光颜色....
        [Category("Appearance"),
         DefaultValue(typeof(Color), "White"),
         Description("The colour of the highlight on the top of the button.")]
        public Color HighlightColor
        {
            get { return mHighlightColor; }
            set { mHighlightColor = value; this.Invalidate(); }
        }

        private Color mButtonColor = Color.Black;
        ///设置Button的颜色...
        [Category("Appearance"),
         DefaultValue(typeof(Color), "Black"),
         Description("The bottom color of the button that " +
                     "will be drawn over the base color.")]
        public Color ButtonColor
        {
            get { return mButtonColor; }
            set { mButtonColor = value; this.Invalidate(); }
        }

        private Color mGlowColor = Color.FromA#8dbdff;
        //当鼠标在控件客户端范围内,绘制控件的暗光...
        [Category("Appearance"),
         DefaultValue(typeof(Color), "141,189,255"),
         Description("The colour that the button glows when " +
                     "the mouse is inside the client area.")]
        public Color GlowColor
        {
            get { return mGlowColor; }
            set { mGlowColor = value; this.Invalidate(); }
        }

        private Image mBackImage;
        //Button的背景图....
        [Category("Appearance"),
         DefaultValue(null),
         Description("The background image for the button, " +
                     "this image is drawn over the base " +
                     "color of the button.")]
        public Image BackImage
        {
            get { return mBackImage; }
            set { mBackImage = value; this.Invalidate(); }
        }

        private Color mBaseColor = Color.Black;
        //绘制在Button上凸显明净的颜色,产生玻璃效果(绘制在没有Glow色绘制的客户端区域),如果想要产生玻璃效果,尝试设置为透明色
        [Category("Appearance"),
         DefaultValue(typeof(Color), "Black"),
         Description("The backing color that the rest of" +
                     "the button is drawn. For a glassier " +
                     "effect set this property to Transparent.")]
        public Color BaseColor
        {
            get { return mBaseColor; }
            set { mBaseColor = value; this.Invalidate(); }
        }

        #endregion
        //在分类上添加的内容...
        #endregion

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多