RaUI/Source/ryControls/Gdu.WinFormUI/Forms/GMShadow.cs
如果当时 6713415f1d ### 2021-07-05更新
------
#### ryControlsV4    V3.0.2107.0501
- *.[修复]修复Gdu窗体阴影边框为0时出错的BUG。
2021-07-05 21:57:48 +08:00

396 lines
11 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* 本代码受中华人民共和国著作权法保护,作者仅授权下载代码之人在学习和交流范围内
* 自由使用与修改代码;欲将代码用于商业用途的,请与作者联系。
* 使用本代码请保留此处信息。作者联系方式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();
}
}
}