C# 编写带图标和tooltip的ListBox[续]--Item背景色交替变化

来源:互联网 发布:产品介绍网站源码 编辑:程序博客网 时间:2024/04/30 06:11

跟随前文http://blog.csdn.net/luols/article/details/7184155的脚步继续探索,我们对重写的ListBox项背景色加以控制,让其交替变化显示,并对选中项背景色用渐变刷子,当项被选中时,背景色有一个渐变过程,我们先看下最终的效果:

关键代码在前文已有详尽描述,这里只补充三个属性,以及OnDrawItem方法的重写

三个属性(已设置默认值):

        private Color _rowBackColor1 = Color.White;        private Color _rowBackColor2 = Color.FromArgb(254, 216, 249);        private Color _selectedColor = Color.FromArgb(102, 206, 255);        /// <summary>        /// 选中项背景色        /// </summary>        [Description("选中项背景色")]        public Color SelectedColor        {            get { return _selectedColor; }            set { _selectedColor = value; }        }        /// <summary>        /// 奇数项背景色        /// </summary>        [Description("奇数项背景色")]        public Color RowBackColor1        {            get { return _rowBackColor1; }            set { _rowBackColor1 = value; }        }        /// <summary>        /// 偶数项背景色        /// </summary>        [Description("偶数项背景色")]        public Color RowBackColor2        {            get { return _rowBackColor2; }            set { _rowBackColor2 = value; }        }


OnDrawItem方法(主要增加了对项背景色的控制)

        protected override void OnDrawItem(DrawItemEventArgs e)        {            e.DrawBackground();            e.DrawFocusRectangle();            if (e.Index != MyListBox.NoMatches && base.Items.Count > 0)            {                Graphics g = e.Graphics;                StringFormat sf = new StringFormat();                sf.Trimming = StringTrimming.EllipsisCharacter; //超出指定矩形区域部分用"..."替代                sf.LineAlignment = StringAlignment.Center;//垂直居中                MyListBoxItem item = (MyListBoxItem)Items[e.Index];                if ((e.State & DrawItemState.Selected) == DrawItemState.Selected)                { //选中项背景色设置                    RenderHelper.RenderBackgroundInternal(                        g, e.Bounds, _selectedColor, _selectedColor,                        Color.FromArgb(200, 255, 255, 255),                        0.45f, true, LinearGradientMode.Vertical);                }                else                {                    Color backColor;                    if (e.Index % 2 == 0) //偶数项                    {                        backColor = _rowBackColor2;                    }                    else //奇数项                    {                        backColor = _rowBackColor1;                    }                    using (SolidBrush brush = new SolidBrush(backColor))                    {                        g.FillRectangle(brush, e.Bounds);                    }                }                SizeF size = g.MeasureString(item.Text, e.Font); //获取项文本尺寸                if (HasIcon) //带图标时                {                    if (size.Width > e.Bounds.Width - this.IconWidth) //项文本宽度超过 项宽-图标宽度                    {                        item.ShowTip = true; //显示tooltip                    }                    /* 获取指定矩形区域,注意不能直接用项所在矩形,否则DrawString时会出现自动换行                     * 的情况。前面说超出指定矩形区域用“...”替代 指的是DrawString方法会先塞满整个                     * 矩形区域,如果区域高度够时,就会出现自动换行的情况 ******/                    RectangleF rectF = new RectangleF(e.Bounds.Left,                        e.Index * this.ItemHeight + (this.ItemHeight - size.Height) / 2.0f,                        e.Bounds.Width - this.IconWidth, size.Height);                    //写 项文本                    g.DrawString(item.Text, e.Font, new SolidBrush(e.ForeColor), rectF, sf);                    if (item.ItemImage != null) //在项右侧 画图标                    {                        g.InterpolationMode = InterpolationMode.HighQualityBilinear;                        /* 注意不能用DrawImage(img, x, y)方法,务必指定图标的大小,                         * 否则会导致图标被放大,读者不妨一试 :)  *****/                        g.DrawImage(item.ItemImage, e.Bounds.Right - this.IconWidth, e.Bounds.Top, this.IconWidth, this.IconHeight);                    }                }                else //不带图标                {                    if (size.Width > e.Bounds.Width) //项文本宽度超过 项宽                    {                        item.ShowTip = true; //显示tooltip                    }                    //获取指定矩形区域                    RectangleF rectF = new RectangleF(e.Bounds.Left,                        e.Index * this.ItemHeight + (this.ItemHeight - size.Height) / 2.0f,                        e.Bounds.Width, size.Height);                    //写 项文本                    g.DrawString(item.Text, e.Font, new SolidBrush(e.ForeColor), rectF, sf);                }            }            base.OnDrawItem(e);        }


这里面有一个RenderHelper类

    class RenderHelper    {        public static void RenderBackgroundInternal(Graphics g, Rectangle rect,            Color baseColor, Color borderColor, Color innerBorderColor,            float basePosition, bool drawBorder, LinearGradientMode mode)        {            if (drawBorder)            {                rect.Width--;                rect.Height--;            }            using (LinearGradientBrush brush = new LinearGradientBrush(                rect, Color.Transparent, Color.Transparent, mode))            {                Color[] colors = new Color[4];                colors[0] = GetColor(baseColor, 0, 35, 24, 9);                colors[1] = GetColor(baseColor, 0, 13, 8, 3);                colors[2] = baseColor;                colors[3] = GetColor(baseColor, 0, 68, 69, 54);                ColorBlend blend = new ColorBlend();                blend.Positions = new float[] { 0.0f, basePosition, basePosition + 0.05f, 1.0f };                blend.Colors = colors;                brush.InterpolationColors = blend;                g.FillRectangle(brush, rect);            }            if (baseColor.A > 80)            {                Rectangle rectTop = rect;                if (mode == LinearGradientMode.Vertical)                {                    rectTop.Height = (int)(rectTop.Height * basePosition);                }                else                {                    rectTop.Width = (int)(rect.Width * basePosition);                }                using (SolidBrush brushAlpha =                    new SolidBrush(Color.FromArgb(80, 255, 255, 255)))                {                    g.FillRectangle(brushAlpha, rectTop);                }            }            if (drawBorder)            {                using (Pen pen = new Pen(borderColor))                {                    g.DrawRectangle(pen, rect);                }                rect.Inflate(-1, -1);                using (Pen pen = new Pen(innerBorderColor))                {                    g.DrawRectangle(pen, rect);                }            }        }        private static Color GetColor(Color colorBase, int a, int r, int g, int b)        {            int a0 = colorBase.A;            int r0 = colorBase.R;            int g0 = colorBase.G;            int b0 = colorBase.B;            if (a + a0 > 255) { a = 255; } else { a = Math.Max(a + a0, 0); }            if (r + r0 > 255) { r = 255; } else { r = Math.Max(r + r0, 0); }            if (g + g0 > 255) { g = 255; } else { g = Math.Max(g + g0, 0); }            if (b + b0 > 255) { b = 255; } else { b = Math.Max(b + b0, 0); }            return Color.FromArgb(a, r, g, b);        }    }