//添加自定义控件
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Drawing.Imaging; namespace My.UControl
{
public partial class WaveControl : Panel// Control
{
public WaveControl()
{
InitializeComponent();
this.Effect.Tick += new EventHandler(Effect_Tick);
this.Paint += new PaintEventHandler(WavesControl_Paint);
this.MouseMove += new MouseEventHandler(WavesControl_MouseMove); this.Effect.Enabled = true;
this.Effect.Interval = ;
SetStyle(ControlStyles.UserPaint, true);
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
SetStyle(ControlStyles.DoubleBuffer, true);
this.BackColor = Color.White;
}
public WaveControl(Bitmap bmp)
: this()
{
this.bmpImage = bmp;
}
#region Fields or Properties
private int scale = ;
/// <summary>
/// The scale of the wave matrix compared to the size of the image.
/// Use it for large images to reduce processor load.
///
/// 0 : wave resolution is the same than image resolution
/// 1 : wave resolution is half the image resolution
/// ...and so on
/// </summary>
public int Scale
{
get { return scale; }
set { scale = value; }
}
private Bitmap bmpImage;
/// <summary>
/// Background image
/// </summary>
public Bitmap BmpImage
{
get { return bmpImage; }
set
{
if (value == null)
return;
bmpImage = value;
bmpHeight = bmpImage.Height;
bmpWidth = bmpImage.Width;
waveHeight = bmpHeight >> scale;
waveWidth = bmpWidth >> scale; waves = new short[waveWidth, waveHeight, ]; bmpBytes = new byte[bmpWidth * bmpHeight * ]; bmpBitmapData = bmpImage.LockBits(new Rectangle(, , bmpWidth, bmpHeight),
System.Drawing.Imaging.ImageLockMode.ReadWrite,
System.Drawing.Imaging.PixelFormat.Format32bppArgb);
Marshal.Copy(bmpBitmapData.Scan0, bmpBytes, , bmpWidth * bmpHeight * );
}
} private int bmpHeight { get; set; }
private int bmpWidth { get; set; } private int waveWidth { get; set; }
private int waveHeight { get; set; } private short[, ,] waves { get; set; }
private byte[] bmpBytes { get; set; } private System.Drawing.Imaging.BitmapData bmpBitmapData { get; set; }
private bool IsWaves = false; private int activedBuf = ;
#endregion void WavesControl_MouseMove(object sender, MouseEventArgs e)
{
int realX = (int)((e.X / (double)this.ClientRectangle.Width) * waveWidth);
int realY = (int)((e.Y / (double)this.ClientRectangle.Height) * waveHeight);
this.PutDrop(realX, realY, );
}
/// <summary>
/// This function is used to start a wave by simulating a round drop
/// </summary>
/// <param name="realX">x position of the drop</param>
/// <param name="realY">y position of the drop</param>
/// <param name="height">Height position of the drop</param>
private void PutDrop(int realX, int realY, int height)
{
this.IsWaves = true;
int radius =;
double dist;
for (int i = -radius; i <= radius; i++)
{
for (int j = -radius; j <= radius; j++)
{
if (((realX + i >= ) && (realX + i < waveWidth - )) && ((realY + j >= ) && (realY + j < waveHeight - )))
{
dist = Math.Sqrt(i * i + j * j);
if (dist < radius)
waves[realX + i, realY + j, activedBuf] = (short)(Math.Cos(dist * Math.PI / radius) * height);
}
}
}
}
/// <summary>
/// Paint handler
/// Calculates the final effect-image out of
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void WavesControl_Paint(object sender, PaintEventArgs e)
{
if (bmpImage == null) return;
using (Bitmap tmpBmp = bmpImage.Clone() as Bitmap)
{ int xOffset, yOffset;
byte alpha;
if (IsWaves)
{
BitmapData tmpBitmapData = tmpBmp.LockBits(new Rectangle(, , bmpWidth, bmpHeight),
ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
byte[] tmpBytes = new byte[bmpWidth * bmpHeight * ];
Marshal.Copy(tmpBitmapData.Scan0, tmpBytes, , bmpWidth * bmpHeight * );
for (int x = ; x < bmpWidth - ; x++)
{
for (int y = ; y < bmpHeight - ; y++)
{
int waveX = (int)x >> scale;
int waveY = (int)y >> scale;
///check bounds
waveX = waveX <= ? : waveX;
waveY = waveY <= ? : waveY;
waveX = waveX >= waveWidth - ? waveWidth - : waveX;
waveY = waveY >= waveHeight - ? waveHeight - : waveY;
///this gives us the effect of water breaking the light
xOffset = (waves[waveX - , waveY, activedBuf] - waves[waveX + , waveY, activedBuf]) >> ;
yOffset = (waves[waveX, waveY - , activedBuf] - waves[waveX, waveY + , activedBuf]) >> ; if ((xOffset != ) || (yOffset != ))
{
///check bounds
if (x + xOffset >= bmpWidth - )
xOffset = bmpWidth - x - ;
if (y + yOffset >= bmpHeight - )
yOffset = bmpHeight - y - ;
if (x + xOffset < ) xOffset = -x;
if (y + yOffset < ) yOffset = -y;
///generate alpha
alpha = (byte)( - xOffset);
if (alpha < ) alpha = ;
if (alpha > ) alpha = ;
///set colors
tmpBytes[ * (x + y * bmpWidth)] = bmpBytes[ * (x + xOffset + (y + yOffset) * bmpWidth)];
tmpBytes[ * (x + y * bmpWidth) + ] = bmpBytes[ * (x + xOffset + (y + yOffset) * bmpWidth) + ];
tmpBytes[ * (x + y * bmpWidth) + ] = bmpBytes[ * (x + xOffset + (y + yOffset) * bmpWidth) + ];
tmpBytes[ * (x + y * bmpWidth) + ] = alpha;
}
}
}
///copy data back
Marshal.Copy(tmpBytes, , tmpBitmapData.Scan0, bmpWidth * bmpHeight * );
tmpBmp.UnlockBits(tmpBitmapData);
}
e.Graphics.DrawImage(tmpBmp, , , this.ClientRectangle.Width, this.ClientRectangle.Height);
}
} /// <summary>
/// This is the method that actually does move the waves around and simulates the
/// behaviour of water.
/// </summary>
private void Waves()
{
int newBuf = this.activedBuf == ? : ;
bool wavesFound = false;
for (int x = ; x < waveWidth - ; x++)
{
for (int y = ; y < waveHeight - ; y++)
{
waves[x, y, newBuf] = (short)(((
waves[x - , y - , activedBuf] +
waves[x - , y, activedBuf] +
waves[x - , y + , activedBuf] +
waves[x, y - , activedBuf] +
waves[x, y + , activedBuf] +
waves[x + , y - , activedBuf] +
waves[x + , y, activedBuf] +
waves[x + , y + , activedBuf]) >> ) - waves[x, y, newBuf]);
///damping
if (waves[x, y, newBuf] != )
{
waves[x, y, newBuf] -= (short)(waves[x, y, newBuf] >> );
wavesFound = true;
}
}
}
IsWaves = wavesFound;
activedBuf = newBuf;
} void Effect_Tick(object sender, EventArgs e)
{
if (IsWaves)
{
Invalidate();
Waves();
}
}
//protected override void OnPaint(PaintEventArgs pe)
//{
// base.OnPaint(pe);
//}
}
}

参考资料[含程序,源码,算法]

http://pan.baidu.com/s/1dD3s2xN

http://www.cnblogs.com/worldreason/archive/2008/05/09/1189648.html

http://www.codeproject.com/Articles/1073/Interactive-water-effect

C# Winform 水波纹效果的更多相关文章

  1. jquery ripples水波纹效果( 涟漪效果)

    这个效果是我从bootstrap-material-design上面分离下来的,bootstrap-material-design的一些组件样式我不太不喜欢,但是非常喜欢这个水波纹效果,所以就有了这篇 ...

  2. 如何使用 HTML5 Canvas 制作水波纹效果

    今天,我们继续分享 JavaScript 实现的效果例子,这篇文章会介绍使用 JavaScript 实现水波纹效果.水波效果以图片为背景,点击图片任意位置都会触发.有时候,我们使用普通的 Javasc ...

  3. 兼容Android的水波纹效果

    Android的水波纹效果只有高版本才有,我们希望自己的应用在低版本用低版本的阴影,高版本用水波纹,这怎么做呢?其实,只要分drawable和drawablev21两个文件夹就好了. 普通情况下的se ...

  4. android自定义控件(4)-自定义水波纹效果

    一.实现单击出现水波纹单圈效果: 照例来说,还是一个自定义控件,观察这个效果,发现应该需要重写onTouchEvent和onDraw方法,通过在onTouchEvent中获取触摸的坐标,然后以这个坐标 ...

  5. 自定义view实现水波纹效果

    水波纹效果: 1.标准正余弦水波纹: 2.非标准圆形液柱水波纹: 虽说都是水波纹,但两者在实现上差异是比较大的,一个通过正余弦函数模拟水波纹效果,另外一个会运用到图像的混合模式(PorterDuffX ...

  6. Android 颜色渲染(七) RadialGradient 环形渲染实现水波纹效果

    利用环形渲染我们可以做到什么? 其实很多都是非常常见的,比如上一篇实现的帮帮糖效果, 彩色的热气球,比如这里要讲到的水波纹效果,或者也可以理解为扩散色渲染效果 首先看一下效果图: 轻触屏幕,即可看到对 ...

  7. 聊聊Android5.0中的水波纹效果

    水波纹效果已经不是什么稀罕的东西了,用过5.0新控件的小伙伴都知道这个效果,可是如果使用一个TextView或者Button或者其它普通控件的话,你是否知道如何给它设置水波纹效果呢?OK,我们今天就来 ...

  8. android 点击水波纹效果

    这里是重点,<ripple>是API21才有的新Tag,正是实现水波纹效果的; 其中<ripple android:color="#FF21272B" .... ...

  9. Android 自定义view实现水波纹效果

    http://blog.csdn.net/tianjian4592/article/details/44222565 在实际的开发中,很多时候还会遇到相对比较复杂的需求,比如产品妹纸或UI妹纸在哪看了 ...

随机推荐

  1. P1010 幂次方

    这么难得题,居然普及-?做了好久 #include <bits/stdc++.h> using namespace std; int fact[21]; void solve(int n) ...

  2. jquery的$.ajax async使用详解

      async在jquery ajax中是一个同步参数了,我们下面来给大家介绍在jquery ajax中使用async时碰到的一些问题与方法介绍,希望例子能给各位同学带来一些帮助哦.   async默 ...

  3. php数据访问:pdo用法、事物回滚功能和放sql注入功能

    PDO:    一.含义:        数据访问抽象层    二.作用        通过PDO能够访问其它的数据库    三. 用法:        1.造对象            ① $pdo ...

  4. IOS 手势事件的冲突

    关于手操作需要强调几点: UIImageView默认是不支持交互的,也就是userInteractionEnabled=NO ,因此要接收触摸事件(手势识别),必须设置userInteractionE ...

  5. C# winForm程序开机启动和托盘显示 (转http://blog.csdn.net/xinyue3054/article/details/6599508)

    这段时间一直进行cs项目,故整理下开机自动运行.托盘.显示.隐藏. (1).在窗口上点击关闭按钮或者最小化时将托盘显示: (2).双击托盘图标显示窗口: (3).右键点击托盘图标提供三个菜单选项,“退 ...

  6. Windows-005-显示隐藏文件

    此文主要讲述如何设置 Win7 系统显示隐藏的文件.文件夹和驱动器,敬请亲们参阅.若有不足之处,敬请大神指正,不胜感激!详情如下: Win7 系统安装完成后,默认是不显示隐藏的文件.文件夹和驱动器的( ...

  7. 如何安装sass

    1.安装ruby 2. 运行ruby时输入 gem install 及sass安装文件路径. sass安装文件见文件.

  8. background-size的cover和content的用法

    background-size:cover; 表示背景图拉伸布满,如果在手机上做的话,背景图片会拉大,失真.这样做不妥 background-size:content; 表示背景图片在内容区域正常显示 ...

  9. Linux信号处理

    给进程设置僵尸状态的目的是维护子进程的信息,以便父进程在以后某个时间获取.这些信息包括子进程的进程ID.终止状态以及资源利用信息(CPU时间,内存使用量等等).如果一个进程终止,而该进程有子进程处于僵 ...

  10. Sersync实现触发式文件同步 替代inotify和rsync

    Sersync实现触发式文件同步 替代inotify和rsync Pyinotify是一个Python模块,用来监测文件系统的变化. Pyinotify依赖于Linux内核的功能—inotify(内核 ...