You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

467 lines
16 KiB

#if NETFX || NETCORE
using System;
using System.Drawing;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Drawing.Drawing2D;
namespace Apewer.Surface
{
internal class BlockShadow : BaseForm
{
#region definition
private BlockForm _parent;
#endregion
#region this
public void Constructor()
{
this.Optimize();
_parent.TopMost = TopMost = _parent.TopMost;
_parent.BringToFront();
this.Location = new Point(_parent.Location.X - 100, _parent.Location.Y - 100);
this.Width = _parent.Width + 200;
this.Height = _parent.Height + 200;
this.TopMost = _parent.TopMost;
this.ShowInTaskbar = false;
this.FormBorderStyle = FormBorderStyle.None;
this.Icon = _parent.Icon;
this.ShowIcon = _parent.ShowIcon;
this.Text = _parent.Text;
FormsUtility.UpdateShadow(this, ShadowImage(Width, Height));
FormsUtility.MousePenetration(this);
this.Paint += Event_This_Paint;
_parent.LocationChanged += new EventHandler(Main_LocationChanged);
_parent.SizeChanged += new EventHandler(Main_SizeChanged);
_parent.VisibleChanged += new EventHandler(Main_VisibleChanged);
_parent.ResizeBegin += Event_Form_ResizeBegin;
_parent.ResizeEnd += Event_Form_Resizeend;
}
public BlockShadow(BlockForm argGraceForm)
{
_parent = argGraceForm;
Constructor();
}
#endregion
#region base
protected override CreateParams CreateParams
{
get
{
CreateParams cParms = base.CreateParams;
cParms.ExStyle |= 0x00080000; // WS_EX_LAYERED
return cParms;
}
}
#endregion
#region event
private void Event_This_Paint(object sender, PaintEventArgs e)
{
}
private void Event_Form_Resizeend(object sender, EventArgs e)
{
//this.Visible = true;
}
private void Event_Form_ResizeBegin(object sender, EventArgs e)
{
//this.Visible = false;
}
private void Main_LocationChanged(object sender, EventArgs e)
{
Location = new Point(_parent.Left - 100, _parent.Top - 100);
}
private void Main_SizeChanged(object sender, EventArgs e)
{
this.Size = new Size(_parent.Width + 200, _parent.Height + 200);
FormsUtility.UpdateShadow(this, ShadowImage(Width, Height));
}
private void Main_VisibleChanged(object sender, EventArgs e)
{
this.Visible = _parent.Visible;
}
#endregion
#region shadow
private Bitmap ShadowImage(int argWidth, int argHeight, bool argFocus = true)
{
return ShadowImage_1(argWidth, argHeight, argFocus);
}
private Bitmap ShadowImage_2(int argWidth, int argHeight, bool argFocus = true)
{
var vbitmap = new Bitmap(argWidth, argHeight, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
var vg = Graphics.FromImage(vbitmap);
vg.Clear(Color.FromArgb(0, 0, 0, 0));
vg.SmoothingMode = SmoothingMode.HighQuality;
vg.CompositingMode = CompositingMode.SourceCopy;
int vwidth = _parent.Width + 200;
int vheight = _parent.Height + 200;
if ((vwidth > Screen.PrimaryScreen.Bounds.Width) || (vheight > Screen.PrimaryScreen.Bounds.Height))
{
//using (var vp = new Pen(bordercolor)) vg.DrawRectangle(vp, 100, 100, Width - 200, Height - 200);
vg.Dispose();
return vbitmap;
}
for (int i = 0; i < 100; i++)
{
var vrect = new Rectangle(i, i, vwidth - (i * 2), vheight - (i * 2));
var vpath = FormsUtility.CreatePath(vrect, 99 - i);
var valpha = GetAlpha(99 - i);
var vpen = new Pen(Color.FromArgb(valpha, 0, 0, 0));
// var vbrush = new SolidBrush(Color.FromArgb(valpha, 0, 0, 0));
vg.DrawRectangle(vpen, vrect);
//vg.DrawPath(vpen, vpath);
//vg.FillPath(vbrush, vpath);
//vbrush.Dispose();
vpen.Dispose();
vpath.Dispose();
}
//for (int i = 0; i < 100; i++)
//{
// var vrect = new Rectangle(i, i, 100 - i, 100 - i);
// var valpha = getalpha(99 - i);
// using (var vbrush = new SolidBrush(Color.FromArgb(valpha, 0, 0, 0)))
// {
// vg.FillPie(vbrush, vrect, 180, 90);
// vg.FillPie(vbrush, new Rectangle(0,0,100,100));
// }
//}
//using (var vbrush = new SolidBrush(Color.Transparent))
//{
// vg.FillRectangle(vbrush, new Rectangle(100, 100, vwidth - 200, vheight - 200));
//}
//using (var vbrush = new SolidBrush(Color.Transparent))
//{
// vg.FillRectangle(vbrush, new Rectangle(100, 100, vwidth - 200, vheight - 200));
//}
vg.Dispose();
return vbitmap;
}
private Bitmap ShadowImage_1(int argWidth, int argHeight, bool argFocus = true)
{
var vbitmap = new Bitmap(argWidth, argHeight, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
var vg = Graphics.FromImage(vbitmap);
vg.Clear(Color.FromArgb(0, 0, 0, 0));
int vwidth = _parent.Width + 200;
int vheight = _parent.Height + 200;
if ((vwidth > Screen.PrimaryScreen.Bounds.Width) || (vheight > Screen.PrimaryScreen.Bounds.Height))
{
//using (var vp = new Pen(bordercolor)) vg.DrawRectangle(vp, 100, 100, Width - 200, Height - 200);
vg.Dispose();
return vbitmap;
}
// 边角距离补偿
int vcorneroffset = 2;
// 上
for (int y = 0; y <= 99; y++)
{
double vl = 100 - y;
using (var vp = new Pen(Color.FromArgb(GetAlpha(vl), 0, 0, 0))) vg.DrawLine(vp, 100, y, argWidth - 101, y);
}
// 下
for (int y = argHeight - 100; y <= argHeight - 2; y++)
{
double vl = y - (argHeight - 101);
using (var vp = new Pen(Color.FromArgb(GetAlpha(vl), 0, 0, 0))) vg.DrawLine(vp, 100, y, argWidth - 101, y);
}
// 左
for (int x = 0; x <= 99; x++)
{
double vl = 100 - x;
using (var vp = new Pen(Color.FromArgb(GetAlpha(vl), 0, 0, 0))) vg.DrawLine(vp, x, 100, x, argHeight - 101);
}
// 右
for (int x = argWidth - 100; x <= argWidth - 2; x++)
{
double vl = x - (argWidth - 101);
using (var vp = new Pen(Color.FromArgb(GetAlpha(vl), 0, 0, 0))) vg.DrawLine(vp, x, 100, x, argHeight - 101);
}
// 左上
for (int x = 0; x <= 99; x++)
{
for (int y = 0; y <= 99; y++)
{
double vx = 100 - x; double vy = 100 - y;
double vl = Math.Sqrt((vx * vx) + (vy * vy)) + vcorneroffset;
vbitmap.SetPixel(x, y, Color.FromArgb(GetAlpha(vl), 0, 0, 0));
}
}
// 右上
for (int x = argWidth - 100; x <= argWidth - 1; x++)
{
for (int y = 0; y <= 99; y++)
{
double vx = 100 - (argWidth - x); double vy = 100 - y;
double vl = Math.Sqrt((vx * vx) + (vy * vy)) + vcorneroffset;
vbitmap.SetPixel(x, y, Color.FromArgb(GetAlpha(vl), 0, 0, 0));
}
}
// 左下
for (int x = 0; x <= 99; x++)
{
for (int y = argHeight - 100; y <= argHeight - 1; y++)
{
double vx = 100 - x; double vy = 100 - (argHeight - y);
double vl = Math.Sqrt((vx * vx) + (vy * vy)) + vcorneroffset;
vbitmap.SetPixel(x, y, Color.FromArgb(GetAlpha(vl), 0, 0, 0));
}
}
// 右下
for (int x = argWidth - 100; x <= argWidth - 1; x++)
{
for (int y = argHeight - 100; y <= argHeight - 1; y++)
{
double vx = 100 - (argWidth - x); double vy = 100 - (argHeight - y);
double vl = Math.Sqrt((vx * vx) + (vy * vy)) + vcorneroffset;
vbitmap.SetPixel(x, y, Color.FromArgb(GetAlpha(vl), 0, 0, 0));
}
}
vg.Dispose();
return vbitmap;
}
private static int GetAlpha(double argLength, bool argFocus = true)
{
// 返回值。
double valpha = 0;
// 参数。
double vl = argLength;
if (vl < 0) vl = 0;
if (vl > 100) vl = 100;
// 常数。
double alphamax = 0; // 0 <= x <=255
// 过程变量。
double x = 0, y = 0, xmax = 0, ymax = 0, lmax = 0, tanmax = 0, ratio = 0; ;
// 选择方法。
int vmethod = 1; // flat from 4
switch (vmethod)
{
case 0: // 穷举
ratio = 0.5;
int vlint = (int)argLength;
switch (vlint)
{
#region switch block
case 0: return 40;
case 1: return 39;
case 2: return 38;
case 3: return 37;
case 4: return 36;
case 5: return 36;
case 6: return 35;
case 7: return 34;
case 8: return 33;
case 9: return 33;
case 10: return 32;
case 11: return 31;
case 12: return 30;
case 13: return 30;
case 14: return 29;
case 15: return 28;
case 16: return 28;
case 17: return 27;
case 18: return 26;
case 19: return 26;
case 20: return 25;
case 21: return 24;
case 22: return 24;
case 23: return 23;
case 24: return 23;
case 25: return 22;
case 26: return 21;
case 27: return 21;
case 28: return 20;
case 29: return 20;
case 30: return 19;
case 31: return 19;
case 32: return 18;
case 33: return 17;
case 34: return 17;
case 35: return 16;
case 36: return 16;
case 37: return 15;
case 38: return 15;
case 39: return 14;
case 40: return 14;
case 41: return 13;
case 42: return 13;
case 43: return 12;
case 44: return 12;
case 45: return 12;
case 46: return 11;
case 47: return 11;
case 48: return 10;
case 49: return 10;
case 50: return 10;
case 51: return 9;
case 52: return 9;
case 53: return 8;
case 54: return 8;
case 55: return 8;
case 56: return 7;
case 57: return 7;
case 58: return 7;
case 59: return 6;
case 60: return 6;
case 61: return 6;
case 62: return 5;
case 63: return 5;
case 64: return 5;
case 65: return 4;
case 66: return 4;
case 67: return 4;
case 68: return 4;
case 69: return 3;
case 70: return 3;
case 71: return 3;
case 72: return 3;
case 73: return 2;
case 74: return 2;
case 75: return 2;
case 76: return 2;
case 77: return 2;
case 78: return 1;
case 79: return 1;
case 80: return 1;
case 81: return 1;
case 82: return 1;
case 83: return 1;
case 84: return 1;
case 85: return 0;
case 86: return 0;
case 87: return 0;
case 88: return 0;
case 89: return 0;
case 90: return 0;
case 91: return 0;
case 92: return 0;
case 93: return 0;
case 94: return 0;
case 95: return 0;
case 96: return 0;
case 97: return 0;
case 98: return 0;
case 99: return 0;
case 100: return 0;
#endregion
}
break;
case 1: // 正比例
ratio = 0.2;
valpha = (100 - vl) * ratio;
break;
case 2: // 正切函数
alphamax = 55;
tanmax = 0.45; // 0 < x < 0.5
valpha = (Math.Tan(Math.PI * tanmax * ((100 - vl) / 100)) / Math.Tan(Math.PI * tanmax)) * alphamax;
break;
case 3: // 正弦函数
lmax = 40;
if (vl <= lmax)
{
y = (lmax - vl) * (lmax - vl);
alphamax = 30;
xmax = Math.PI / 2;
x = ((lmax - vl) / lmax) * xmax;
if (x < 0) x = 0;
if (x > Math.PI / 2) x = Math.PI / 2;
valpha = (Math.Sin(Math.PI * 1.5 + x) + 1) * alphamax;
}
else valpha = 0;
break;
case 4: // 平方函数
lmax = 100;
if (vl <= lmax)
{
alphamax = 40;
y = (lmax - vl) * (lmax - vl);
valpha = (y / (lmax * lmax)) * alphamax;
}
else valpha = 0;
break;
case 5: // 幂函数
lmax = 40;
if (vl <= lmax)
{
alphamax = 1;
ratio = 1.1;
x = lmax - vl;
y = Math.Pow(ratio, x);
ymax = Math.Pow(ratio, lmax);
valpha = (y / ymax) * alphamax;
}
else valpha = 0;
break;
case 6:
if (vl <= 40) valpha = 40 - vl;
else valpha = 0;
break;
}
if (valpha < 0) valpha = 0; if (valpha > 255) valpha = 255;
return (int)valpha;
}
#endregion
}
}
#endif