1 New WPF Project
Link Project add:
System.Drawing
System.Windows.Forms
WindowsFormsIntegration
MainWindow.xaml:
<Window x:Class="WpfwaterEffectTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:wf="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"
xmlns:local="clr-namespace:WpfwaterEffectTest"
mc:Ignorable="d"
Title="MainWindow" Height="768" Width="1024" ResizeMode="NoResize" WindowStyle="None" WindowStartupLocation="CenterScreen">
<Canvas Name="mainCanv">
</Canvas>
</Window>
MainWindow.xaml.cs:
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Forms;
using System.Windows.Forms.Integration;
using System.Windows.Threading;
namespace WpfwaterEffectTest
{
public partial class MainWindow : Window
{
private Bitmap _bmp;
private short[,,] _waves;
private int _waveWidth;
private int _waveHeight;
private int _activeBuffer = 0;
private bool _weHaveWaves;
private int _bmpHeight, _bmpWidth;
private byte[] _bmpBytes;
private BitmapData _bmpBitmapData;
private int _scale;
System.Windows.Forms.PictureBox pbViewport = null;
DispatcherTimer waterTime = new DispatcherTimer(DispatcherPriority.Render);
public MainWindow()
{
InitializeComponent();
pbViewport = new PictureBox();
this.pbViewport.Image = System.Drawing.Image.FromFile("About2.jpg");
this.pbViewport.Top = 0;
this.pbViewport.Left = 0;
this.pbViewport.Height = 360;
this.pbViewport.Width = 203;
this.pbViewport.SizeMode = PictureBoxSizeMode.AutoSize;
this.pbViewport.Paint += new PaintEventHandler(this.WaterEffectControl_Paint);
this.pbViewport.MouseMove += new System.Windows.Forms.MouseEventHandler(this.WaterEffectControl_MouseMove);
waterTime.Tick += new EventHandler(effectTimer_Tick);
WindowsFormsHost wfh = new WindowsFormsHost();
wfh.Child = pbViewport;
wfh.Width = 203;
wfh.Height = 360;
wfh.Opacity = 0.9;
mainCanv.Children.Add(wfh);
Canvas.SetZIndex(wfh, 1);
this.Width = this.pbViewport.Width;
this.Height = this.pbViewport.Height;
this.ImageBitmapNew = (Bitmap)(this.pbViewport.Image);
waterTime.Interval = TimeSpan.FromMilliseconds(50);
waterTime.Start();
}
private void effectTimer_Tick(object sender, System.EventArgs e)
{
if (_weHaveWaves)
{
this.pbViewport.Invalidate();
ProcessWaves();
}
}
private void ProcessWaves()
{
int newBuffer = (_activeBuffer == 0) ? 1 : 0;
bool wavesFound = false;
for (int x = 1; x < _waveWidth - 1; x++)
{
for (int y = 1; y < _waveHeight - 1; y++)
{
_waves[x, y, newBuffer] = (short)(
((_waves[x - 1, y - 1, _activeBuffer] +
_waves[x, y - 1, _activeBuffer] +
_waves[x + 1, y - 1, _activeBuffer] +
_waves[x - 1, y, _activeBuffer] +
_waves[x + 1, y, _activeBuffer] +
_waves[x - 1, y + 1, _activeBuffer] +
_waves[x, y + 1, _activeBuffer] +
_waves[x + 1, y + 1, _activeBuffer]) >> 2) - _waves[x, y, newBuffer]);
if (_waves[x, y, newBuffer] != 0)
{
_waves[x, y, newBuffer] -= (short)(_waves[x, y, newBuffer] >> 4);
wavesFound = true;
}
}
}
_weHaveWaves = wavesFound;
_activeBuffer = newBuffer;
}
private void PutDrop(int x, int y, short height)
{
_weHaveWaves = true;
int radius = 20;
double dist;
for (int i = -radius; i <= radius; i++)
{
for (int j = -radius; j <= radius; j++)
{
if (((x + i >= 0) && (x + i < _waveWidth - 1)) && ((y + j >= 0) && (y + j < _waveHeight - 1)))
{
dist = Math.Sqrt(i * i + j * j);
if (dist < radius)
_waves[x + i, y + j, _activeBuffer] = (short)(Math.Cos(dist * Math.PI / radius) * height);
}
}
}
}
private void WaterEffectControl_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
{
if (e.Button == MouseButtons.Left && _bmp != null)
{
int realX = (int)((e.X / (double)this.pbViewport.ClientRectangle.Width) * _waveWidth);
int realY = (int)((e.Y / (double)this.pbViewport.ClientRectangle.Height) * _waveHeight);
PutDrop(realX, realY, 200);
}
}
#region Properties
public Bitmap ImageBitmapNew
{
get { return _bmp; }
set
{
if (_bmp != null)
{
_bmp.Dispose();
}
_bmp = value;
if (value != null)
{
_bmpHeight = _bmp.Height;
_bmpWidth = _bmp.Width;
_waveWidth = _bmpWidth >> _scale;
_waveHeight = _bmpHeight >> _scale;
_waves = new Int16[_waveWidth, _waveHeight, 2];
_bmpBytes = new Byte[_bmpWidth * _bmpHeight * 4];
_bmpBitmapData = _bmp.LockBits(new Rectangle(0, 0, _bmpWidth, _bmpHeight), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
Marshal.Copy(_bmpBitmapData.Scan0, _bmpBytes, 0, _bmpWidth * _bmpHeight * 4);
_bmp.UnlockBits(_bmpBitmapData);
}
}
}
public int Scale
{
get { return _scale; }
set { _scale = value; }
}
#endregion Properties
public void WaterEffectControl_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
if (_bmp != null)
{
using (Bitmap tmp = (Bitmap)_bmp.Clone())
{
int xOffset, yOffset;
byte alpha;
if (_weHaveWaves)
{
BitmapData tmpData = tmp.LockBits(new Rectangle(0, 0, _bmpWidth, _bmpHeight), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
byte[] tmpBytes = new Byte[_bmpWidth * _bmpHeight * 4];
Marshal.Copy(tmpData.Scan0, tmpBytes, 0, _bmpWidth * _bmpHeight * 4);
for (int x = 1; x < _bmpWidth - 1; x++)
{
for (int y = 1; y < _bmpHeight - 1; y++)
{
int waveX = (int)x >> _scale;
int waveY = (int)y >> _scale;
if (waveX <= 0) waveX = 1;
if (waveY <= 0) waveY = 1;
if (waveX >= _waveWidth - 1) waveX = _waveWidth - 2;
if (waveY >= _waveHeight - 1) waveY = _waveHeight - 2;
xOffset = (_waves[waveX - 1, waveY, _activeBuffer] - _waves[waveX + 1, waveY, _activeBuffer]) >> 3;
yOffset = (_waves[waveX, waveY - 1, _activeBuffer] - _waves[waveX, waveY + 1, _activeBuffer]) >> 3;
if ((xOffset != 0) || (yOffset != 0))
{
if (x + xOffset >= _bmpWidth - 1) xOffset = _bmpWidth - x - 1;
if (y + yOffset >= _bmpHeight - 1) yOffset = _bmpHeight - y - 1;
if (x + xOffset < 0) xOffset = -x;
if (y + yOffset < 0) yOffset = -y;
alpha = (byte)(200 - xOffset);
if (alpha < 0) alpha = 0;
if (alpha > 255) alpha = 254;
tmpBytes[4 * (x + y * _bmpWidth)] = _bmpBytes[4 * (x + xOffset + (y + yOffset) * _bmpWidth)];
tmpBytes[4 * (x + y * _bmpWidth) + 1] = _bmpBytes[4 * (x + xOffset + (y + yOffset) * _bmpWidth) + 1];
tmpBytes[4 * (x + y * _bmpWidth) + 2] = _bmpBytes[4 * (x + xOffset + (y + yOffset) * _bmpWidth) + 2];
tmpBytes[4 * (x + y * _bmpWidth) + 3] = alpha;
}
}
}
Marshal.Copy(tmpBytes, 0, tmpData.Scan0, _bmpWidth * _bmpHeight * 4);
tmp.UnlockBits(tmpData);
}
e.Graphics.DrawImage(tmp, 0, 0, this.pbViewport.ClientRectangle.Width, this.pbViewport.ClientRectangle.Height);
}
}
}
}
}
pbViewport.Height = 360 and pbViewport.Width = 203 equal to the size of the loaded image
Insert Image File in App Direct("About2.jpg") and include in the project
The code is not mine, limited from UserControl "WaterEffectPictureBox" WinForm