Winform绘制控件解决闪烁问题

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq870841070/article/details/85375807

一开始用复合控件(就是在UserControl上面拖进去一些Label、Button之类的), 然后在把这个用户控件加入到滚动容器中去,

可没想到滚动过程简直不忍直视,即使开启了双缓存

  后来一想还是重写onpaint自己绘制界面算了,但是说起绘制界面又麻烦,这可是个苦力活

  不过效果还是有的,流畅的让你感觉不到卡 

  

  代码如下

  

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApp1
{

    public partial class UserControl1 : UserControl
    {
        #region 私有属性
        Font fontDict = new Font("Microsoft YaHei", 13);
        Font fontYb = new Font("Microsoft YaHei", 10);
        Font fontDesc = new Font("新宋体", 9);
        /// <summary>
        /// 发音图标
        /// </summary>
        Image soundIcon = null;
        /// <summary>
        /// 发音图标_高亮
        /// </summary>
        Image soundIconHigh = null;
        /// <summary>
        /// 遗忘图标
        /// </summary>
        Image forgetIcon = null;
        /// <summary>
        /// 阶段图标
        /// </summary>
        Image gradeIcon = null;

        /// <summary>
        /// 组队按钮
        /// </summary>
        UIRectangle flagButton = null;

        /// <summary>
        /// 删除按钮
        /// </summary>
        UIRectangle delButton = null;

        Rectangle rectSound1;
        Rectangle rectSound2;
        /// <summary>
        /// 是否鼠标进入sound1
        /// </summary>
        bool isEnterSound1 = false;
        /// <summary>
        /// 是否鼠标进入sound2
        /// </summary>
        bool isEnterSound2 = false;

        event SoundEvent mouseEnterSound;

        event EventHandler mouseClickSound;

        event EventHandler mouseClickFlag;

        event EventHandler mouseClickDelete;
        #endregion

        /// <summary>
        /// 单词名称
        /// </summary>
        public string DictName { set; get; }

        /// <summary>
        /// 英音标
        /// </summary>
        public string USKSpell { set; get; }

        /// <summary>
        /// 美音标
        /// </summary>
        public string USASpell { set; get; }

        /// <summary>
        /// 释义
        /// </summary>
        public string Descript { set; get; }

        /// <summary>
        /// 遗忘次数
        /// </summary>
        public int ForgetCount { set; get; }

        /// <summary>
        /// 阶段名称
        /// </summary>
        public string GradeName { set; get; }

        /// <summary>
        /// 鼠标进入发音图标事件
        /// </summary>
        public event SoundEvent OnMouseEnterSound {
            add {
                mouseEnterSound += value;
            }
            remove {
                mouseEnterSound -= value;
            }
        }

        /// <summary>
        /// 鼠标点击发音图标事件
        /// </summary>
        public event EventHandler OnClickSound {
            add {
                mouseClickSound += value;
            }
            remove {
                mouseClickSound -= value;
            }
        }

        /// <summary>
        /// 鼠标点击旗帜事件
        /// </summary>
        public event EventHandler OnClickFlag {
            add {
                mouseClickFlag += value;
            }
            remove {
                mouseClickFlag -= value;
            }
        }
       
        /// <summary>
        /// 鼠标点击删除按钮事件
        /// </summary>
        public event EventHandler OnClickDelete {
            add {
                mouseClickDelete += value;
            }
            remove {
                mouseClickDelete -= value;
            }
        }
        public UserControl1()
        {
            this.DoubleBuffered = true;
            InitializeComponent();
            this.Load += UserControl1_Load;

        }

        /// <summary>
        /// 加载完毕
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void UserControl1_Load(object sender, EventArgs e)
        {
            //加载图片资源
            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(UserControl1));
            soundIcon = ((System.Drawing.Image)(resources.GetObject("sound_play_gray")));
            soundIconHigh = ((System.Drawing.Image)(resources.GetObject("sound_play")));
            forgetIcon = ((System.Drawing.Image)(resources.GetObject("ico_question")));
            gradeIcon = ((System.Drawing.Image)(resources.GetObject("ico_grade")));
            flagButton = new UIRectangle(((System.Drawing.Image)(resources.GetObject("ico_flag_normal"))), ((System.Drawing.Image)(resources.GetObject("ico_flag_focus"))));
            delButton = new UIRectangle(((System.Drawing.Image)(resources.GetObject("ico_delete_normal"))), ((System.Drawing.Image)(resources.GetObject("ico_delete_focus"))));
            this.Margin = new Padding(0);

            DictName = "Caption";
            USKSpell = "英 [caption]";
            USASpell = "美 [caption]";
            Descript = "释义:n. 说明文字 v.给(图片、照片等)加说明文字释义:n. 说明文字 v.给(图片、照片等)加说明文字释义:n. 说明文字 v.给(图片、照片等)加说明文字";
            GradeName = "青铜 x3";
            ForgetCount = 9;
        }

        /// <summary>
        /// 控件重绘
        /// </summary>
        /// <param name="e"></param>
        protected override void OnPaint(PaintEventArgs e)
        {
            
            //单词宽度
            float dictWidth = GetTextWidth(e.Graphics, DictName, fontDict);
            //USK音标宽度
            float uskWidth = GetTextWidth(e.Graphics, USKSpell, fontYb);
            //USA音标宽度
            float usaWidth = GetTextWidth(e.Graphics, USASpell, fontYb);
            //单词阶段宽度
            float gradeWidth = GetTextWidth(e.Graphics, GradeName, fontYb);
            float left = 10;
            //画单词
            e.Graphics.DrawString(DictName, fontDict, Brushes.Black, left, 5);
            left += dictWidth + 20;
            //画音标
            e.Graphics.DrawString(USKSpell, fontYb, Brushes.Gray, left, 7);
            left += uskWidth + 5;
            #region 画发音图标1
            //发音图标
            if (isEnterSound1)
            {
                e.Graphics.DrawImage(soundIconHigh, left, 9, 15, 15);
                rectSound1 = new Rectangle((int)left, 9, 15, 15);
                left += 30;
            }
            else
            {
                e.Graphics.DrawImage(soundIcon, left, 9, 15, 15);
                rectSound1 = new Rectangle((int)left, 9, 15, 15);
                left += 30;
            }
            #endregion
            //画音标
            e.Graphics.DrawString(USASpell, fontYb, Brushes.Gray, left, 7);
            left += usaWidth + 5;
            #region 画发音图标2
            if (isEnterSound2)
            {
                //发音图标
                e.Graphics.DrawImage(soundIconHigh, left, 9, 15, 15);
                rectSound2 = new Rectangle((int)left, 9, 15, 15);
                left += 50;
            }
            else {
                //发音图标
                e.Graphics.DrawImage(soundIcon, left, 9, 15, 15);
                rectSound2 = new Rectangle((int)left, 9, 15, 15);
                left += 50;
            }
            #endregion

            #region try画遗忘次数
            if (ForgetCount > 0)
            {
                e.Graphics.DrawImage(forgetIcon, new Rectangle((int)left,9,15,15));
                left += 15+3;
                e.Graphics.DrawString(ForgetCount.ToString(), fontYb, Brushes.Gray, left, 7);
                left += 30;
            }
            #endregion

            #region 画单词阶段(熟悉度)
            e.Graphics.DrawImage(gradeIcon, new Rectangle((int)left, 9, 15, 15));
            left += 15 + 3;
            e.Graphics.DrawString(GradeName, fontYb, Brushes.Gray, left, 7);
            left += gradeWidth + 5;
            #endregion

            #region 画组队旗帜
            if (flagButton.IsEnter)
            {
                flagButton.Rect = new Rectangle((int)left, 7, 18, 18);
                e.Graphics.DrawImage(flagButton.HightImage, flagButton.Rect);
                left += 15 + 5;
            }
            else {
                flagButton.Rect = new Rectangle((int)left, 7, 18, 18);
                e.Graphics.DrawImage(flagButton.NormalImage, flagButton.Rect);
                left += 15 + 5;
            }
            #endregion

            #region 画删除图标
            if (delButton.IsEnter)
            {
                delButton.Rect = new Rectangle(this.Width-25, 7, 18, 18);
                e.Graphics.DrawImage(delButton.HightImage, delButton.Rect);
            }
            else
            {
                delButton.Rect = new Rectangle(this.Width - 25, 7, 18, 18);
                e.Graphics.DrawImage(delButton.NormalImage, delButton.Rect);
            }

            #endregion
            //画释义
            e.Graphics.DrawString(Descript, fontDesc, Brushes.Gray, 12, 40);
            //画分割线
           // e.Graphics.DrawRectangle(Pens.Gray, new Rectangle(0,this.Height-1,this.Width,1));
            e.Graphics.DrawLine(Pens.WhiteSmoke,0,this.Height-1,this.Width,this.Height-1);
        }

        /// <summary>
        /// 鼠标移动事件
        /// 判断鼠标是否进入某个矩形内
        /// 判断鼠标是否移出某个矩形内
        /// </summary>
        /// <param name="e"></param>
        protected override void OnMouseMove(MouseEventArgs e)
        {
            base.OnMouseMove(e);
            if (IsInRangle(e.X, e.Y, rectSound1))
            {
                //鼠标进入声音1
                if (!isEnterSound1)
                {
                    isEnterSound1 = true;
                    this.Invalidate(rectSound1);
                    if (mouseEnterSound != null) {
                        //响应事件
                        
                        mouseEnterSound(this,0);
                    }
                }
            }
            else if (IsInRangle(e.X, e.Y, rectSound2))
            {
                if (!isEnterSound2)
                {
                    //鼠标进入声音2
                    isEnterSound2 = true;
                    this.Invalidate(rectSound2);
                    if (mouseEnterSound != null){
                        //响应事件
                        mouseEnterSound(this, 1);
                    }
                }
            }
            else if (IsInRangle(e.X, e.Y, flagButton.Rect))
            {
                //鼠标进入旗帜按钮
                if (!flagButton.IsEnter)
                {
                    flagButton.IsEnter = true;
                    this.Invalidate(flagButton.Rect);
                }
            }
            else if (IsInRangle(e.X, e.Y, delButton.Rect)) {
                //鼠标进入删除按钮
                if (!delButton.IsEnter) {
                    delButton.IsEnter = true;
                    this.Invalidate(delButton.Rect);
                }
            }
            else
            {
                if (isEnterSound1)
                {
                    isEnterSound1 = false;
                    this.Invalidate(rectSound1);
                }
                if (isEnterSound2)
                {
                    isEnterSound2 = false;
                    this.Invalidate(rectSound2);
                }
                if (flagButton.IsEnter)
                {
                    flagButton.IsEnter = false;
                    this.Invalidate(flagButton.Rect);
                }
                if (delButton.IsEnter) {
                    delButton.IsEnter = false;
                    this.Invalidate(delButton.Rect);
                }
            }
        }

        /// <summary>
        /// 鼠标点击事件
        /// 响应各个元素的点击事件
        /// </summary>
        /// <param name="e"></param>
        protected override void OnMouseClick(MouseEventArgs e)
        {
            base.OnMouseClick(e);
            if (IsInRangle(e.X, e.Y, rectSound1))
            {
                if (mouseEnterSound != null)
                {
                    mouseEnterSound(this, 0);
                }
            }
            else if (IsInRangle(e.X, e.Y, rectSound2))
            {
                if (mouseEnterSound != null)
                {
                    mouseEnterSound(this, 1);
                }
            }
            else if (IsInRangle(e.X, e.Y, flagButton.Rect))
            {
                if (mouseClickFlag != null)
                {
                    mouseClickFlag(this, e);
                }
            }
            else if (IsInRangle(e.X, e.Y, delButton.Rect)) {
                if (mouseClickDelete != null) {
                    mouseClickDelete(this,e);
                }
            }
        }
        /// <summary>
        /// 判断是否再此矩形内
        /// </summary>
        /// <param name="rect"></param>
        /// <returns></returns>
        bool IsInRangle(int x,int y,Rectangle rect) {
            if (x >= rect.Left && x <= rect.Left + rect.Width
                 && y >= rect.Top && y <= rect.Top + rect.Height)
            {
                return true;
            }
            return false;
        }
        /// <summary>
        /// 取文字宽度
        /// </summary>
        /// <param name="gp"></param>
        /// <param name="str"></param>
        /// <param name="font"></param>
        /// <returns></returns>
        float GetTextWidth(Graphics gp,string str, Font font) {
            SizeF size = gp.MeasureString(DictName, fontDict);
            return size.Width;
        }

       
    }

    /// <summary>
    /// 描述ui元素
    /// </summary>
    class UIRectangle {
        public Image NormalImage { set; get; }
        public Image HightImage { set; get;}
        public Rectangle Rect { set; get; }
        public bool IsEnter { set; get; }

        public UIRectangle(Image img1,Image img2) {
            this.NormalImage = img1;
            this.HightImage = img2;
            IsEnter = false;
        }
    }

    /// <summary>
    /// 发音图标触发事件类型
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="index"></param>
    public delegate void SoundEvent(object sender, int index);
}

猜你喜欢

转载自blog.csdn.net/qq870841070/article/details/85375807
今日推荐