C#自定义控件七水波纹

C#自定义控件七水波纹

效果图:

这个是网上搞来的,本人修改了一小点代码,不过用C#写这个效率有点低,还是汇编写的最好。

贴出全部代码:

//控件名:myWaterWave

//作者:刘典武

//时间:2011-06-09

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Drawing;

using System.Data;

using System.Text;

using System.Windows.Forms;

using System.Runtime.InteropServices;

using System.Drawing.Imaging;

namespace myControl

{

    public struct DropData

    {

        public int x;

        public int y;

        public int radius;

        public int height;

    }

    public partial class myWaterWave : UserControl

    {

        public myWaterWave()

        {

            InitializeComponent();

            this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);

            this.SetStyle(ControlStyles.DoubleBuffer, true);

            this.SetStyle(ControlStyles.ResizeRedraw, true);

            this.SetStyle(ControlStyles.Selectable, true);

            this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);

            this.SetStyle(ControlStyles.UserPaint, true);

            myWaterTimer = new Timer();

            myWaterTimer.Interval = 50;

            myWaterTimer.Tick += new EventHandler(myWaterTimer_Tick);

            myDropsTimer = new Timer();

            myDropsTimer.Interval = 50000;

            myDropsTimer.Tick += new EventHandler(myDropsTimer_Tick);

        }

        private void myDropsTimer_Tick(object sender, EventArgs e)

        {

            try

            {

                this.myDropsTimer.Enabled = false;

                int _percent = (int)(0.005 * (this.Width + this.Height));

                int _dropsNumber = r.Next(_percent);

                int _drop = 0;

                for (int i = 0; i < _dropsNumber; i++)

                {

                    _drop = r.Next(drops.Length);

                    DropWater(drops[_drop].x, drops[_drop].y, drops[_drop].radius, drops[_drop].height);

                }

                this.myDropsTimer.Interval = r.Next(15 * _percent) + 1;

                this.myDropsTimer.Enabled = true;

            }

            catch { }

        }

        private void myWaterTimer_Tick(object sender, EventArgs e)

        {

            try

            {

                if (fastImage.IsLocked()) return;

                this.myWaterTimer.Stop();

                PaintWater();

                this.myWaterTimer.Start();

            }

            catch { }

        }

        private static int bitmapWidth = 0;

        private static int bitmapHeight = 0;

        private static int bits = 4;

        private static DropData[] drops;

        private FastBitmap fastImage = null;

        private FastBitmap originalImage = null;

        public int currentHeightBuffer = 0;

        public int newHeightBuffer = 0;

        private byte[] bitmapOriginalBytes;

        private Random r = new Random();

        private static int[][][] waveHeight;

        bool isLoaded = false;

        private Image image;

        private bool auto;

        private int number;

        private Timer myWaterTimer, myDropsTimer;

        /// <summary>

        /// 绘画的图片

        /// </summary>

        public Image Image

        {

            get { return image; }

            set { image = value; }

        }

        /// <summary>

        /// 自动产生

        /// </summary>

        public bool Auto

        {

            get { return auto; }

            set { auto = value; }

        }

        /// <summary>

        /// 源点数

        /// </summary>

        public int Number

        {

            get { return number; }

            set { number = value; }

        }

        public void load()

        {

            try

            {

                isLoaded = true;

                this.Width = image.Width;

                this.Height = image.Height;

                bitmapWidth = image.Width;

                bitmapHeight = image.Height;

                waveHeight = new int[bitmapWidth][][];

                for (int i = 0; i < bitmapWidth; i++)

                {

                    waveHeight[i] = new int[bitmapHeight][];

                    for (int j = 0; j < bitmapHeight; j++)

                    {

                        waveHeight[i][j] = new int[2];

                    }

                }

                CreateBitmap();

                if (auto)

                {

                    CreateWaterDrops();

                    this.myWaterTimer.Enabled = true;

                    this.myDropsTimer.Interval = 50;

                    this.myDropsTimer.Enabled = true;

                }

                else

                {

                    this.MouseMove += new MouseEventHandler(myWaterWave_MouseMove);

                }

            }

            catch { }

        }

        private void CreateBitmap()

        {

            originalImage = new FastBitmap((Bitmap)(image).Clone(), bits);

            originalImage.LockBits();

            fastImage = new FastBitmap((Bitmap)(image).Clone(), bits);

            bitmapOriginalBytes = new byte[bits * fastImage.Width() * fastImage.Height()];

            fastImage.LockBits();

            Marshal.Copy(fastImage.Data().Scan0, bitmapOriginalBytes, 0, bitmapOriginalBytes.Length);

            fastImage.Release();

        }

        private void DropWater(int x, int y, int radius, int height)

        {

            long _distance;

            int _x;

            int _y;

            Single _ratio;

            _ratio = (Single)((Math.PI / (Single)radius));

            for (int i = -radius; i <= radius; i++)

            {

                for (int j = -radius; j <= radius; j++)

                {

                    _x = x + i;

                    _y = y + j;

                    if ((_x >= 0) && (_x <= bitmapWidth - 1) && (_y >= 0) && (_y <= bitmapHeight - 1))

                    {

                        _distance = (long)Math.Sqrt(i * i + j * j);

                        if (_distance <= radius)

                        {

                            waveHeight[_x][_y][currentHeightBuffer] = (int)(height * Math.Cos((Single)_distance * _ratio));

                        }

                    }

                }

            }

        }

        private void PaintWater()

        {

            newHeightBuffer = (currentHeightBuffer + 1) % 2;

            fastImage.LockBits();

            byte[] _bufferBits = new byte[bits * fastImage.Width() * fastImage.Height()];

            Marshal.Copy(fastImage.Data().Scan0, _bufferBits, 0, _bufferBits.Length);

            int _offX;

            int _offY;

            for (int _x = 1; _x < bitmapWidth - 1; _x++)

            {

                for (int _y = 1; _y < bitmapHeight - 1; _y++)

                {

                    unchecked

                    {

                        waveHeight[_x][_y][newHeightBuffer] = ((

                            waveHeight[_x - 1][_y][currentHeightBuffer] +

                            waveHeight[_x - 1][_y - 1][currentHeightBuffer] +

                            waveHeight[_x][_y - 1][currentHeightBuffer] +

                            waveHeight[_x + 1][_y - 1][currentHeightBuffer] +

                            waveHeight[_x + 1][_y][currentHeightBuffer] +

                            waveHeight[_x + 1][_y + 1][currentHeightBuffer] +

                            waveHeight[_x][_y + 1][currentHeightBuffer] +

                            waveHeight[_x - 1][_y + 1][currentHeightBuffer]) >> 2)

                        - waveHeight[_x][_y][newHeightBuffer];

                    }

                    waveHeight[_x][_y][newHeightBuffer] -= (waveHeight[_x][_y][newHeightBuffer] >> 5);

                    _offX = ((waveHeight[_x - 1][_y][newHeightBuffer] - waveHeight[_x + 1][_y][newHeightBuffer])) >> 3;

                    _offY = ((waveHeight[_x][_y - 1][newHeightBuffer] - waveHeight[_x][_y + 1][newHeightBuffer])) >> 3;

                    if ((_offX == 0) && (_offY == 0)) continue;

                    if (_x + _offX <= 0) _offX = -_x;

                    if (_x + _offX >= bitmapWidth - 1) _offX = bitmapWidth - _x - 1;

                    if (_y + _offY <= 0) _offY = -_y;

                    if (_y + _offY >= bitmapHeight - 1) _offY = bitmapHeight - _y - 1;

                    _bufferBits[bits * (_x + _y * bitmapWidth) + 0] = bitmapOriginalBytes[bits * (_x + _offX + (_y + _offY) * bitmapWidth) + 0];

                    _bufferBits[bits * (_x + _y * bitmapWidth) + 1] = bitmapOriginalBytes[bits * (_x + _offX + (_y + _offY) * bitmapWidth) + 1];

                    _bufferBits[bits * (_x + _y * bitmapWidth) + 2] = bitmapOriginalBytes[bits * (_x + _offX + (_y + _offY) * bitmapWidth) + 2];

                }

            }

            Marshal.Copy(_bufferBits, 0, fastImage.Data().Scan0, _bufferBits.Length);

            currentHeightBuffer = newHeightBuffer;

            this.Invalidate();

        }

        private void CreateWaterDrops()

        {

            int _dropX;

            int _dropY;

            int _dropRadius;

            int _height;

            int _percent = (int)(0.0015 * (this.Width + this.Height));

            drops = new DropData[number];

            for (int i = 0; i < drops.Length; i++)

            {

                _dropX = r.Next(bitmapWidth);

                _dropY = r.Next(bitmapHeight);

                _height = r.Next(400);

                _dropRadius = r.Next(4 * _percent);

                if (_dropRadius < 4) _dropRadius = 4;

                drops[i].x = _dropX;

                drops[i].y = _dropY;

                drops[i].radius = _dropRadius;

                drops[i].height = _height;

            }

        }

        private void myWaterWave_Paint(object sender, PaintEventArgs e)

        {

            try

            {

                if (isLoaded)

                {

                    fastImage.Release();

                    e.Graphics.DrawImage(fastImage.Bitmap, 0, 0, fastImage.Width(), fastImage.Height());

                }

            }

            catch { }

        }

        private void myWaterWave_MouseMove(object sender, MouseEventArgs e)

        {

            int dropX;

            int dropY;

            int dropRadius;

            int height;

            int percent = (int)(0.0015 * (this.Width + this.Height));

            drops = new DropData[1];

            dropX = e.X;

            dropY = e.Y;

            height = r.Next(400);

            dropRadius = r.Next(4 * percent);

            if (dropRadius < 4) dropRadius = 4;

            drops[0].x = dropX;

            drops[0].y = dropY;

            drops[0].radius = dropRadius;

            drops[0].height = height;

            this.myWaterTimer.Enabled = true;

            this.myDropsTimer.Interval = 50;

            this.myDropsTimer.Enabled = true;

        }

        private void myWaterWave_MouseLeave(object sender, EventArgs e)

        {

            this.myDropsTimer.Enabled = false;

        }

    }

    public unsafe class FastBitmap

    {

        public struct PixelData

        {

            public byte blue;

            public byte green;

            public byte red;

            public byte alpha;

        }

        Bitmap Subject;

        int SubjectWidth;

        BitmapData bitmapData = null;

        Byte* pBase = null;

        bool isLocked = false;

        int _bits = 0;

        public FastBitmap(Bitmap SubjectBitmap, int bits)

        {

            this.Subject = SubjectBitmap;

            _bits = bits;

            try

            {

                //LockBits();

            }

            catch (Exception ex)

            {

                throw ex;

            }

        }

        public void Release()

        {

            try

            {

                UnlockBits();

            }

            catch (Exception ex)

            {

                throw ex;

            }

        }

        public Bitmap Bitmap

        {

            get

            {

                return Subject;

            }

        }

        public void SetPixel(int X, int Y, Color Colour)

        {

            try

            {

                PixelData* p = PixelAt(X, Y);

                p->red = Colour.R;

                p->green = Colour.G;

                p->blue = Colour.B;

            }

            catch (AccessViolationException ave)

            {

                throw (ave);

            }

            catch (Exception ex)

            {

                throw ex;

            }

        }

        public Color GetPixel(int X, int Y)

        {

            try

            {

                PixelData* p = PixelAt(X, Y);

                return Color.FromArgb((int)p->red, (int)p->green, (int)p->blue);

            }

            catch (AccessViolationException ave)

            {

                throw (ave);

            }

            catch (Exception ex)

            {

                throw ex;

            }

        }

        public int Width() { return Subject.Width; }

        public int Height() { return Subject.Height; }

        public bool IsLocked() { return isLocked; }

        public BitmapData Data() { return bitmapData; }

        public void LockBits()

        {

            if (isLocked) return;

            try

            {

                GraphicsUnit unit = GraphicsUnit.Pixel;

                RectangleF boundsF = Subject.GetBounds(ref unit);

                Rectangle bounds = new Rectangle((int)boundsF.X,

                    (int)boundsF.Y,

                    (int)boundsF.Width,

                    (int)boundsF.Height);

                SubjectWidth = (int)boundsF.Width * sizeof(PixelData);

                if (SubjectWidth % _bits != 0)

                {

                    SubjectWidth = _bits * (SubjectWidth / _bits + 1);

                }

                if (_bits == 3)

                    bitmapData = Subject.LockBits(bounds, ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

                else

                    bitmapData = Subject.LockBits(bounds, ImageLockMode.ReadWrite, PixelFormat.Format32bppRgb);

                pBase = (Byte*)bitmapData.Scan0.ToPointer();

            }

            finally

            {

                isLocked = true;

            }

        }

        private PixelData* PixelAt(int x, int y)

        {

            return (PixelData*)(pBase + y * SubjectWidth + x * sizeof(PixelData));

        }

        private void UnlockBits()

        {

            if (bitmapData == nullreturn;

            Subject.UnlockBits(bitmapData);

            bitmapData = null;

            pBase = null;

            isLocked = false;

        }

    }

}

搞定!休息下!呵呵!请假回家相亲咯!


posted @ 2011-07-08 17:23  飞扬青云  阅读(3627)  评论(5编辑  收藏  举报