C# Winform 水波纹效果

//添加自定义控件
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 水波纹效果的更多相关文章
- jquery ripples水波纹效果( 涟漪效果)
这个效果是我从bootstrap-material-design上面分离下来的,bootstrap-material-design的一些组件样式我不太不喜欢,但是非常喜欢这个水波纹效果,所以就有了这篇 ...
- 如何使用 HTML5 Canvas 制作水波纹效果
今天,我们继续分享 JavaScript 实现的效果例子,这篇文章会介绍使用 JavaScript 实现水波纹效果.水波效果以图片为背景,点击图片任意位置都会触发.有时候,我们使用普通的 Javasc ...
- 兼容Android的水波纹效果
Android的水波纹效果只有高版本才有,我们希望自己的应用在低版本用低版本的阴影,高版本用水波纹,这怎么做呢?其实,只要分drawable和drawablev21两个文件夹就好了. 普通情况下的se ...
- android自定义控件(4)-自定义水波纹效果
一.实现单击出现水波纹单圈效果: 照例来说,还是一个自定义控件,观察这个效果,发现应该需要重写onTouchEvent和onDraw方法,通过在onTouchEvent中获取触摸的坐标,然后以这个坐标 ...
- 自定义view实现水波纹效果
水波纹效果: 1.标准正余弦水波纹: 2.非标准圆形液柱水波纹: 虽说都是水波纹,但两者在实现上差异是比较大的,一个通过正余弦函数模拟水波纹效果,另外一个会运用到图像的混合模式(PorterDuffX ...
- Android 颜色渲染(七) RadialGradient 环形渲染实现水波纹效果
利用环形渲染我们可以做到什么? 其实很多都是非常常见的,比如上一篇实现的帮帮糖效果, 彩色的热气球,比如这里要讲到的水波纹效果,或者也可以理解为扩散色渲染效果 首先看一下效果图: 轻触屏幕,即可看到对 ...
- 聊聊Android5.0中的水波纹效果
水波纹效果已经不是什么稀罕的东西了,用过5.0新控件的小伙伴都知道这个效果,可是如果使用一个TextView或者Button或者其它普通控件的话,你是否知道如何给它设置水波纹效果呢?OK,我们今天就来 ...
- android 点击水波纹效果
这里是重点,<ripple>是API21才有的新Tag,正是实现水波纹效果的; 其中<ripple android:color="#FF21272B" .... ...
- Android 自定义view实现水波纹效果
http://blog.csdn.net/tianjian4592/article/details/44222565 在实际的开发中,很多时候还会遇到相对比较复杂的需求,比如产品妹纸或UI妹纸在哪看了 ...
随机推荐
- 【转】配置 VS 2015 开发跨平台手机应用
为了使用 VS 2015 开发跨平台手机应用,VS 2015 装了很多次,遇到了很多坑,才终于弄明白怎样配置才能正常使用C#开发手机应用,现把步骤分享给大家,以免大家少走弯路. 运行环境: Windo ...
- Java中instanceof用法
java 中的instanceof 运算符是用来在运行时指出对象是否是特定类的一个实例.instanceof通过返回一个布尔值来指出,这个对象是否是这个特定类或者是它的子类的一个实例. 用法:resu ...
- vim编辑器配置修改
刚上手的vim,黑底白字,看起来笨死了,于是一顿狂找,终于找到了配置方法. 配置当然要去etc目录下. cd /etc/vim ls -l //找到vim ...
- 【C++】运算符重载
运算符重载,主要是简化类类型运算,能够让我们对类对象直接用运算符进行运算.基本语法: 类型 operator 运算符(参数列表){ ... } Complex operator+(Complex va ...
- Stakeholder Risk Management
In this article we'll address the people swirling around your project: stakeholders. You'll find som ...
- <dependency>spring-webmvc</dependency>
Spring 4.2.0.RELEASE版本: <dependency> <groupId>org.springframework</groupId> <ar ...
- 8款实用Sublime text 3插件推荐
Sublime Text作为一个尽为人知的代码编辑器,其优点不用赘述.界面整洁美观.文本功能强大,且运行速度极快,非常适合编写代码,写文章做笔记.Sublime Text还支持Mac.Windows和 ...
- [BS-09] UITabBarController简单介绍
iOS开发UI篇—UITabBarController简单介绍 一.简单介绍 UITabBarController和UINavigationController类似,UITabBarControlle ...
- ASP: VS2015 + IIS Express 10 学习笔记
首先搞清楚 ASP 与 ASP.NET 的区别(.asp与.aspx). https://msdn.microsoft.com/en-us/library/ms973813.aspx 环境配置: ht ...
- 关于StdAfx.h和StdAfx.cpp
http://www.cplusplus.com/articles/2z86b7Xj/ https://msdn.microsoft.com/en-us/library/h552b3ca.aspx h ...