csharp/944095635/DMSkin-for-WPF/DMSkin.WPF/DMSkinComplexWindow.cs

DMSkinComplexWindow.cs
using DMSkin.Core.WIN32;
using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Threading;

namespace DMSkin.WPF
{
    /// 
    /// 双层双体 - 在Windows 7上面 系统按钮区域还存在一些BUG。
    /// 
    public partial clast DMSkinComplexWindow : Window
    {
        #region 初始化
        public DMSkinComplexWindow()
        {
            InitializeWindowStyle();
            //绑定窗体操作函数
            SourceInitialized += MainWindow_SourceInitialized;
            StateChanged += MainWindow_StateChanged;
            IsVisibleChanged += MainWindow_IsVisibleChanged;
            MouseLeftButtonDown += MainWindow_MouseLeftButtonDown;
            Closed += MainWindow_Closed;
            SizeChanged += MainWindow_SizeChanged;
            LocationChanged += MainWindow_LocationChanged;
        }
        #endregion

        #region 切换单双窗口模式
        /// 
        /// 加载双层窗口的样式
        /// 
        private void InitializeWindowStyle()
        {
            _shadowWindow = new ShadowWindow();
            Dispatcher.BeginInvoke(new Action(x =>
            {
                Thread.Sleep(70);
                _shadowWindow.Left = this.Left - 30;
                _shadowWindow.Top = this.Top - 30;
                ShadowWindowVisibility(true);//初始化
                Owner = _shadowWindow;//绑定阴影窗体
                Activate();
            }), DispatcherPriority.ApplicationIdle, this);
        }
        #endregion

        #region 阴影窗体
        /// 
        /// 显示或者隐藏阴影
        /// 
        private void ShadowWindowVisibility(bool show)
        {
            if (show)
            {
                _shadowWindow.Show();
            }
            else
            {
                _shadowWindow.Hide();
            }
        }

        /// 
        /// 阴影窗体
        /// 
        ShadowWindow _shadowWindow = null;
        /// 
        /// 窗体关闭时 关闭阴影窗口
        /// 
        private void MainWindow_Closed(object sender, EventArgs e)
        {
            if (_shadowWindow != null)
            {
                _shadowWindow.Close();
            }
        }

        /// 
        /// 主窗体修改尺寸时 更新阴影窗口尺寸
        /// 
        private void MainWindow_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            if (_shadowWindow != null)
            {
                _shadowWindow.Width = Width + 60;
                _shadowWindow.Height = Height + 60;
            }
        }

        /// 
        /// 窗体移动坐标时 更新阴影窗口坐标
        /// 
        private void MainWindow_LocationChanged(object sender, EventArgs e)
        {
            if (_shadowWindow != null)
            {
                _shadowWindow.Left = Left - 30;
                _shadowWindow.Top = Top - 30;
            }
        }
        #endregion

        #region 系统函数
        IntPtr Handle = IntPtr.Zero;
        void MainWindow_SourceInitialized(object sender, EventArgs e)
        {
            Handle = new WindowInteropHelper(this).Handle;
            HwndSource source = HwndSource.FromHwnd(Handle);
            if (source == null)
            { throw new Exception("Cannot get HwndSource instance."); }
            source.AddHook(new HwndSourceHook(this.WndProc));
        }

        private void WmNCCalcSize(IntPtr LParam)
        {
            // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/windows/windowreference/windowmessages/wm_nccalcsize.asp
            // http://groups.google.pl/groups?selm=OnRNaGfDEHA.1600%40tk2msftngp13.phx.gbl

            var r = (RECT)Marshal.PtrToStructure(LParam, typeof(RECT));
            //var max = MinMaxState == FormWindowState.Maximized;

            if (WindowState == WindowState.Maximized)
            {
                var x = NativeMethods.GetSystemMetrics(NativeConstants.SM_CXSIZEFRAME);
                var y = NativeMethods.GetSystemMetrics(NativeConstants.SM_CYSIZEFRAME);
                var p = NativeMethods.GetSystemMetrics(NativeConstants.SM_CXPADDEDBORDER);
                var w = x + p;
                var h = y + p;

                r.left += w;
                r.top += h;
                r.right -= w;
                r.bottom -= h;

                var appBarData = new APPBARDATA();
                appBarData.cbSize = Marshal.SizeOf(typeof(APPBARDATA));
                var autohide = (NativeMethods.SHAppBarMessage(NativeConstants.ABM_GETSTATE, ref appBarData) & NativeConstants.ABS_AUTOHIDE) != 0;
                if (autohide) r.bottom -= 1;

                Marshal.StructureToPtr(r, LParam, true);
            }
        }

        //四个坐标
        POINTAPI[] poin = new POINTAPI[4];
        //是否正在绘制边角
        bool ReWindowState = false;
        //重设主窗口裁剪区域
        public void ReWindow()
        {
            if (ReWindowState)//已经在绘制过程
            {
                return;
            }
            ReWindowState = true;
            Task.Factory.StartNew(() =>
            {
                //150毫秒延迟,并且150毫秒内不会重复触发多次
                Thread.Sleep(150);
                //让窗体不被裁剪
                poin[3].x = (int)ActualWidth;
                poin[1].y = (int)ActualHeight;
                poin[2].x = (int)ActualWidth;
                poin[2].y = (int)ActualHeight;
                IntPtr hRgn = NativeMethods.CreatePolygonRgn(ref poin[0], 4, 0);
                NativeMethods.SetWindowRgn(Handle, hRgn, true);
                ReWindowState = false;
                //("触发时间:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"));
            });
        }

        IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
        {
            switch (msg)
            {
                //WM_NCCALCSIZE
                case (int)WindowMessages.WM_NCCALCSIZE:
                    //WmNCCalcSize(lParam);
                    ReWindow();
                    handled = true;
                    break;
                ///重绘 非客户区
                case (int)WindowMessages.WM_NCPAINT:
                    // Here should all our painting occur, but...
                    handled = true;
                    return NativeConstants.TRUE;

                case (int)WindowMessages.WM_NCACTIVATE:
                    // ... WM_NCACTIVATE does some painting directly 
                    // without bothering with WM_NCPAINT ...
                    bool active = (wParam == NativeConstants.TRUE);
                    if (WindowState != WindowState.Minimized)
                    {
                        handled = true;
                        return NativeConstants.TRUE;
                    }
                    break;
                //------------------
                //if (wParam == (IntPtr)Win32.WM_TRUE)
                //{
                //    handled = true;
                //}

                case (int)WindowMessages.WM_NCLBUTTONDOWN:
                    if (wParam.ToInt32() == (int)HitTest.HTCLOSE ||
                        wParam.ToInt32() == (int)HitTest.HTMAXBUTTON ||
                        wParam.ToInt32() == (int)HitTest.HTMINBUTTON ||
                        wParam.ToInt32() == (int)HitTest.HTHELP)
                    {
                        NativeMethods.SendMessage(Handle, (int)WindowMessages.WM_NCPAINT, IntPtr.Zero, IntPtr.Zero);
                        handled = true;
                    }
                    break;
                case (int)WindowMessages.WM_NCUAHDRAWCAPTION:
                case (int)WindowMessages.WM_NCUAHDRAWFRAME:
                    handled = true;
                    break;
                    //获取窗口的最大化最小化信息
                    //case (int)WindowMessages.WM_GETMINMAXINFO:
                    //    WmGetMinMaxInfo(hwnd, lParam);
                    //    handled = true;
                    //    break;
                    //窗口拉伸 还有DPI BUG 
                    //case (int)WindowMessages.WM_NCHITTEST:
                    //    return WmNCHitTest(lParam, ref handled);
            }
            return IntPtr.Zero;
        }

        ///   
        /// 圆角拖动大小 
        ///   
        private readonly int cornerWidth = 8;

        ///   
        /// 拉伸鼠标坐标 
        ///   
        private Point mousePoint = new Point();
        private IntPtr WmNCHitTest(IntPtr lParam, ref bool handled)
        {
            this.mousePoint.X = (int)(short)(lParam.ToInt32() & 0xFFFF);
            this.mousePoint.Y = (int)(short)(lParam.ToInt32() >> 16);
            if (ResizeMode == ResizeMode.CanResize || ResizeMode == ResizeMode.CanResizeWithGrip)
            {
                handled = true;
                //if (Math.Abs(this.mousePoint.Y - this.Top)