为MenuStrip增加一个渲染器

    Office 2007 的菜单效果真的是绚丽,但在应该的专业领域的应用开发中大部分都不是很需要这效果,虽然很多的Ribbon能达到这效果,但同VS提供的可视化开发还是存在很大的差距,VS的可视化开发速度快,效率高,操作简单,容易上手。但有时为了更近人的界面,我们也可以给MenuStrip装饰一下。

    MenuStrip是通过MenuStripRenderer来完成菜单的绘制效果的,Framework有三个渲染器,我们就继承其中一个,通过让重写其中的部分方法来达到不同的效果。

    这里实现的功能有:为菜单或工具栏添加一个水印。菜单的图标或工具栏的图标做一个鼠标移进时加亮的效果(只需一张图片即可实现)。至于重给菜单或工具栏的底色,用户可以自己实现。

    1.继承ToolStripProfessionalRenderer

    ToolStripProfessionalRenderer就是从工具箱拖出ToolStrip的默认效果

    属性:WatermarkImage  水印图片  

    属性:WatermarkTransparency 透明效果(0-255)

    属性:WatermarkGrayEffect  是否使用灰度效果

    属性:BrightValue  鼠标进入时图片增加亮度的效果

 

    图片增亮和水印效果是数字图像处理技术,具体的算法,可以在网上查找,这里有个透明的效果是经过自己研究出来的。

 

    重写OnRenderItemImage方法,判断菜单项的状态,把正常的图片或增亮的图片赋给Renderer。

    重写OnRenderToolStripBackground方法,实现水印功能

 

代码片段:

 

/***************************************************************************************************************
 * 文件名称:JWMenuStripRenderer.cs
 *
 * 功能描述:菜单 渲染器。更改鼠标进入时图片自动增亮的功能。
 *
 * 创建日期:2009-10-16
 *
 * 创 建 人:Lance Yang
 *
 * 修改:
 *      2009-10-15     Lance Yang       -修改内容。
 *
 * **************************************************************************************************************/
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Drawing2D;

namespace LC.Client.Controls
{
    /// <summary>
    /// ToolStrip 渲染器。更改背景为过度显示和鼠标进入时图片自动增亮的功能。
    /// </summary>
    public class LCMenuStripRenderer : ToolStripProfessionalRenderer
    {
        List<EtyImageState> m_ImageList = new List<EtyImageState>();

        public LCMenuStripRenderer()
        {
            this.RoundedEdges = false;
        }

        private int m_WatermarkTransparency = 255;
        /// <summary>
        /// 水印显示的透明度。
        /// </summary>
        ///
        public int WatermarkTransparency
        {
            get { return m_WatermarkTransparency; }
            set
            {
                if (value > 255 || value < 0)
                    throw new Exception("请输入 0 - 255 之间的一个数值。");

                m_WatermarkTransparency = value;
                WatermarkImage = m_WatermarkImage;
            }
        }

        private bool m_watermarkGrayEffect = false;

        /// <summary>
        /// 水印的灰度效果,默认为 false;
        /// </summary>
        ///        
        public bool WatermarkGrayEffect
        {
            get { return m_watermarkGrayEffect; }
            set
            {
                m_watermarkGrayEffect = value;
                WatermarkImage = m_WatermarkImage;
            }
        }


        private Bitmap m_WatermarkImage;
        /// <summary>
        /// 水印的图片。
        /// </summary>
        ///
        public Bitmap WatermarkImage
        {
            get { return m_WatermarkImage; }
            set
            {
                m_WatermarkImage = value;
                //制作水印
                if (value != null)
                {
                    Bitmap img = new Bitmap(value);

                    if (m_watermarkGrayEffect)
                        ImageTool.GrayByPixels(img);
                    if (m_WatermarkTransparency != 255)
                        ImageTool.WatermarkImage(img, m_WatermarkTransparency);

                    m_WatermarkImage = img;
                }
                else
                    m_WatermarkImage = null;

            }
        }

        private int m_brightValue = 26;
        /// <summary>
        /// 鼠标进入时的图片增亮值。默认为 26
        /// </summary>
        public int BrightValue
        {
            get { return m_brightValue; }
            set { m_brightValue = value; }
        }

        protected override void OnRenderItemImage(ToolStripItemImageRenderEventArgs e)
        {
            Bitmap img = e.Image as Bitmap;
            if (img != null)
            {
                bool isEqualsInitImage = false;
                EtyImageState ety = EtyImageState.GetEtyImageState(m_ImageList, img.GetHashCode(), out isEqualsInitImage);
                if (ety == null)
                {
                    ety = new EtyImageState();
                    ety.InitImage = img;
                    ety.LightImage = ImageTool.Brightness(img, m_brightValue);
                    m_ImageList.Add(ety);
                }

                if (e.Item.Selected)
                    e.Item.Image = ety.LightImage;
                else
                    e.Item.Image = ety.InitImage;
            }
            base.OnRenderItemImage(e);
        }

        int borderPadding = 2;
        /// <summary>
        /// 水印的边距,默认为2
        /// </summary>
        public int WatermarkPadding
        {
            get { return borderPadding; }
            set { borderPadding = value; }
        }

        protected override void OnRenderToolStripBackground(ToolStripRenderEventArgs e)
        {
            base.OnRenderToolStripBackground(e);

            if (e.ToolStrip is ToolStripDropDown)    //过滤,根据需要可能还有更多的过滤
                return;


            ////System.Diagnostics.Debug.WriteLine("显示水印");
            //显示水印。
            if (m_WatermarkImage != null)
            {
                Point position = Point.Empty;
                int top = borderPadding;
                int left = 0;
                int width = 0;
                int height = 0;
                if (m_WatermarkImage.Height > e.ToolStrip.Height - borderPadding * 2)
                {
                    //重新定义图片的显示宽高
                    double rate = (double)m_WatermarkImage.Width / (double)m_WatermarkImage.Height;
                    height = e.ToolStrip.Height - borderPadding * 2;
                    width = Convert.ToInt32(rate * height);
                }
                else
                {
                    width = m_WatermarkImage.Width;
                    height = m_WatermarkImage.Height;
                    top = (e.ToolStrip.Height - height) / 2;

                }
                left = e.ToolStrip.Width - width - borderPadding * 2;

                position = new Point(left, top);
                Rectangle rect = new Rectangle(left, top, width, height);
                e.Graphics.DrawImage(m_WatermarkImage, rect, new Rectangle(0, 0, m_WatermarkImage.Width, m_WatermarkImage.Height), GraphicsUnit.Pixel);
            }
        }
    }
}

 

 

 

    /// <summary>
    /// 为保存图片的状态而设
    /// </summary>
    internal class EtyImageState
    {
        public int InitImageKey
        {
            get
            {
                if (m_InitImage == null)
                    return -1;
                else
                    return m_InitImage.GetHashCode();
            }
        }

        private Image m_InitImage;

        public Image InitImage
        {
            get { return m_InitImage; }
            set { m_InitImage = value; }
        }

        public int LightImageKey
        {
            get
            {
                if (m_LightImage == null)
                    return -1;
                else
                    return m_LightImage.GetHashCode();
            }
        }

        private Image m_LightImage;

        public Image LightImage
        {
            get { return m_LightImage; }
            set { m_LightImage = value; }
        }

        /// <summary>
        /// 从集合
        /// </summary>
        /// <param name="list"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public static EtyImageState GetEtyImageState(List<EtyImageState> list, int key, out bool isEqualsInitImage)
        {
            isEqualsInitImage = false;
            EtyImageState retEty = null;
            foreach (EtyImageState ety in list)
            {
                if (ety.InitImageKey == key)
                {
                    isEqualsInitImage = true;
                    retEty = ety;
                    break;
                }
                else if (ety.LightImageKey == key)
                {
                    retEty = ety;
                    break;
                }
            }
            return retEty;
        }

    }

 

数字处理算法类:

 

using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.IO;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;

namespace LC.Client.Controls
{
    public static class ImageTool
    {
        /// <summary>
        /// 根据字符串生成图片。
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public static Bitmap DeserializeFromBase64(string data)
        {
            // Decode the string and create a memory stream
            // on the decoded string data.
            MemoryStream stream =
                new MemoryStream(Convert.FromBase64String(data));

            // Create a new bitmap from the stream.
            Bitmap b = new Bitmap(stream);

            return b;
        }
        //图片 转为    base64编码的文本
        public static string ImgToBase64String(Image bmp)
        {
            MemoryStream ms = new MemoryStream();
            bmp.Save(ms, bmp.RawFormat);
            byte[] arr = new byte[ms.Length];
            ms.Position = 0;
            ms.Read(arr, 0, (int)ms.Length);
            ms.Close();
            String strbase64 = Convert.ToBase64String(arr);
            return strbase64;
        }

        /// <summary>
        /// 图片增亮。
        /// </summary>
        /// <param name="img"></param>
        /// <returns></returns>
        public static Image Brightness(Image img, int brightValue)
        {
            int percent = brightValue;
            Single v = 0.006F * percent;
            Single[][] matrix = {
                new Single[] { 1, 0, 0, 0, 0 },
                new Single[] { 0, 1, 0, 0, 0 },
                new Single[] { 0, 0, 1, 0, 0 },
                new Single[] { 0, 0, 0, 1, 0 },
                new Single[] { v, v, v, 0, 1 }
            };
            System.Drawing.Imaging.ColorMatrix cm = new System.Drawing.Imaging.ColorMatrix(matrix);
            System.Drawing.Imaging.ImageAttributes attr = new System.Drawing.Imaging.ImageAttributes();
            attr.SetColorMatrix(cm);
            //Image tmp
            //Image tmp = (Image)img.Clone();
            Bitmap tmp = new Bitmap(img);
            Graphics g = Graphics.FromImage(tmp);
            try
            {
                Rectangle destRect = new Rectangle(0, 0, img.Width, img.Height);
                g.DrawImage(tmp, destRect, 0, 0, tmp.Width, tmp.Height, GraphicsUnit.Pixel, attr);
            }
            finally
            {
                g.Dispose();
            }

            return tmp;

        }

        //处理不了透明的背景
        /// <summary>
        /// 制作水印图片
        /// </summary>
        /// <param name="iTheImage">要制作水印的图片</param>
        /// <param name="width">制作水印的宽</param>
        /// <param name="height">制作水印的高</param>
        /// <returns></returns>
        public static Bitmap WatermarkImage(Bitmap iTheImage, int width, int height)
        {
            //Bitmap watermark = new Bitmap(width, height,
            //        PixelFormat.Format24bppRgb);
            Bitmap watermark = new Bitmap(iTheImage);

            Graphics g = Graphics.FromImage(watermark);
            g.Clear(Color.White);
            //g.Clear(iTheImage.GetPixel(0,0));
            g.SmoothingMode = SmoothingMode.HighQuality;
            g.InterpolationMode = InterpolationMode.High;

            ImageAttributes imageAttributes = new ImageAttributes();
            ColorMap colorMap = new ColorMap();

            colorMap.OldColor = Color.FromArgb(255, 0, 255, 0);
            colorMap.NewColor = Color.FromArgb(0, 0, 0, 0);
            ColorMap[] remapTable = { colorMap };

            imageAttributes.SetRemapTable(remapTable, ColorAdjustType.Bitmap);

            float[][] colorMatrixElements = {
                                                new float[] {1.0f, 0.0f, 0.0f, 0.0f, 0.0f},
                                                new float[] {0.0f, 1.0f, 0.0f, 0.0f, 0.0f},
                                                new float[] {0.0f, 0.0f, 1.0f, 0.0f, 0.0f},
                                                new float[] {0.0f, 0.0f, 0.0f, 0.3f, 0.0f},
                                                new float[] {0.0f, 0.0f, 0.0f, 0.0f, 1.0f}
                                            };

            ColorMatrix colorMatrix = new ColorMatrix(colorMatrixElements);

            imageAttributes.SetColorMatrix(colorMatrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);

            #region 保留学习

            ////int WatermarkWidth = 0;
            ////int WatermarkHeight = 0;
            ////double bl = 1d;

            //////计算水印图片的比率
            //////取背景的1/4宽度来比较
            ////if ((width > watermark.Width * 4) && (height > watermark.Height * 4))
            ////{
            ////    bl = 1;
            ////}
            ////else if ((width > watermark.Width * 4) && (height < watermark.Height * 4))
            ////{
            ////    bl = Convert.ToDouble(height / 4) / Convert.ToDouble(watermark.Height);

            ////}
            ////else if ((width < watermark.Width * 4) && (height > watermark.Height * 4))
            ////{
            ////    bl = Convert.ToDouble(width / 4) / Convert.ToDouble(watermark.Width);
            ////}
            ////else
            ////{
            ////    if ((width * watermark.Height) > (height * watermark.Width))
            ////    {
            ////        bl = Convert.ToDouble(height / 4) / Convert.ToDouble(watermark.Height);

            ////    }
            ////    else
            ////    {
            ////        bl = Convert.ToDouble(width / 4) / Convert.ToDouble(watermark.Width);

            ////    }

            ////}

            ////WatermarkWidth = Convert.ToInt32(watermark.Width * bl);
            ////WatermarkHeight = Convert.ToInt32(watermark.Height * bl);


            ////switch (_watermarkPosition)
            ////{
            ////    case "WM_TOP_LEFT":
            ////        xpos = 10;
            ////        ypos = 10;
            ////        break;
            ////    case "WM_TOP_RIGHT":
            ////        xpos = _width - WatermarkWidth - 10;
            ////        ypos = 10;
            ////        break;
            ////    case "WM_BOTTOM_RIGHT":
            ////        xpos = _width - WatermarkWidth - 10;
            ////        ypos = _height - WatermarkHeight - 10;
            ////        break;
            ////    case "WM_BOTTOM_LEFT":
            ////        xpos = 10;
            ////        ypos = _height - WatermarkHeight - 10;
            ////        break;
            ////}

            #endregion

            try
            {
                Rectangle destRect = new Rectangle(0, 0, watermark.Width, watermark.Height);

                g.DrawImage(iTheImage, destRect, 0, 0, watermark.Width, watermark.Height,
                    GraphicsUnit.Pixel,
                    imageAttributes);
            }
            finally
            {
                imageAttributes.Dispose();
                g.Dispose();
            }

            return watermark;
        }

        /// <summary>
        /// 制作透明的图片。对透明背景保留原来的样子。
        /// </summary>
        /// <param name="bmpobj"></param>
        /// <param name="transValue">透明度 (0 - 255)</param>
        public static void WatermarkImage(Bitmap bmpobj, int transValue)
        {
            for (int i = 0; i < bmpobj.Height; i++)
            {
                for (int j = 0; j < bmpobj.Width; j++)
                {
                    Color dot = bmpobj.GetPixel(j, i);
                    if (dot.A > 0)
                    {
                        bmpobj.SetPixel(j, i, Color.White);
                        bmpobj.SetPixel(j,i,Color.FromArgb(transValue,dot.R,dot.G,dot.B));
                    }
                }
            }
        }

        /// <summary>
        /// 灰度转换,逐点方式
        /// </summary>
        public static void GrayByPixels(Bitmap bmpobj)
        {
            for (int i = 0; i < bmpobj.Height; i++)
            {
                for (int j = 0; j < bmpobj.Width; j++)
                {
                    Color dot = bmpobj.GetPixel(j, i);
                    if (dot.A > 0)
                    {
                        int tmpValue = GetGrayNumColor(dot);
                        bmpobj.SetPixel(j, i, Color.FromArgb(tmpValue, tmpValue, tmpValue));
                    }
                }
            }
        }
        /// <summary>
        /// 根据RGB,计算灰度值
        /// </summary>
        /// <param name="posClr">Color值</param>
        /// <returns>灰度值,整型</returns>
        private static int GetGrayNumColor(System.Drawing.Color posClr)
        {
            return (posClr.R * 19595 + posClr.G * 38469 + posClr.B * 7472) >> 16;
        }


        ////public static bool Invert(Bitmap b)
        ////{
        ////    BitmapData bmData = b.LockBits(new Rectangle(0, 0, b.Width, b.Height),
        ////       ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
        ////    int stride = bmData.Stride;
        ////    System.IntPtr Scan0 = bmData.Scan0;
        ////    unsafe
        ////    {
        ////        byte* p = (byte*)(void*)Scan0;
        ////        int nOffset = stride - b.Width * 3;
        ////        int nWidth = b.Width * 3;
        ////        for (int y = 0; y < b.Height; ++y)
        ////        {
        ////            for (int x = 0; x < nWidth; ++x)
        ////            {
        ////                p[0] = (byte)(255 - p[0]);
        ////                ++p;
        ////            }
        ////            p += nOffset;
        ////        }
        ////    }
        ////    b.UnlockBits(bmData);
        ////    return true;
        ////}

        ////public static bool Gray(Bitmap b)
        ////{
        ////    BitmapData bmData = b.LockBits(new Rectangle(0, 0, b.Width, b.Height),
        ////              ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
        ////    int stride = bmData.Stride;
        ////    System.IntPtr Scan0 = bmData.Scan0;
        ////    unsafe
        ////    {
        ////        byte* p = (byte*)(void*)Scan0;
        ////        int nOffset = stride - b.Width * 3;
        ////        byte red, green, blue;
        ////        for (int y = 0; y < b.Height; ++y)
        ////        {
        ////            for (int x = 0; x < b.Width; ++x)
        ////            {
        ////                blue = p[0];
        ////                green = p[1];
        ////                red = p[2];
        ////                p[0] = p[1] = p[2] = (byte)(.299 * red + .587 * green + .114 * blue);
        ////                p += 3;
        ////            }
        ////            p += nOffset;
        ////        }
        ////    }
        ////    b.UnlockBits(bmData);
        ////    return true;
        ////}

        ////public static bool Brightness(Bitmap b, int nBrightness)
        ////{
        ////    if (nBrightness < -255 || nBrightness > 255)
        ////        return false;
        ////    BitmapData bmData = b.LockBits(new Rectangle(0, 0, b.Width,
        ////                                b.Height), ImageLockMode.ReadWrite,
        ////                                PixelFormat.Format24bppRgb);
        ////    int stride = bmData.Stride;
        ////    System.IntPtr Scan0 = bmData.Scan0;
        ////    int nVal = 0;
        ////    unsafe
        ////    {
        ////        byte* p = (byte*)(void*)Scan0;
        ////        int nOffset = stride - b.Width * 3;
        ////        int nWidth = b.Width * 3;
        ////        for (int y = 0; y < b.Height; ++y)
        ////        {
        ////            for (int x = 0; x < nWidth; ++x)
        ////            {
        ////                nVal = (int)(p[0] + nBrightness);
        ////                if (nVal < 0) nVal = 0;
        ////                if (nVal > 255) nVal = 255;
        ////                p[0] = (byte)nVal;
        ////                ++p;
        ////            }
        ////            p += nOffset;
        ////        }
        ////    }
        ////    b.UnlockBits(bmData);
        ////    return true;
        ////}
    }
}

 

 

 

 

posted @ 2011-02-11 13:09  Lance Yang  阅读(746)  评论(2编辑  收藏  举报