using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.ComponentModel;
using DevComponents.DotNetBar.Metro.Rendering;
using System.Runtime.InteropServices;
using System.Diagnostics;
using DevComponents.DotNetBar.Metro.ColorTables;
using DevComponents.DotNetBar.Controls;
using System.Reflection;
namespace DevComponents.DotNetBar.Metro
{
    public class MetroAppForm : Form
    {
        #region System Menu Constants
        private const string SysMenuRestore = "restore";
        private const string SysMenuMove = "move";
        private const string SysMenuSize = "size";
        private const string SysMenuMinimize = "minimize";
        private const string SysMenuMaximize = "maximize";
        private const string SysMenuClose = "close";
        private const string SysMenu = "sysMenu";
        #endregion
        #region Events
        /// 
        /// Occurs before modal panel is shown and allows change of modal panel bounds.
        /// 
        [Description("Occurs before modal panel is shown and allows change of modal panel bounds.")]
        public event ModalPanelBoundsEventHandler PrepareModalPanelBounds;
        /// 
        /// Raises PrepareModalPanelBounds event.
        /// 
        /// Provides event arguments.
        protected virtual void OnPrepareModalPanelBounds(ModalPanelBoundsEventArgs e)
        {
            ModalPanelBoundsEventHandler handler = PrepareModalPanelBounds;
            if (handler != null)
                handler(this, e);
        }
        #endregion
        #region Constructor
        private System.Windows.Forms.Padding GlassDefaultPadding = new System.Windows.Forms.Padding(1, 1, 1, 1); //new System.Windows.Forms.Padding(0, 1, 1, 1);
        private System.Windows.Forms.Padding PlainDefaultPadding = new System.Windows.Forms.Padding(1, 1, 1, 1);
        
        /// 
        /// Initializes a new instance of the MetroForm class.
        /// 
        public MetroAppForm()
        {
            if (!StyleManager.IsMetro(StyleManager.Style))
                StyleManager.Style = eStyle.Metro;
            StyleManager.Register(this);
            _IsGlassEnabled = WinApi.IsGlassEnabled;
            this.ControlBox = false;
            //this.Font = new System.Drawing.Font("Segoe UI", 14.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
            if (_IsGlassEnabled)
                this.Padding = GlassDefaultPadding;
            else
                this.Padding = PlainDefaultPadding;
            //_BorderOverlay = new BorderOverlay();
            //this.Controls.Add(_BorderOverlay);
            //UpdateBorderOverlay();
        }
        /// 
        /// Clean up any resources being used.
        /// 
        /// true if managed resources should be disposed; otherwise, false.
        protected override void Dispose(bool disposing)
        {
            if (disposing) StyleManager.Unregister(this);
            base.Dispose(disposing);
        }
        //private BorderOverlay _BorderOverlay = null;
        //private void UpdateBorderOverlay()
        //{
        //    if (_BorderOverlay == null) return;
        //    Rectangle bounds = new Rectangle(0, 0, this.Width, this.Height);
        //    if (_BorderOverlay.Bounds != bounds)
        //    {
        //        // Exclude Border
        //        Rectangle borderExcludedBounds = bounds;
        //        Thickness thickness = this.BorderThickness;
        //        if (thickness.IsZero)
        //        {
        //            thickness = MetroRender.GetColorTable().MetroForm.BorderThickness;
        //        }
        //        if (thickness.IsZero)
        //        {
        //            _BorderOverlay.Visible = false;
        //            return;
        //        }
        //        borderExcludedBounds.Width -= (int)thickness.Horizontal;
        //        borderExcludedBounds.Height -= (int)thickness.Vertical;
        //        borderExcludedBounds.X += (int)thickness.Left;
        //        borderExcludedBounds.Y += (int)thickness.Top;
        //        Region region = new Region(bounds);
        //        region.Exclude(borderExcludedBounds);
        //        if (!_BorderOverlay.Visible) _BorderOverlay.Visible = true;
        //        _BorderOverlay.Bounds = bounds;
        //        _BorderOverlay.Region = region;
        //        if (this.Controls.IndexOf(_BorderOverlay) != 0)
        //            _BorderOverlay.SendToBack();
        //    }
        //}
        /// 
        /// Called by StyleManager to notify control that style on manager has changed and that control should refresh its appearance if
        /// its style is controlled by StyleManager.
        /// 
        /// New active style.
        [EditorBrowsable(EditorBrowsableState.Never)]
        public void StyleManagerStyleChanged(eDotNetBarStyle newStyle)
        {
            UpdateColorScheme();
        }
        private void UpdateColorScheme()
        {
            StyleManager.UpdateMetroAmbientColors(this);
        }
        protected override void OnShown(EventArgs e)
        {
            if (this.DesignMode)
                UpdateColorScheme();
            else if (_PreRenderShell && _MetroTab != null)
            {
                using (Bitmap bmp = new Bitmap(16, 16))
                    _MetroTab.DrawToBitmap(bmp, new Rectangle(0, 0, this.Width, this.Height));
            }
            base.OnShown(e);
        }
        private bool _PreRenderShell = true;
        /// 
        /// Gets or sets whether MetroShell is pre-rendered when form is shown to make first rendering smoother. Default value is true.
        /// 
        [DefaultValue(true), Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public bool PreRenderShell
        {
            get { return _PreRenderShell; }
            set { _PreRenderShell = value; }
        }
        protected override void OnHandleCreated(EventArgs e)
        {
            UpdateColorScheme();
            base.OnHandleCreated(e);
        }
        #endregion
        #region Implementation
        protected override void ScaleControl(SizeF factor, BoundsSpecified specified)
        {
            Dpi.SetScaling(factor);
            base.ScaleControl(factor, specified);
        }
        /// 
        /// Gets whether at least one modal panel is displayed.
        /// 
        [Browsable(false)]
        public bool IsModalPanelDisplayed
        {
            get
            {
                return _ModalPanels.Count > 0;
            }
        }
        private bool _ModalPanelBoundsExcludeStatusBar = false;
        /// 
        /// Indicates whether modal panel when displayed shows MetroStatusBar.
        /// 
        [DefaultValue(false), Category("Appearance"), Description("Indicates whether modal panel when displayed shows MetroStatusBar.")]
        public bool ModalPanelBoundsExcludeStatusBar
        {
            get { return _ModalPanelBoundsExcludeStatusBar; }
            set
            {
                _ModalPanelBoundsExcludeStatusBar = value;
            }
        }
        
        /// 
        /// Shows the panel control in the center of the form and covers all non system controls making the panel effectively modal.
        /// 
        /// Control to show.
        public void ShowModalPanel(Control panel)
        {
            ShowModalPanel(panel, false, eSlideSide.Left, SlidePanel.DefaultAnimationTime);
        }
        /// 
        /// Shows the panel control in the center of the form by sliding it in from specified side and covers all non system controls making the panel effectively modal.
        /// 
        /// Panel to show.
        /// Side to slide panel into the view from.
        public void ShowModalPanel(Control panel, eSlideSide slideFromSide)
        {
            ShowModalPanel(panel, true, slideFromSide, SlidePanel.DefaultAnimationTime);
        }
        /// 
        /// Shows the panel control in the center of the form by sliding it in from specified side and covers all non system controls making the panel effectively modal.
        /// 
        /// Panel to show.
        /// Side to slide panel into the view from.
        /// Slide animation speed in milliseconds.
        public void ShowModalPanel(Control panel, eSlideSide slideFromSide, int animationTimeMilliseconds)
        {
            ShowModalPanel(panel, true, slideFromSide, SlidePanel.DefaultAnimationTime);
        }
        private List _ModalPanels = new List();
        private List _DisabledItemIds = new List();
        private void ShowModalPanel(Control panel, bool slideIn, eSlideSide slideFromSide, int animationTimeMilliseconds)
        {
            StyleManager.UpdateAmbientColors(panel);
            SlidePanel slidePanel = new SlidePanel();
            slidePanel.CenterContent = true;
            slidePanel.AnimationTime = animationTimeMilliseconds;
            slidePanel.SlideSide = slideFromSide;
            slidePanel.SlideOutButtonVisible = false;
            if (slideIn)
            {
                slidePanel.Bounds = GetModalPanelBounds();
                slidePanel.SlideOutOfViewSilent(this);
            }
            else
            {
                slidePanel.Bounds = GetModalPanelBounds();
            }
            slidePanel.Controls.Add(panel);
            this.Controls.Add(slidePanel);
            this.Controls.SetChildIndex(slidePanel, 0);
            _ModalPanels.Add(slidePanel);
            if (_ModalPanels.Count == 1 && _MetroTab != null)
            {
                //_MetroTab.MetroTabStrip.Enabled = false;
                _MetroTab.MetroTabStrip.StripContainerItem.Enabled = false;
                for (int i = 0; i < _MetroTab.MetroTabStrip.CaptionContainerItem.SubItems.Count; i++)
                {
                    BaseItem item = _MetroTab.MetroTabStrip.CaptionContainerItem.SubItems[i];
                    if (item.SystemItem && !(item is QatCustomizeItem)) continue;
                    item.Enabled = false;
                    _DisabledItemIds.Add(item.Id);
                }
                _MetroTab.MetroTabStrip.Invalidate();
            }
            this.Update();
            if (slideIn)
                slidePanel.IsOpen = true;
        }
        /// 
        /// Hides the panel control that was previously shown using ShowModalPanel method.
        /// 
        /// Control to hide.
        public void CloseModalPanel(Control panel)
        {
            CloseModalPanel(panel, false, eSlideSide.Left);
        }
        /// 
        /// Hides the panel control that was previously shown using ShowModalPanel method by sliding it out of the view to the specified side.
        /// 
        /// Control to hide.
        /// Side to slide control into.
        public void CloseModalPanel(Control panel, eSlideSide slideOutToSide)
        {
            CloseModalPanel(panel, true, slideOutToSide);
        }
        private void CloseModalPanel(Control panel, bool slideOut, eSlideSide slideOutToSide)
        {
            SlidePanel slidePanel = null;
            foreach (Control modalPanel in _ModalPanels)
            {
                if (modalPanel.Contains(panel))
                {
                    slidePanel = (SlidePanel)modalPanel;
                    break;
                }
            }
            if (slidePanel == null) throw new ArgumentException("panel was not shown previously using ShowModalPanel method");
            if (slideOut)
            {
                slidePanel.SlideSide = slideOutToSide;
                slidePanel.IsOpen = false;
                DateTime start = DateTime.Now;
                while (slidePanel.IsAnimating)
                {
                    Application.DoEvents();
                    if (DateTime.Now.Subtract(start).TotalMilliseconds > 950)
                    {
                        slidePanel.AbortAnimation();
                        slidePanel.Visible = false;
                        break;
                    }
                }
            }
            else
                slidePanel.Visible = false;
            slidePanel.Controls.Remove(panel);
            if (slidePanel.Parent != null)
                slidePanel.Parent.Controls.Remove(slidePanel);
            if (_ModalPanels.Contains(slidePanel))
                _ModalPanels.Remove(slidePanel);
            if(!slidePanel.IsDisposed)
                slidePanel.Dispose();
            if (_ModalPanels.Count == 0 && _MetroTab != null)
            {
                //_MetroTab.MetroTabStrip.Enabled = true;
                _MetroTab.MetroTabStrip.StripContainerItem.Enabled = true;
                for (int i = 0; i < _MetroTab.MetroTabStrip.CaptionContainerItem.SubItems.Count; i++)
                {
                    BaseItem item = _MetroTab.MetroTabStrip.CaptionContainerItem.SubItems[i];
                    if (item.SystemItem) continue;
                    if(_DisabledItemIds.Contains(item.Id))
                        item.Enabled = true;
                }
                _MetroTab.MetroTabStrip.Refresh();
            }
        }
        internal NonClientInfo GetNonClientInfo()
        {
            WinApi.RECT rect = new WinApi.RECT(0, 0, 200, 200);
            CreateParams params1 = this.CreateParams;
            WinApi.AdjustWindowRectEx(ref rect, params1.Style, false, params1.ExStyle);
            NonClientInfo n = new NonClientInfo();
            n.CaptionTotalHeight = Math.Abs(rect.Top);
            n.BottomBorder = rect.Height - 200 - n.CaptionTotalHeight;
            n.LeftBorder = Math.Abs(rect.Left);
            n.RightBorder = rect.Width - 200 - n.LeftBorder;
            return n;
        }
        private void UpdateModalPanelsSize()
        {
            foreach (Control modalPanel in _ModalPanels)
            {
                modalPanel.Bounds = GetModalPanelBounds();
                if (this.WindowState == FormWindowState.Maximized)
                {
                    NonClientInfo nci = GetNonClientInfo();
                    modalPanel.Padding = new System.Windows.Forms.Padding(nci.LeftBorder + 1);
                }
                else
                    modalPanel.Padding = new System.Windows.Forms.Padding();
            }
        }
        private Rectangle GetModalPanelBounds()
        {
            Thickness borderThickness = GetBorderThickness();
            int statusBarHeight = 0;
            if (_ModalPanelBoundsExcludeStatusBar)
            {
                foreach (Control item in this.Controls)
                {
                    if (item is MetroStatusBar && item.Dock == DockStyle.Bottom)
                    {
                        statusBarHeight = item.Height;
                        break;
                    }
                }
            }
            Rectangle bounds = Rectangle.Empty;
            if (_MetroTab != null && _MetroTab.CaptionVisible)
            {
                int captionHeight = _MetroTab.MetroTabStrip.GetCaptionHeight() + 2;
                bounds = new Rectangle((int)borderThickness.Left, captionHeight, this.Width - (int)borderThickness.Horizontal, this.Height - captionHeight - (int)borderThickness.Bottom - statusBarHeight);
            }
            else
            {
                bounds = new Rectangle((int)borderThickness.Left, (int)borderThickness.Top, this.Width - (int)borderThickness.Horizontal, this.Height - (int)borderThickness.Vertical - statusBarHeight);
            }
            ModalPanelBoundsEventArgs args = new ModalPanelBoundsEventArgs(bounds);
            OnPrepareModalPanelBounds(args);
            bounds = args.ModalPanelBounds;
            return bounds;
        }
        private bool _IsGlassEnabled = false;
        /// 
        /// Returns whether Windows Glass effects are enabled.
        /// 
        [Browsable(false)]
        public bool IsGlassEnabled
        {
            get
            {
                return _IsGlassEnabled;
            }
        }
        private void UpdateIsGlassEnabled()
        {
            bool glassEnabled = WinApi.IsGlassEnabled;
            if (glassEnabled != _IsGlassEnabled)
            {
                _IsGlassEnabled = glassEnabled;
                OnGlassEnabledChanged();
            }
        }
        private void OnGlassEnabledChanged()
        {
            if (_IsGlassEnabled)
                this.Padding = GlassDefaultPadding;
            else
                this.Padding = PlainDefaultPadding;
            if (_IsGlassEnabled && this.Region != null)
                this.Region = null;
            else
                this.Region = GetPlainFormRegion();
            this.Refresh();
        }
        private Region GetPlainFormRegion()
        {
            Region reg = new Region(new Rectangle(0, 0, this.Width, this.Height));
            return reg;
        }
        private MetroShell _MetroTab = null;
        /// 
        /// Gets or sets the MetroTab that is hosted by this form. This property is for internal use only.
        /// 
        [Browsable(false)]
        public virtual MetroShell MetroShell
        {
            get { return _MetroTab; }
            internal set
            {
                _MetroTab = value;
            }
        }
        protected override void OnStyleChanged(EventArgs e)
        {
            UpdateMetroSystemCaptionItem();
            base.OnStyleChanged(e);
        }
        protected override void OnControlAdded(ControlEventArgs e)
        {
            if (e.Control is MetroShell)
            {
                _MetroTab = e.Control as MetroShell;
                UpdateMetroSystemCaptionItem();
            }
            base.OnControlAdded(e);
        }
        protected override void OnControlRemoved(ControlEventArgs e)
        {
            if (e.Control == _MetroTab)
            {
                _MetroTab = null;
            }
            base.OnControlRemoved(e);
        }
        private bool _Sizable = true;
        /// 
        /// Gets or sets whether form can be resized.
        /// 
        [DefaultValue(true), Category("Behavior"), Description("Indicates whether form can be resized.")]
        public bool Sizable
        {
            get { return _Sizable; }
            set { _Sizable = value; }
        }
        /// 
        /// Gets effective Border Thickness for the form.
        /// 
        /// Thickness
        public Thickness GetBorderThickness()
        {
            if (!_BorderThickness.IsZero) return _BorderThickness;
            MetroAppFormColorTable ct = GetFormColorTable();
            return this.IsGlassEnabled ? ct.BorderThickness : ct.BorderPlainThickness;
        }
        private MetroAppFormColorTable GetFormColorTable()
        {
            MetroColorTable ct = MetroRender.GetColorTable();
            return ct.MetroAppForm;
        }
        private Thickness _BorderThickness = new Thickness();
        /// 
        /// Gets or sets the form border thickness. Default value is empty thickness which indicates that thickness is taken from MetroFormColorTable.
        /// 
        [Category("Appearance"), Description("Indicates form border thickness.")]
        public Thickness BorderThickness
        {
            get { return _BorderThickness; }
            set
            {
                if (value != _BorderThickness)
                {
                    Thickness oldValue = _BorderThickness;
                    _BorderThickness = value;
                    OnBorderThicknessChanged(oldValue, value);
                }
            }
        }
        /// 
        /// Called when BorderThickness property has changed.
        /// 
        /// Old property value
        /// New property value
        protected virtual void OnBorderThicknessChanged(Thickness oldValue, Thickness newValue)
        {
            //OnPropertyChanged(new PropertyChangedEventArgs("BorderThickness"));
            this.Invalidate();
        }
        private BorderColors _BorderColor;
        /// 
        /// Gets or sets the form border colors.
        /// 
        public BorderColors BorderColor
        {
            get { return _BorderColor; }
            set
            {
                if (value != _BorderColor)
                {
                    BorderColors oldValue = _BorderColor;
                    _BorderColor = value;
                    OnBorderColorChanged(oldValue, value);
                }
            }
        }
        /// 
        /// Called when BorderColor property has changed.
        /// 
        /// Old property value
        /// New property value
        protected virtual void OnBorderColorChanged(BorderColors oldValue, BorderColors newValue)
        {
            //OnPropertyChanged(new PropertyChangedEventArgs("BorderColor"));
            this.Invalidate();
        }
        protected override void OnPaint(PaintEventArgs e)
        {
            if (!_IsGlassEnabled && this.Region == null)
                this.Region = GetPlainFormRegion();
            MetroRender.Paint(this, e);
            base.OnPaint(e);
        }
        protected override void OnActivated(EventArgs e)
        {
            ExtendGlass();
            this.Invalidate();
            base.OnActivated(e);
        }
        protected override void OnDeactivate(EventArgs e)
        {
            this.Invalidate();
            base.OnDeactivate(e);
        }
        private void ExtendGlass()
        {
            if (!WinApi.IsGlassEnabled) return;
            WinApi.MARGINS m = new WinApi.MARGINS();
            m.cyTopHeight = 0;
            m.cxLeftWidth = 0;
            m.cxRightWidth = 0;
            m.cyBottomHeight = NativeFunctions.IsTerminalSession() ? 0 : 1;
            WinApi.DwmExtendFrameIntoClientArea(this.Handle, ref m);
        }
        protected virtual bool WindowsMessageSetText(ref Message m)
        {
            if (WinApi.IsGlassEnabled) return true;
            bool modified = WinApi.ModifyHwndStyle(m.HWnd, (int)WinApi.WindowStyles.WS_VISIBLE, 0);
            base.DefWndProc(ref m);
            if (_MetroTab != null) _MetroTab.Refresh();
            if (modified)
            {
                WinApi.ModifyHwndStyle(m.HWnd, 0, (int)WinApi.WindowStyles.WS_VISIBLE);
            }
            return false;
        }
        protected virtual bool WindowsMessageWindowsPosChanged(ref Message m)
        {
            if (this.WindowState == FormWindowState.Minimized || this.WindowState == FormWindowState.Maximized)
            {
                _TrackSetBoundsCore = true;
                base.WndProc(ref m);
                _TrackSetBoundsCore = true;
                return false;
            }
            return true;
        }
        protected override void WndProc(ref Message m)
        {
            bool callBase = true;
            if (!PreProcessWndProc(ref m))
                return;
            if (m.Msg == (int)WinApi.WindowsMessages.WM_NCCALCSIZE)
            {
                callBase = WindowsMessageNCCalcSize(ref m);
            }
            else if (m.Msg == (int)WinApi.WindowsMessages.WM_NCACTIVATE)
            {
                callBase = WindowsMessageNCActivate(ref m);
            }
            else if (m.Msg == (int)WinApi.WindowsMessages.WM_DWMCOMPOSITIONCHANGED)
            {
                callBase = WindowsMessageDwmCompositionChanged(ref m);
            }
            else if (m.Msg == (int)WinApi.WindowsMessages.WM_NCHITTEST)
            {
                callBase = WindowsMessageNCHitTest(ref m);
            }
            else if (m.Msg == (int)WinApi.WindowsMessages.WM_SETTEXT)
            {
                callBase = WindowsMessageSetText(ref m);
            }
            else if (m.Msg == (int)WinApi.WindowsMessages.WM_NCPAINT)
            {
                callBase = WindowsMessageNCPaint(ref m);
            }
            else if (m.Msg == (int)WinApi.WindowsMessages.WM_ERASEBKGND)
            {
                if (!WinApi.IsGlassEnabled)
                {
                    callBase = false;
                    m.Result = new IntPtr(1);
                }
            }
            else if (m.Msg == (int)WinApi.WindowsMessages.WM_SETICON)
            {
                callBase = WindowsMessageSetIcon(ref m);
            }
            else if (m.Msg == (int)WinApi.WindowsMessages.WM_SETTEXT)
            {
                callBase = WindowsMessageSetText(ref m);
            }
            else if (m.Msg == (int)WinApi.WindowsMessages.WM_SETCURSOR)
            {
                callBase = WindowsMessageSetCursor(ref m);
            }
            else if (m.Msg == (int)WinApi.WindowsMessages.WM_WINDOWPOSCHANGED)
            {
                callBase = WindowsMessageWindowsPosChanged(ref m);
            }
            if (callBase)
                base.WndProc(ref m);
        }
        protected virtual bool WindowsMessageSetCursor(ref Message m)
        {
            // Button down on client area while there is a modal form displayed
            if (!_IsActive && (WinApi.HIWORD(m.LParam) == (int)WinApi.WindowsMessages.WM_LBUTTONUP || WinApi.HIWORD(m.LParam) == (int)WinApi.WindowsMessages.WM_LBUTTONDOWN) && WinApi.LOWORD(m.LParam) == (int)WinApi.WindowHitTestRegions.Error ||
                !this.Enabled || BarUtilities.IsModalFormOpen)
                return true;
            bool modified = WinApi.ModifyHwndStyle(m.HWnd, (int)WinApi.WindowStyles.WS_VISIBLE, 0);
            base.DefWndProc(ref m);
            if (_MetroTab != null && this.DesignMode) _MetroTab.Refresh();
            if (modified)
            {
                WinApi.ModifyHwndStyle(m.HWnd, 0, (int)WinApi.WindowStyles.WS_VISIBLE);
            }
            return false;
        }
        protected virtual bool WindowsMessageSetIcon(ref Message m)
        {
            bool modified = WinApi.ModifyHwndStyle(m.HWnd, (int)WinApi.WindowStyles.WS_VISIBLE, 0);
            base.DefWndProc(ref m);
            if (_MetroTab != null) _MetroTab.Refresh();
            if (modified)
            {
                WinApi.ModifyHwndStyle(m.HWnd, 0, (int)WinApi.WindowStyles.WS_VISIBLE);
            }
            return false;
        }
        protected virtual bool WindowsMessageNCPaint(ref Message m)
        {
            if (WinApi.IsGlassEnabled)
            {
                return true;
            }
            else
            {
                m.Result = IntPtr.Zero;
                return false;
            }
        }
        /// 
        /// Called when WM_NCHITTEST message is received.
        /// 
        /// Reference to message data.
        /// Return true to call base form implementation otherwise return false.
        protected virtual bool WindowsMessageNCHitTest(ref Message m)
        {
            // Get position being tested...
            int x = WinApi.LOWORD(m.LParam);
            int y = WinApi.HIWORD(m.LParam);
            Point p = PointToClient(new Point(x, y));
            Thickness borderResize = FormResizeBorder;
            if (this.Sizable && !borderResize.IsZero && this.WindowState == FormWindowState.Normal)
            {
                Rectangle hitTest = new Rectangle(0, 0, (int)borderResize.Left, (int)borderResize.Top); hitTest.Inflate(1, 1);
                if (hitTest.Contains(p))
                {
                    m.Result = new IntPtr((int)WinApi.WindowHitTestRegions.TopLeftSizeableCorner);
                    return false;
                }
                hitTest = new Rectangle(this.Width - (int)borderResize.Right, 0, (int)borderResize.Right, (int)borderResize.Top); hitTest.Inflate(1, 1);
                if (hitTest.Contains(p))
                {
                    m.Result = new IntPtr((int)WinApi.WindowHitTestRegions.TopRightSizeableCorner);
                    return false;
                }
                hitTest = new Rectangle(this.Width - ((int)borderResize.Right+Dpi.Width10), this.Height - ((int)borderResize.Bottom+Dpi.Height10), (int)borderResize.Right+Dpi.Width10, (int)borderResize.Bottom+Dpi.Height10); hitTest.Inflate(2, 2);
                if (hitTest.Contains(p))
                {
                    m.Result = new IntPtr((int)WinApi.WindowHitTestRegions.BottomRightSizeableCorner);
                    return false;
                }
                hitTest = new Rectangle(0, this.Height - (int)borderResize.Bottom, (int)borderResize.Left, (int)borderResize.Bottom); hitTest.Inflate(1, 1);
                if (hitTest.Contains(p))
                {
                    m.Result = new IntPtr((int)WinApi.WindowHitTestRegions.BottomLeftSizeableCorner);
                    return false;
                }
                hitTest = new Rectangle(0, 0, (int)borderResize.Left, this.Height);
                if (hitTest.Contains(p))
                {
                    m.Result = new IntPtr((int)WinApi.WindowHitTestRegions.LeftSizeableBorder);
                    return false;
                }
                hitTest = new Rectangle(0, 0, this.Width, (int)borderResize.Top);
                if (hitTest.Contains(p))
                {
                    m.Result = new IntPtr((int)WinApi.WindowHitTestRegions.TopSizeableBorder);
                    return false;
                }
                hitTest = new Rectangle(this.Width - (int)borderResize.Right, 0, (int)borderResize.Right, this.Height);
                if (hitTest.Contains(p))
                {
                    m.Result = new IntPtr((int)WinApi.WindowHitTestRegions.RightSizeableBorder);
                    return false;
                }
                hitTest = new Rectangle(0, this.Height - (int)borderResize.Bottom, this.Width, (int)borderResize.Bottom);
                if (hitTest.Contains(p))
                {
                    m.Result = new IntPtr((int)WinApi.WindowHitTestRegions.BottomSizeableBorder);
                    return false;
                }
            }
            MetroShell tab = _MetroTab;
            if (tab != null)
            {
                Rectangle r = new Rectangle((RightToLeft == RightToLeft.No ? (int)borderResize.Left : this.Width - (int)borderResize.Right - 24), (int)borderResize.Left, 24, 24);
                if (r.Contains(p))
                {
                    m.Result = new IntPtr((int)WinApi.WindowHitTestRegions.Menu);
                    return false;
                }
            }
            if (BarFunctions.IsWindows7 && this.WindowState == FormWindowState.Maximized && tab != null && tab.CaptionVisible)
            {
                p = tab.MetroTabStrip.PointToClient(new Point(x, y));
                if (tab.MetroTabStrip.CaptionBounds.Contains(p))
                {
                    m.Result = new IntPtr((int)WinApi.WindowHitTestRegions.TitleBar);
                    return false;
                }
            }
            return true;
        }
        /// 
        /// Called when WM_DWMCOMPOSITIONCHANGED message is received.
        /// 
        /// Reference to message data.
        /// Return true to call base form implementation otherwise return false.
        protected virtual bool WindowsMessageDwmCompositionChanged(ref Message m)
        {
            UpdateIsGlassEnabled();
            ExtendGlass();
            return true;
        }
        private bool _IsActive = false;
        /// 
        /// Gets whether form is active.
        /// 
        [Browsable(false)]
        public bool IsActive
        {
            get { return _IsActive; }
            internal set
            {
                if (_IsActive != value)
                {
                    _IsActive = value;
                    OnIsActiveChanged();
                }
            }
        }
        private void OnIsActiveChanged()
        {
            if (_MetroTab != null)
                _MetroTab.MetroTabStrip.Invalidate(_MetroTab.MetroTabStrip.CaptionBounds);
        }
        /// 
        /// Called when WM_NCACTIVATE message is received.
        /// 
        /// Reference to message data.
        /// Return true to call base form implementation otherwise return false.
        protected virtual bool WindowsMessageNCActivate(ref Message m)
        {
            if (m.WParam != IntPtr.Zero)
                IsActive = true;
            else
                IsActive = false;
            m.Result = WinApi.DefWindowProc(m.HWnd, WinApi.WindowsMessages.WM_NCACTIVATE, m.WParam, new IntPtr(-1));
            if (this.DesignMode)
                RefreshAll();
            return false;
        }
        private void RefreshAll()
        {
            if (this.IsHandleCreated)
            {
                this.Invalidate(true);
                this.Refresh();
            }
        }
        protected override void OnTextChanged(EventArgs e)
        {
            if (this.DesignMode)
            {
                if (_MetroTab != null) _MetroTab.Refresh();
            }
            base.OnTextChanged(e);
        }
        private bool _Minimized = false;
        private bool _Maximized = false;
        private bool _ChangingSize = false;
        protected override void OnResize(EventArgs e)
        {
            if (!_IsGlassEnabled)
            {
                this.Region = GetPlainFormRegion();
                this.Invalidate();
            }
            UpdateModalPanelsSize();
            
            base.OnResize(e);
        }
        private bool _TrackSetBoundsCore = false;
        protected override void SetBoundsCore(int x, int y, int width, int height, BoundsSpecified specified)
        {
            if (_TrackSetBoundsCore ||
                this.DesignMode && ((specified & BoundsSpecified.Height) == BoundsSpecified.Height || (specified & BoundsSpecified.Width) == BoundsSpecified.Width))
            {
                if (width != this.Width || height != this.Height)
                {
                    AdjustBounds(ref width, ref height, specified);
                }
                _TrackSetBoundsCore = false;
            }
            //else if ((specified & BoundsSpecified.Width) == BoundsSpecified.None)
            //{
            //    specified |= BoundsSpecified.Width;
            //    AdjustBounds(ref width, ref height, specified);
            //}
            base.SetBoundsCore(x, y, width, height, specified);
        }
        protected virtual void AdjustBounds(ref int width, ref int height)
        {
            AdjustBounds(ref width, ref height, BoundsSpecified.Width | BoundsSpecified.Height);
        }
        protected virtual void AdjustBounds(ref int width, ref int height, BoundsSpecified specified)
        {
            WinApi.RECT rect = new WinApi.RECT(0, 0, width, height);
            CreateParams params1 = this.CreateParams;
            WinApi.AdjustWindowRectEx(ref rect, params1.Style, false, params1.ExStyle);
            if ((specified & BoundsSpecified.Height) == BoundsSpecified.Height)
            {
                height -= (rect.Height - height);
                //if (IsGlassEnabled)
                //{
                //    if (this.FormBorderStyle == FormBorderStyle.FixedDialog)
                //        height += SystemInformation.FixedFrameBorderSize.Height;
                //    else if (this.FormBorderStyle == FormBorderStyle.Fixed3D)
                //        height += SystemInformation.FixedFrameBorderSize.Height;
                //    else if (this.FormBorderStyle == FormBorderStyle.FixedSingle)
                //        height += 1;
                //    else if (this.FormBorderStyle == FormBorderStyle.FixedToolWindow)
                //        height += SystemInformation.FixedFrameBorderSize.Height;
                //    else
                //        height += SystemInformation.FrameBorderSize.Height /* * NativeFunctions.BorderMultiplierFactor*/;
                //}
            }
            if ((specified & BoundsSpecified.Width) == BoundsSpecified.Width)
            {
                width -= (rect.Width - width);
            }
        }
        protected override void SetClientSizeCore(int x, int y)
        {
            if (!this.DesignMode)
            {
                this.Size = new Size(x, y);
                Type type = typeof(Control);
                try // try with ignore catch is bad idea but in this case its for future proofing, just in case M$ removes these members
                {
                    type.InvokeMember("clientWidth", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.SetField, null, this, new object[] { x });
                    type.InvokeMember("clientHeight", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.SetField, null, this, new object[] { y });
                }
                catch { }
                OnClientSizeChanged(EventArgs.Empty);
                return;
            }
            base.SetClientSizeCore(x, y);
        }
        private FormWindowState GetWindowState()
        {
            WinApi.WINDOWPLACEMENT wp = new WinApi.WINDOWPLACEMENT();
            if (WinApi.GetWindowPlacement(this.Handle, out wp))
            {
                if (wp.showCmd == (int)WinApi.ShowWindowCommands.Maximize)
                    return FormWindowState.Maximized;
                else if (wp.showCmd == (int)WinApi.ShowWindowCommands.Minimize)
                    return FormWindowState.Minimized;
                else if (wp.showCmd == (int)WinApi.ShowWindowCommands.Normal)
                    return FormWindowState.Normal;
            }
            return this.WindowState;
        }
        /// 
        /// Called when WM_NCCALCSIZE message is received.
        /// 
        /// Message structure.
        /// true to call base WndProc otherwise false.
        protected virtual bool WindowsMessageNCCalcSize(ref Message m)
        {
            // Default implementation of ribbon form does not have non-client area at all...
            if (m.WParam != IntPtr.Zero && GetWindowState() == FormWindowState.Maximized)
            {
                WinApi.NCCALCSIZE_PARAMS csp;
                csp = (WinApi.NCCALCSIZE_PARAMS)Marshal.PtrToStructure(m.LParam, typeof(WinApi.NCCALCSIZE_PARAMS));
                NonClientInfo nci = GetNonClientInfo();
                Size reduction = new Size(nci.LeftBorder, nci.BottomBorder); //SystemInformation.FrameBorderSize;
                Size frameBorderSize = reduction;
                if (reduction.Width > 2)
                    reduction.Width -= reduction.Width - 2;
                if (reduction.Height > 2)
                    reduction.Height -= reduction.Height - 2;
                WinApi.WINDOWPOS pos = (WinApi.WINDOWPOS)Marshal.PtrToStructure(csp.lppos, typeof(WinApi.WINDOWPOS));
                //Console.WriteLine(pos);
                WinApi.RECT newClientRect = WinApi.RECT.FromRectangle(new Rectangle(pos.x + frameBorderSize.Width - 1, pos.y + reduction.Height,
                    pos.cx - frameBorderSize.Width * 2 + 3, pos.cy - frameBorderSize.Height - 1));
                if (_AutoHideTaskBarReduction > 0)
                {
                    Taskbar taskBar = new Taskbar();
                    if (taskBar.AutoHide)
                    {
                        if (taskBar.Position == TaskbarPosition.Bottom)
                            newClientRect.Bottom -= _AutoHideTaskBarReduction;
                        else if (taskBar.Position == TaskbarPosition.Top)
                        {
                            newClientRect.Bottom -= _AutoHideTaskBarReduction;
                            newClientRect.Top += _AutoHideTaskBarReduction;
                        }
                        else if (taskBar.Position == TaskbarPosition.Left)
                        {
                            newClientRect.Right -= _AutoHideTaskBarReduction;
                            newClientRect.Left += _AutoHideTaskBarReduction;
                        }
                        else if (taskBar.Position == TaskbarPosition.Right)
                            newClientRect.Right -= _AutoHideTaskBarReduction;
                    }
                }
                csp.rgrc0 = newClientRect;
                csp.rgrc1 = newClientRect;
                Marshal.StructureToPtr(csp, m.LParam, false);
                m.Result = new IntPtr((int)WinApi.WindowsMessages.WVR_VALIDRECTS);
                this.Invalidate();
                return false;
            }
            m.Result = IntPtr.Zero;
            this.Invalidate();
            return false;
        }
        private int _AutoHideTaskBarReduction = 4;
        /// 
        /// Indicates the number of pixels subtracted from form's height or width (depending on taskbar position) when form is maximized and taskbar is in auto-hide state. Default value is 4.
        /// 
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public int AutoHideTaskBarReduction
        {
            get { return _AutoHideTaskBarReduction; }
            set { _AutoHideTaskBarReduction = value; }
        }
        private bool PreProcessWndProc(ref Message m)
        {
            return true;
        }
        protected override bool ProcessDialogKey(Keys keyData)
        {
            if (keyData == Keys.Escape)
            {
                MetroShell metroTab = this.MetroShell;
                if (metroTab != null)
                {
                    MetroAppButton appButton = metroTab.GetApplicationButton() as MetroAppButton;
                    if (appButton != null)
                    {
                        if (appButton.ProcessEscapeKey(keyData))
                            return true;
                    }
                }
            }
            return base.ProcessDialogKey(keyData);
        }
        /// 
        /// This property is not to be used with MetroForm.
        /// 
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        public new FormBorderStyle FormBorderStyle
        {
            get { return base.FormBorderStyle; }
            set { base.FormBorderStyle = value; }
        }
        private Thickness _FormResizeBorder = new Thickness(5);
        /// 
        /// Gets or sets the size of the border on the edges of the form that when mouse is over allow for form resizing.
        /// 
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public Thickness FormResizeBorder
        {
            get { return _FormResizeBorder; }
            set { _FormResizeBorder = value; }
        }
        private void UpdateMetroSystemCaptionItem()
        {
            SystemCaptionItem captionItem = GetSystemCaptionItem();
            if (captionItem != null)
            {
                captionItem.MinimizeVisible = this.MinimizeBox;
                captionItem.RestoreMaximizeVisible = this.MaximizeBox;
                captionItem.CloseVisible = this.CloseBoxVisible;
                captionItem.HelpVisible = this.HelpButton;
                if (!this.MaximizeBox && !this.MinimizeBox && !this.CloseBoxVisible)
                    captionItem.Visible = false;
                else
                    captionItem.Visible = true;
                if (_MetroTab != null)
                    _MetroTab.RecalcLayout();
            }
        }
        private SystemCaptionItem GetSystemCaptionItem()
        {
            if (_MetroTab != null)
            {
                return _MetroTab.MetroTabStrip.SystemCaptionItem;
            }
            return null;
        }
        private bool _CloseBoxVisible = true;
        /// 
        /// Indicates whether Close button in top-right corner of the form is visible.
        /// 
        [DefaultValue(true), Category("Appearance"), Description("Indicates whether Close button in top-right corner of the form is visible.")]
        public bool CloseBoxVisible
        {
            get { return _CloseBoxVisible; }
            set { _CloseBoxVisible = value; UpdateMetroSystemCaptionItem(); }
        }
        /// 
        /// This property cannot be used on MetroAppForm
        /// 
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public override bool AutoScroll
        {
            get
            {
                return base.AutoScroll;
            }
            set
            {
                if (value) value = false;
                base.AutoScroll = value;
            }
        }
        /// 
        /// This property cannot be used on MetroAppForm
        /// 
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public override Point AutoScrollOffset
        {
            get
            {
                return base.AutoScrollOffset;
            }
            set
            {
                base.AutoScrollOffset = value;
            }
        }
        /// 
        /// This property cannot be used on MetroAppForm
        /// 
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public new Size AutoScrollMargin
        {
            get
            {
                return base.AutoScrollMargin;
            }
            set
            {
                base.AutoScrollMargin = value;
            }
        }
        /// 
        /// This property cannot be used on MetroAppForm
        /// 
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public new Size AutoScrollMinSize
        {
            get
            {
                return base.AutoScrollMinSize;
            }
            set
            {
                base.AutoScrollMinSize = value;
            }
        }
 
 
        #endregion
        #region System Menu Handling
        private ContextMenuBar _ContextMenuBar = null;
        internal void ShowSystemWindowMenu(Point p)
        {
            if (this.DesignMode) return;
            CreateContextMenuBar();
            // Update items enabled state
            ButtonItem sysMenu = ((ButtonItem)_ContextMenuBar.Items[SysMenu]);
            sysMenu.SubItems[SysMenuRestore].Enabled = this.WindowState != FormWindowState.Normal;
            sysMenu.SubItems[SysMenuMove].Enabled = this.WindowState == FormWindowState.Normal;
            sysMenu.SubItems[SysMenuSize].Enabled = this.WindowState == FormWindowState.Normal && this.Sizable;
            sysMenu.SubItems[SysMenuMinimize].Enabled = this.WindowState != FormWindowState.Minimized && this.MinimizeBox; ;
            sysMenu.SubItems[SysMenuMaximize].Enabled = this.WindowState != FormWindowState.Maximized && this.Sizable && this.MaximizeBox; ;
            sysMenu.SubItems[SysMenuClose].Enabled = true;
            sysMenu.Popup(p);
        }
        internal void ShowSystemWindowMenu()
        {
            ShowSystemWindowMenu(Control.MousePosition);
        }
        private string GetLocalizedString(string key)
        {
            string text = "";
            if (key == LocalizationKeys.FormSystemMenuRestore)
                text = _SystemMenuRestore;
            else if (key == LocalizationKeys.FormSystemMenuMove)
                text = _SystemMenuMove;
            else if (key == LocalizationKeys.FormSystemMenuSize)
                text = _SystemMenuSize;
            else if (key == LocalizationKeys.FormSystemMenuMinimize)
                text = _SystemMenuMinimize;
            else if (key == LocalizationKeys.FormSystemMenuMaximize)
                text = _SystemMenuMaximize;
            else if (key == LocalizationKeys.FormSystemMenuClose)
                text = _SystemMenuClose;
            return LocalizationManager.GetLocalizedString(key, text);
        }
        private void CreateContextMenuBar()
        {
            if (_ContextMenuBar != null || this.DesignMode) return;
            _ContextMenuBar = new ContextMenuBar();
            _ContextMenuBar.Style = eDotNetBarStyle.StyleManagerControlled;
            this.Controls.Add(_ContextMenuBar);
            ButtonItem sysMenu = new ButtonItem(SysMenu);
            _ContextMenuBar.Items.Add(sysMenu);
            ButtonItem sysItem = new ButtonItem(SysMenuRestore, GetLocalizedString(LocalizationKeys.FormSystemMenuRestore));
            sysItem.Image = BarFunctions.LoadBitmap("SystemImages.WinRestore.png");
            sysItem.Click += new EventHandler(SysItemClick);
            sysMenu.SubItems.Add(sysItem);
            sysItem = new ButtonItem(SysMenuMove, GetLocalizedString(LocalizationKeys.FormSystemMenuMove));
            sysItem.Click += new EventHandler(SysItemClick);
            sysMenu.SubItems.Add(sysItem);
            sysItem = new ButtonItem(SysMenuSize, GetLocalizedString(LocalizationKeys.FormSystemMenuSize));
            sysItem.Click += new EventHandler(SysItemClick);
            sysMenu.SubItems.Add(sysItem);
            sysItem = new ButtonItem(SysMenuMinimize, GetLocalizedString(LocalizationKeys.FormSystemMenuMinimize));
            sysItem.Click += new EventHandler(SysItemClick);
            sysItem.Image = BarFunctions.LoadBitmap("SystemImages.WinMin.png");
            sysMenu.SubItems.Add(sysItem);
            sysItem = new ButtonItem(SysMenuMaximize, GetLocalizedString(LocalizationKeys.FormSystemMenuMaximize));
            sysItem.Click += new EventHandler(SysItemClick);
            sysItem.Image = BarFunctions.LoadBitmap("SystemImages.WinMax.png");
            sysMenu.SubItems.Add(sysItem);
            sysItem = new ButtonItem(SysMenuClose, GetLocalizedString(LocalizationKeys.FormSystemMenuClose));
            sysItem.Click += new EventHandler(SysItemClick);
            sysItem.Image = BarFunctions.LoadBitmap("SystemImages.WinClose.png");
            sysItem.BeginGroup = true;
            sysItem.FontBold = true;
            sysItem.HotFontBold = true;
            sysItem.Shortcuts.Add(eShortcut.CtrlF4);
            sysMenu.SubItems.Add(sysItem);
        }
        void SysItemClick(object sender, EventArgs e)
        {
            BaseItem item = sender as BaseItem;
            if (item == null) return;
            if (item.Name == SysMenuRestore)
                NativeFunctions.PostMessage(this.Handle, NativeFunctions.WM_SYSCOMMAND, NativeFunctions.SC_RESTORE, 0);
            else if (item.Name == SysMenuMove)
                NativeFunctions.PostMessage(this.Handle, NativeFunctions.WM_SYSCOMMAND, NativeFunctions.SC_MOVE, 0);
            else if (item.Name == SysMenuSize)
                NativeFunctions.PostMessage(this.Handle, NativeFunctions.WM_SYSCOMMAND, NativeFunctions.SC_SIZE, 0);
            else if (item.Name == SysMenuMinimize)
                NativeFunctions.PostMessage(this.Handle, NativeFunctions.WM_SYSCOMMAND, NativeFunctions.SC_MINIMIZE, 0);
            else if (item.Name == SysMenuMaximize)
                NativeFunctions.PostMessage(this.Handle, NativeFunctions.WM_SYSCOMMAND, NativeFunctions.SC_MAXIMIZE, 0);
            else if (item.Name == SysMenuClose)
                NativeFunctions.PostMessage(this.Handle, NativeFunctions.WM_SYSCOMMAND, NativeFunctions.SC_CLOSE, 0);
        }
        private string _SystemMenuRestore = "Restore";
        /// 
        /// Gets or sets text for form system menu Restore item.
        /// 
        [DefaultValue("Restore"), Description("Indicates text for form system menu Restore item."), Localizable(true), Category("System Menu")]
        public string SystemMenuRestore
        {
            get { return _SystemMenuRestore; }
            set { _SystemMenuRestore = value; }
        }
        private string _SystemMenuMove = "Move";
        /// 
        /// Gets or sets text for form system menu Move item.
        /// 
        [DefaultValue("Move"), Description("Indicates text for form system menu Move item."), Localizable(true), Category("System Menu")]
        public string SystemMenuMove
        {
            get { return _SystemMenuMove; }
            set { _SystemMenuMove = value; }
        }
        private string _SystemMenuSize = "Size";
        /// 
        /// Gets or sets text for form system menu Size item.
        /// 
        [DefaultValue("Size"), Description("Indicates text for form system menu Size item."), Localizable(true), Category("System Menu")]
        public string SystemMenuSize
        {
            get { return _SystemMenuSize; }
            set { _SystemMenuSize = value; }
        }
        private string _SystemMenuMinimize = "Minimize";
        /// 
        /// Gets or sets text for form system menu Minimize item.
        /// 
        [DefaultValue("Minimize"), Description("Indicates text for form system menu Minimize item."), Localizable(true), Category("System Menu")]
        public string SystemMenuMinimize
        {
            get { return _SystemMenuMinimize; }
            set { _SystemMenuMinimize = value; }
        }
        private string _SystemMenuMaximize = "Maximize";
        /// 
        /// Gets or sets text for form system menu Maximize item.
        /// 
        [DefaultValue("Maximize"), Description("Indicates text for form system menu Maximize item."), Localizable(true), Category("System Menu")]
        public string SystemMenuMaximize
        {
            get { return _SystemMenuMaximize; }
            set { _SystemMenuMaximize = value; }
        }
        private string _SystemMenuClose = "Close";
        /// 
        /// Gets or sets text for form system menu Close item.
        /// 
        [DefaultValue("Close"), Description("Indicates text for form system menu Close item."), Localizable(true), Category("System Menu")]
        public string SystemMenuClose
        {
            get { return _SystemMenuClose; }
            set { _SystemMenuClose = value; }
        }
        #endregion
    }
    #region BorderOverlay
    internal class BorderOverlay : Control
    {
        /// 
        /// Initializes a new instance of the BorderOverlay class.
        /// 
        public BorderOverlay()
        {
            this.SetStyle(ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint | ControlStyles.Opaque |
                ControlStyles.ResizeRedraw | ControlStyles.DoubleBuffer | ControlStyles.Selectable, true);
        }
        protected override void OnPaint(PaintEventArgs e)
        {
            MetroRender.Paint(this, e);
            base.OnPaint(e);
        }
        protected override void WndProc(ref Message m)
        {
            if (m.Msg == (int)WinApi.WindowsMessages.WM_NCHITTEST)
            {
                m.Result = new IntPtr((int)WinApi.WindowHitTestRegions.TransparentOrCovered);
                return;
            }
            base.WndProc(ref m);
        }
    }
    #endregion
    #region PrepareModalPanelBounds Event
    /// 
    /// Delegate for PrepareModalPanelBounds event.
    /// 
    /// 
    /// 
    public delegate void ModalPanelBoundsEventHandler(object sender, ModalPanelBoundsEventArgs e);
    /// 
    /// Provides data for PrepareModalPanelBounds event.
    /// 
    public class ModalPanelBoundsEventArgs : EventArgs
    {
        /// 
        /// Gets or sets the bounds modal panel will occupy when shown.
        /// 
        public Rectangle ModalPanelBounds = Rectangle.Empty;
        /// 
        /// Initializes a new instance of the ModalPanelBoundsEventArgs class.
        /// 
        /// 
        public ModalPanelBoundsEventArgs(Rectangle modalPanelBounds)
        {
            ModalPanelBounds = modalPanelBounds;
        }
    }
    #endregion
}