C# 模仿360安全卫士玻璃按钮 修正版(源码)

效果图

\

一 准备工作

      两张透明的png图片(尺寸73 x 81),一张用于鼠标进入控件时显示,一张用于鼠标单击控件时显示。

      新建自定义控件,在构造函数中添加代码

       public GlassButton()

        {

          SetStyle(ControlStyles.DoubleBuffer, true);                   //双缓冲防止重绘时闪烁

            SetStyle(ControlStyles.AllPaintingInWmPaint, true);           //忽略WM_ERASEBKGND 窗口消息减少闪烁

            SetStyle(ControlStyles.UserPaint, true);                      //自定义绘制控件内容

            SetStyle(ControlStyles.SupportsTransparentBackColor, true);   //模拟透明           

            SetStyle(ControlStyles.Selectable, true);                     //接收焦点

            Size = new Size(73, 81);                                      //初始大小

            Font = new Font("微软雅黑", 9);                               //控件字体

        }

      新建枚举,用来表示当前控件的状态

       ///<summary>

    /// 控件状态

    ///</summary>

    public enum State

    {

        ///<summary>

        /// 无

        ///</summary>

        Normal = 0,

        ///<summary>

        /// 获得焦点

        ///</summary>

        Focused = 1,

        ///<summary>

        /// 失去焦点

        ///</summary>

        LostFocused = 2,

        ///<summary>

        /// 鼠标指针进入控件

        ///</summary>

        MouseEnter = 3

    }


 

二 制作方法

      比较简单,在这里只贴一下代码,大家一看就明白

      属性

///<summary>

        /// 获取或设置控件显示的图片

        ///</summary>

        [Description("获取或设置控件显示的图标")]

        public Bitmap Bitmap

        {

            get { return _bmp; }

            set {

                _bmp = value;

                Invalidate(false);

            }

        }

        ///<summary>

        /// 重写控件焦点属性

        ///</summary>

        [Description("重写控件焦点属性")]

        public new bool Focused

        {

            get { return _focused; }

            set

            {

                _focused = value;

                if (_focused)

                    state = State.Focused;

                else

                    state = State.LostFocused;

                Invalidate(false);

            }

        }

      重载事件

              //自定义绘制

        protected override void OnPaint(PaintEventArgs e)

        {

            base.OnPaint(e);

            Graphics g = e.Graphics;

            g.SmoothingMode = SmoothingMode.HighQuality;

            g.PixelOffsetMode = PixelOffsetMode.HighQuality;

            switch (state)

            {

                case State.Focused: {

                    DrawSelected(g);

                    break;

                }

                case State.MouseEnter: {

                    if (!Focused)

                        g.DrawImage(Properties.Resources.enter, ClientRectangle);

                    else

                        DrawSelected(g);

                    break;

                }

            }

            DrawImage(g);

            DrawText(g);

        }     

        //焦点进入

        protected override void OnEnter(EventArgs e)

        {

            base.OnEnter(e);

            Focused = true;

        }

        //失去焦点

        protected override void OnLeave(EventArgs e)

        {

            base.OnLeave(e);

            Focused = false;

        }

        //禁止调整大小

        protected override void OnResize(EventArgs e)

        {

            Width = 73;

            Height = 81;

        }

        protected override void OnMouseEnter(EventArgs e)

        {

            base.OnMouseEnter(e);           

            state = State.MouseEnter;

            Invalidate(false);

        }

        protected override void OnMouseLeave(EventArgs e)

        {

            base.OnMouseLeave(e);

            if (!Focused)

            {

                state = State.LostFocused;

                Invalidate(false);

            }

        }

        //只响应单击鼠标左键事件

        protected override void OnClick(EventArgs e)

        {

            MouseEventArgs m = (MouseEventArgs)e;

            if (m.Button == MouseButtons.Left)

            {

                base.OnClick(e);

                Focus();

            }

        }

      方法

              #region//Draw

        void DrawSelected(Graphics g)

        {

            g.DrawImage(Properties.Resources.down, ClientRectangle);

        }

        void DrawImage(Graphics g)

        {

            if (_bmp != null)

            {

                Bitmap bmp = ScaleZoom(_bmp);

                bmp_Left = (Width - bmp.Width) / 2;

                g.DrawImage(bmp, new Rectangle(bmp_Left, bmp_Top, bmp.Width, bmp.Height));

            }

        }

        void DrawText(Graphics g)

        {

            SizeF size = g.MeasureString(Text, Font);

            g.DrawString(Text, Font, new SolidBrush(ForeColor), (Width - size.Width) / 2, 58);

        }

        #endregion

        #region//按比例缩放图片

        public Bitmap ScaleZoom(Bitmap bmp)

        {

            if (bmp != null)

            {

                double zoomScale;

                if (bmp.Width > bmp_Size || bmp.Height > bmp_Size)

                {

                    double imageScale = (double)bmp.Width / (double)bmp.Height;

                    double thisScale = 1;

                    if (imageScale > thisScale)

                    {

                        zoomScale = (double)bmp_Size / (double)bmp.Width;

                        return BitMapZoom(bmp, bmp_Size, (int)(bmp.Height * zoomScale));

                    }

                    else

                    {

                        zoomScale = (double)bmp_Size / (double)bmp.Height;

                        return BitMapZoom(bmp, (int)(bmp.Width * zoomScale), bmp_Size);

                    }

                }

            }

            return bmp;

        }

        #endregion

        #region//缩放BitMap

        ///<summary>

        /// 图片缩放

        ///</summary>

        ///<param name="bmpSource">源图片</param>

        ///<param name="bmpSize">缩放图片的大小</param>

        ///<returns>缩放的图片</returns>

        public Bitmap BitMapZoom(Bitmap bmpSource, int bmpWidth, int bmpHeight)

        {

            Bitmap bmp, zoomBmp;

            try

            {

                bmp = new Bitmap(bmpSource);

                zoomBmp = new Bitmap(bmpWidth, bmpHeight);

                Graphics gh = Graphics.FromImage(zoomBmp);

                gh.InterpolationMode = InterpolationMode.HighQualityBicubic;

                gh.DrawImage(bmp, new Rectangle(0, 0, bmpWidth, bmpHeight), new Rectangle(0, 0, bmp.Width, bmp.Height), GraphicsUnit.Pixel);

                gh.Dispose();

                return zoomBmp;

            }

            catch

            { }

            finally

            {

                bmp = null;

                zoomBmp = null;

                GC.Collect();

            }

            return null;

        }

        #endregion

三 要点

      要点就在于各个按钮之间焦点切换的问题,就如效果图所示,当有一个按钮获取了焦点,其他按钮将显示为失去焦点的状态。

      MSDN上建议当控件得到焦点时使用Enter事件,也就表示焦点进入当前所选择控件,当控件失去焦点时使用Leave事件。

      所以要重载Control组件的OnEnter和OnLeave事件,在此控件中重写了Focused属性,当引发了控件的焦点事件后将触发OnPaint事件重新绘制,而引发Enter事件的发起者来自于控件的Focus()方法。

//焦点进入

        protected override void OnEnter(EventArgs e)

        {

            base.OnEnter(e);

            Focused = true;

        }

        //失去焦点

        protected override void OnLeave(EventArgs e)

        {

            base.OnLeave(e);

            Focused = false;

        }

http://up.2cto.com/2011/1102/20111102023717645.zip

猜你喜欢

转载自blog.csdn.net/bruce135lee/article/details/81181008