396 lines
11 KiB
C#
396 lines
11 KiB
C#
/*
|
||
* 本代码受中华人民共和国著作权法保护,作者仅授权下载代码之人在学习和交流范围内
|
||
* 自由使用与修改代码;欲将代码用于商业用途的,请与作者联系。
|
||
* 使用本代码请保留此处信息。作者联系方式: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
|
||
{
|
||
get { return _owner.XTheme.ShadowWidth==0?1: _owner.XTheme.ShadowWidth; }
|
||
}
|
||
|
||
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();
|
||
}
|
||
}
|
||
}
|