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