2021-02-22 13:42:48 +00:00
|
|
|
|
/*
|
|
|
|
|
* 本代码受中华人民共和国著作权法保护,作者仅授权下载代码之人在学习和交流范围内
|
|
|
|
|
* 自由使用与修改代码;欲将代码用于商业用途的,请与作者联系。
|
|
|
|
|
* 使用本代码请保留此处信息。作者联系方式:ping3108@163.com, 欢迎进行技术交流
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
using System;
|
|
|
|
|
using System.Drawing;
|
|
|
|
|
using System.Drawing.Drawing2D;
|
|
|
|
|
using System.Windows.Forms;
|
|
|
|
|
|
|
|
|
|
using MGdu.WinFormUI.Win32;
|
|
|
|
|
using MGdu.WinFormUI.MyGraphics;
|
|
|
|
|
|
|
|
|
|
namespace MGdu.WinFormUI
|
|
|
|
|
{
|
|
|
|
|
internal partial class GMShadow : Form
|
|
|
|
|
{
|
|
|
|
|
private GMForm _owner;
|
|
|
|
|
private bool _timeToResizeOwner;
|
|
|
|
|
|
|
|
|
|
public GMShadow(GMForm owner)
|
|
|
|
|
{
|
|
|
|
|
_owner = owner;
|
|
|
|
|
_timeToResizeOwner = false;
|
|
|
|
|
InitializeComponent();
|
|
|
|
|
FormIni();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void BeginToResizeOwner()
|
|
|
|
|
{
|
|
|
|
|
_timeToResizeOwner = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void FormIni()
|
|
|
|
|
{
|
|
|
|
|
base.FormBorderStyle = FormBorderStyle.None;
|
|
|
|
|
base.WindowState = FormWindowState.Normal;
|
|
|
|
|
base.ShowInTaskbar = false;
|
|
|
|
|
SetStyle(
|
|
|
|
|
ControlStyles.UserPaint |
|
|
|
|
|
ControlStyles.AllPaintingInWmPaint |
|
|
|
|
|
ControlStyles.OptimizedDoubleBuffer |
|
|
|
|
|
ControlStyles.ResizeRedraw |
|
|
|
|
|
ControlStyles.DoubleBuffer, true);
|
|
|
|
|
UpdateStyles();
|
|
|
|
|
base.AutoScaleMode = AutoScaleMode.None;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected override CreateParams CreateParams
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
CreateParams cp = base.CreateParams;
|
|
|
|
|
cp.ExStyle |= (int)Win32.WinAPI.WindowStyleEx.WS_EX_LAYERED;
|
|
|
|
|
return cp;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void SetFormReion()
|
|
|
|
|
{
|
|
|
|
|
if (base.Region != null)
|
|
|
|
|
base.Region.Dispose();
|
|
|
|
|
|
|
|
|
|
using (GraphicsPath path = GraphicsPathHelper.CreateRoundedRect(
|
|
|
|
|
new Rectangle(Point.Empty, base.Size), 16, RoundStyle.All, false))
|
|
|
|
|
{
|
|
|
|
|
this.Region = new Region(path);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void SetOwnerSize()
|
|
|
|
|
{
|
|
|
|
|
var size = base.Size;
|
|
|
|
|
size.Width -= ShadowWidth * 2;
|
|
|
|
|
size.Height -= ShadowWidth * 2;
|
|
|
|
|
if (_owner.Size != size)
|
|
|
|
|
{
|
|
|
|
|
_owner.Size = size;
|
|
|
|
|
_owner.Update();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void SetOwnerLocation()
|
|
|
|
|
{
|
|
|
|
|
Point location = base.Location;
|
|
|
|
|
location.Offset(ShadowWidth, ShadowWidth);
|
|
|
|
|
if (_owner.Location != location)
|
|
|
|
|
{
|
|
|
|
|
_owner.Location = location;
|
|
|
|
|
_owner.Update();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#region properties from owner
|
|
|
|
|
|
|
|
|
|
private int ShadowWidth
|
|
|
|
|
{
|
2021-07-05 13:56:28 +00:00
|
|
|
|
get { return _owner.XTheme.ShadowWidth==0?1: _owner.XTheme.ShadowWidth; }
|
2021-02-22 13:42:48 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private bool UseShadowToResize
|
|
|
|
|
{
|
|
|
|
|
get { return _owner.XTheme.UseShadowToResize; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private Color ShadowColor
|
|
|
|
|
{
|
|
|
|
|
get { return _owner.XTheme.ShadowColor; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private int ShadowAValueDark
|
|
|
|
|
{
|
|
|
|
|
get { return _owner.XTheme.ShadowAValueDark; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private int ShadowAValueLight
|
|
|
|
|
{
|
|
|
|
|
get { return _owner.XTheme.ShadowAValueLight; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region resize rect region
|
|
|
|
|
|
|
|
|
|
private Rectangle TopLeftRect
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
return new Rectangle(0, 0, ShadowWidth, ShadowWidth);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private Rectangle TopRect
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
return new Rectangle(
|
|
|
|
|
ShadowWidth,
|
|
|
|
|
0,
|
|
|
|
|
this.Size.Width - ShadowWidth * 2,
|
|
|
|
|
ShadowWidth);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private Rectangle TopRightRect
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
return new Rectangle(
|
|
|
|
|
this.Size.Width - ShadowWidth,
|
|
|
|
|
0,
|
|
|
|
|
ShadowWidth,
|
|
|
|
|
ShadowWidth);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private Rectangle LeftRect
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
return new Rectangle(
|
|
|
|
|
0,
|
|
|
|
|
ShadowWidth,
|
|
|
|
|
ShadowWidth,
|
|
|
|
|
this.Size.Height - ShadowWidth * 2);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private Rectangle RightRect
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
return new Rectangle(
|
|
|
|
|
this.Size.Width - ShadowWidth,
|
|
|
|
|
ShadowWidth,
|
|
|
|
|
ShadowWidth,
|
|
|
|
|
this.Size.Height - ShadowWidth * 2);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private Rectangle BottomLeftRect
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
return new Rectangle(
|
|
|
|
|
0,
|
|
|
|
|
this.Size.Height - ShadowWidth,
|
|
|
|
|
ShadowWidth,
|
|
|
|
|
ShadowWidth);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private Rectangle BottomRect
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
return new Rectangle(
|
|
|
|
|
ShadowWidth,
|
|
|
|
|
this.Size.Height - ShadowWidth,
|
|
|
|
|
this.Size.Width - ShadowWidth * 2,
|
|
|
|
|
ShadowWidth);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private Rectangle BottomRightRect
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
return new Rectangle(
|
|
|
|
|
this.Size.Width - ShadowWidth,
|
|
|
|
|
this.Size.Height - ShadowWidth,
|
|
|
|
|
ShadowWidth,
|
|
|
|
|
ShadowWidth);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
private void DrawShadow(Graphics g)
|
|
|
|
|
{
|
|
|
|
|
int aDark = ShadowAValueDark;
|
|
|
|
|
int aLight = ShadowAValueLight;
|
|
|
|
|
if (aDark < 0)
|
|
|
|
|
aDark = 0;
|
|
|
|
|
if (aDark > 180)
|
|
|
|
|
aDark = 180;
|
|
|
|
|
if (aLight < 0)
|
|
|
|
|
aLight = 0;
|
|
|
|
|
if (aLight > 180)
|
|
|
|
|
aLight = 180;
|
|
|
|
|
if (aLight > aDark)
|
|
|
|
|
{
|
|
|
|
|
int t = aLight;
|
|
|
|
|
aLight = aDark;
|
|
|
|
|
aDark = t;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int diff = (aDark - aLight) / ShadowWidth;
|
|
|
|
|
Rectangle rect = base.ClientRectangle;
|
|
|
|
|
rect.Width--;
|
|
|
|
|
rect.Height--;
|
|
|
|
|
g.SmoothingMode = SmoothingMode.AntiAlias;
|
|
|
|
|
for (int i = 0; i < ShadowWidth; i++)
|
|
|
|
|
{
|
|
|
|
|
using (Pen p = new Pen(Color.FromArgb(aLight + diff * i, ShadowColor)))
|
|
|
|
|
{
|
|
|
|
|
g.DrawRectangle(p, rect);
|
|
|
|
|
}
|
|
|
|
|
rect.Inflate(-1, -1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
internal void RefleshLayeredForm()
|
|
|
|
|
{
|
|
|
|
|
Bitmap formBitMap = new Bitmap(base.Width, base.Height);
|
|
|
|
|
Graphics g = Graphics.FromImage(formBitMap);
|
|
|
|
|
|
|
|
|
|
DrawShadow(g);
|
|
|
|
|
|
|
|
|
|
Win32.WinAPI.POINT ptSrc = new Win32.WinAPI.POINT(0, 0);
|
|
|
|
|
Win32.WinAPI.POINT ptWinPos = new Win32.WinAPI.POINT(base.Left, base.Top);
|
|
|
|
|
Win32.WinAPI.SIZE szWinSize = new Win32.WinAPI.SIZE(Width, Height);
|
|
|
|
|
byte biAlpha = 0xFF;
|
|
|
|
|
Win32.WinAPI.BLENDFUNCTION stBlend = new Win32.WinAPI.BLENDFUNCTION(
|
|
|
|
|
(byte)Win32.WinAPI.BlendOp.AC_SRC_OVER, 0, biAlpha, (byte)Win32.WinAPI.BlendOp.AC_SRC_ALPHA);
|
|
|
|
|
|
|
|
|
|
IntPtr gdiBitMap = IntPtr.Zero;
|
|
|
|
|
IntPtr memoryDC = IntPtr.Zero;
|
|
|
|
|
IntPtr preBits = IntPtr.Zero;
|
|
|
|
|
IntPtr screenDC = IntPtr.Zero;
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
screenDC = Win32.WinAPI.GetDC(IntPtr.Zero);
|
|
|
|
|
memoryDC = Win32.WinAPI.CreateCompatibleDC(screenDC);
|
|
|
|
|
|
|
|
|
|
gdiBitMap = formBitMap.GetHbitmap(Color.FromArgb(0));
|
|
|
|
|
|
|
|
|
|
preBits = Win32.WinAPI.SelectObject(memoryDC, gdiBitMap);
|
|
|
|
|
Win32.WinAPI.UpdateLayeredWindow(base.Handle
|
|
|
|
|
, screenDC
|
|
|
|
|
, ref ptWinPos
|
|
|
|
|
, ref szWinSize
|
|
|
|
|
, memoryDC
|
|
|
|
|
, ref ptSrc
|
|
|
|
|
, 0
|
|
|
|
|
, ref stBlend
|
|
|
|
|
, (uint)Win32.WinAPI.ULWPara.ULW_ALPHA);
|
|
|
|
|
}
|
|
|
|
|
finally
|
|
|
|
|
{
|
|
|
|
|
if (gdiBitMap != IntPtr.Zero)
|
|
|
|
|
{
|
|
|
|
|
Win32.WinAPI.SelectObject(memoryDC, preBits);
|
|
|
|
|
Win32.WinAPI.DeleteObject(gdiBitMap);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Win32.WinAPI.DeleteDC(memoryDC);
|
|
|
|
|
Win32.WinAPI.ReleaseDC(IntPtr.Zero, screenDC);
|
|
|
|
|
g.Dispose();
|
|
|
|
|
formBitMap.Dispose();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void WmNcHitTest(ref Message m)
|
|
|
|
|
{
|
|
|
|
|
int para = m.LParam.ToInt32();
|
|
|
|
|
int x0 = Win32.WinAPI.LOWORD(para);
|
|
|
|
|
int y0 = Win32.WinAPI.HIWORD(para);
|
|
|
|
|
Point p = PointToClient(new Point(x0, y0));
|
|
|
|
|
|
|
|
|
|
if (UseShadowToResize)
|
|
|
|
|
{
|
|
|
|
|
if (TopLeftRect.Contains(p))
|
|
|
|
|
{
|
|
|
|
|
m.Result = new IntPtr((int)Win32.WinAPI.NCHITTEST.HTTOPLEFT);
|
|
|
|
|
return ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (TopRect.Contains(p))
|
|
|
|
|
{
|
|
|
|
|
m.Result = new IntPtr((int)Win32.WinAPI.NCHITTEST.HTTOP);
|
|
|
|
|
return ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (TopRightRect.Contains(p))
|
|
|
|
|
{
|
|
|
|
|
m.Result = new IntPtr((int)Win32.WinAPI.NCHITTEST.HTTOPRIGHT);
|
|
|
|
|
return ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (LeftRect.Contains(p))
|
|
|
|
|
{
|
|
|
|
|
m.Result = new IntPtr((int)Win32.WinAPI.NCHITTEST.HTLEFT);
|
|
|
|
|
return ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (RightRect.Contains(p))
|
|
|
|
|
{
|
|
|
|
|
m.Result = new IntPtr((int)Win32.WinAPI.NCHITTEST.HTRIGHT);
|
|
|
|
|
return ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (BottomLeftRect.Contains(p))
|
|
|
|
|
{
|
|
|
|
|
m.Result = new IntPtr((int)Win32.WinAPI.NCHITTEST.HTBOTTOMLEFT);
|
|
|
|
|
return ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (BottomRect.Contains(p))
|
|
|
|
|
{
|
|
|
|
|
m.Result = new IntPtr((int)Win32.WinAPI.NCHITTEST.HTBOTTOM);
|
|
|
|
|
return ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (BottomRightRect.Contains(p))
|
|
|
|
|
{
|
|
|
|
|
m.Result = new IntPtr((int)Win32.WinAPI.NCHITTEST.HTBOTTOMRIGHT);
|
|
|
|
|
return ;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m.Result = new IntPtr((int)Win32.WinAPI.NCHITTEST.HTCLIENT);
|
|
|
|
|
return ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected override void WndProc(ref Message m)
|
|
|
|
|
{
|
|
|
|
|
if (m.Msg == (int)Win32.WinAPI.WindowMessages.WM_NCHITTEST)
|
|
|
|
|
{
|
|
|
|
|
WmNcHitTest(ref m);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
base.WndProc(ref m);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected override void OnSizeChanged(EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
base.OnSizeChanged(e);
|
|
|
|
|
RefleshLayeredForm();
|
|
|
|
|
SetFormReion();
|
|
|
|
|
if (UseShadowToResize && _timeToResizeOwner && _owner.WindowState == FormWindowState.Normal)
|
|
|
|
|
SetOwnerSize();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected override void OnLocationChanged(EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
base.OnLocationChanged(e);
|
|
|
|
|
if (UseShadowToResize && _timeToResizeOwner && _owner.WindowState == FormWindowState.Normal)
|
|
|
|
|
SetOwnerLocation();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|