• 为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;
            ////}
        }
    }

  • 相关阅读:
    随机数组找丢失数据
    js打开新页面 关闭当前页 关闭父页面
    Markdown测试
    ThinkPHP中的时间自动填充 无法获取时间
    页面在谷歌浏览器和IE浏览器顶部多出空白行,火狐显示正常
    Thinkphp中验证码不显示解决办法
    106运用SWITCH语句打印星期几的单词
    声明两个变量并赋值计算出矩形的面积
    不用*用移位运算符计算21*16的数值是多少
    97.经典实例,计算球形的面积和体积
  • 原文地址:https://www.cnblogs.com/Yjianyong/p/1951254.html
Copyright © 2020-2023  润新知