zoukankan      html  css  js  c++  java
  • C# 模仿360安全卫士玻璃按钮(源码)[转]

    注:感谢Aleax博友提出的Bug(见#7楼),现已纠正,纠正的内容会在要点里说明,修改过的源码已附上,也谢谢各位博友提出的意见和方法,当然方法有很多种,这只是其中一种非常简单和直接的方法,给初学者一点参考,望大家多多提意。

    效果图

    一 准备工作

          两张透明的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
    }


     

    二 制作方法

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

          属性

    Property
            ///<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);
    }
    }

          重载事件

    Override
            //自定义绘制
    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();
    }
    }

          方法 

    Method
    #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;
    }


     

    源码下载

  • 相关阅读:
    js 中 && 和 ||
    The server time zone value 'EDT' is unrecognized or represents more than one time zone.
    docker进入容器
    docker 挂载本地目录
    Docker for Windows 挂载目录失败
    docker下redis启动 根据本地配置文件
    docker 安装 nacos/nacos-server 镜像并配置本地数据库
    spring cloud Nacos Config配置中心
    Docker卸载
    虚拟机centos添加硬盘和分区挂载
  • 原文地址:https://www.cnblogs.com/saptechnique/p/2250598.html
Copyright © 2011-2022 走看看