//添加自定义控件
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妹纸在哪看了 ...
随机推荐
-
Tomcat中解决sql server连接失败--- java.lang.ClassNotFoundException: com.microsoft.jdbc.sqlserver.SQLServerDriver
php连接mysql数据库很容易,他俩真是黄金搭档.最近转战java连接微软sqlServer,步骤稍微复杂一点,但也不是太难,中途遇到了一点小问题,最后在csdn论坛里找到了答案http://bbs ...
-
hadoop-1.2.1伪分布模式配置
1.hadoop-env.sh 修改 export JAVA_HOME=/Library/Java/Home #增加 JAVA_HOME 2.masters localhost 3.slaves lo ...
-
第三方框架之SDWebImage
1. 下载SDWebImage,导入工程.github托管地址https://github.com/rs/SDWebImage 2. 在需要的地方导入头文件#import "UIImageV ...
-
将nginx配置为服务,php-fpm配置说明
编写shell脚本 vi /etc/init.d/nginx #!/bin/bash # # Startup script for the PHP-FPM server. # # chkconfig: ...
-
关于一次Weblogic活动线程的问题处理
Weblogic控制台监控发现 环境>>服务器>>你的服务器>>监控>>线程 中活动执行线程竟然是2000多.同一套系统在另一套平台上,并且访问的人不少 ...
-
hpuoj 1706: 牛B【正向拓扑】【建图】
1706: 牛B 时间限制: 1 Sec 内存限制: 128 MB提交: 22 解决: 6[提交][状态][讨论版] 题目描述 一群来自日本*带着AK47,火箭弹,开着坦克,带着飞机,强行洗 ...
-
简述tcp协议对http性能的影响及优化
当网站服务器并发连接达到一定程度时,你可能需要考虑服务器系统中tcp协议设置对http服务器的影响. tcp相关延时主要包括: 1.tcp连接时建立握手: 2.tcp慢启动拥塞控制: 3.数据聚集的N ...
-
Swift的基础,操作符,字符串和集合类型
这篇文章主要讲解苹果Swift官方指南的第二章前四节的要点内容,如果想看完整的英文文档可以去苹果开发者页面下载. Basic 声明常量let 声明变量var 注释依旧使用"//" ...
-
Vuex 最简单的数量增减实例
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式.它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化.Vuex 也集成到 Vue 的官方调试工具 ...
-
【转】Python的下划线
原文: 1. Python中的下划线(译文) 2. [转]关于python中带下划线的变量和函数的意义 总结: 1. 单下划线开头.保护变量,不可被其他包导入使用,除非在__all__声明可以显示引用 ...