// COPYRIGHT (C) Tom. ALL RIGHTS RESERVED. // THE AntdUI PROJECT IS AN WINFORM LIBRARY LICENSED UNDER THE Apache-2.0 License. // LICENSED UNDER THE Apache License, VERSION 2.0 (THE "License") // YOU MAY NOT USE THIS FILE EXCEPT IN COMPLIANCE WITH THE License. // YOU MAY OBTAIN A COPY OF THE LICENSE AT // // http://www.apache.org/licenses/LICENSE-2.0 // // UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING, SOFTWARE // DISTRIBUTED UNDER THE LICENSE IS DISTRIBUTED ON AN "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. // SEE THE LICENSE FOR THE SPECIFIC LANGUAGE GOVERNING PERMISSIONS AND // LIMITATIONS UNDER THE License. // GITEE: https://gitee.com/antdui/AntdUI // GITHUB: https://github.com/AntdUI/AntdUI // CSDN: https://blog.csdn.net/v_132 // QQ: 17379620 using System; using System.ComponentModel; using System.Drawing; using System.Windows.Forms; using Vanara.PInvoke; using static Vanara.PInvoke.User32; namespace AntdUI { public class BaseForm : Form { public BaseForm() { SetStyle( ControlStyles.UserPaint | ControlStyles.DoubleBuffer | ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer, true); UpdateStyles(); } public void SetCursor(bool val) { if (InvokeRequired) { Invoke(new Action(() => { SetCursor(val); })); return; } Cursor = val ? Cursors.Hand : DefaultCursor; } #region 主题 bool dark = false; /// /// 深色模式 /// [Description("深色模式"), Category("外观"), DefaultValue(false)] public bool Dark { get => dark; set { if (dark == value) return; dark = value; mode = dark ? TAMode.Dark : TAMode.Light; if (IsHandleCreated) DarkUI.UseImmersiveDarkMode(Handle, value); } } TAMode mode = TAMode.Auto; /// /// 色彩模式 /// [Description("色彩模式"), Category("外观"), DefaultValue(TAMode.Auto)] public TAMode Mode { get => mode; set { if (mode == value) return; mode = value; if (mode == TAMode.Dark || (mode == TAMode.Auto || Config.Mode == TMode.Dark)) Dark = true; else Dark = false; } } internal void SetTheme() { if (mode == TAMode.Dark || (mode == TAMode.Auto || Config.Mode == TMode.Dark)) DarkUI.UseImmersiveDarkMode(Handle, true); } #endregion #region 程序 /// /// 最小化 /// public virtual void Min() { WindowState = FormWindowState.Minimized; } public virtual bool IsMax { get => WindowState == FormWindowState.Maximized; } /// /// 最大化/还原 /// public virtual bool MaxRestore() { if (WindowState == FormWindowState.Maximized) { WindowState = FormWindowState.Normal; return false; } else { WindowState = FormWindowState.Maximized; return true; } } /// /// 最大化 /// public virtual void Max() { WindowState = FormWindowState.Maximized; } /// /// 全屏/还原 /// public virtual bool FullRestore() { if (WindowState == FormWindowState.Maximized) { NoFull(); return false; } else { Full(); return true; } } /// /// 全屏 /// public virtual void Full() { FormBorderStyle = FormBorderStyle.None; WindowState = FormWindowState.Maximized; } public virtual void NoFull() { FormBorderStyle = FormBorderStyle.Sizable; WindowState = FormWindowState.Normal; } #endregion public virtual bool AutoHandDpi { get; set; } = true; #region DPI public float Dpi() => Config.Dpi; protected override void OnLoad(EventArgs e) { if (AutoHandDpi) AutoDpi(Dpi(), this); base.OnLoad(e); } public void AutoDpi(Control control) { AutoDpi(Dpi(), control); } public void AutoDpi(float dpi, Control control) { Helper.DpiAuto(dpi, control); } #endregion #region 交互 #region 拖动窗口 /// /// 拖动窗口(鼠标按下) /// public virtual void DraggableMouseDown() { ReleaseCapture(); SendMessage(Handle, 0x0112, 61456 | 2, IntPtr.Zero); } #endregion #region 调整窗口大小 /// /// 调整窗口大小(鼠标移动) /// /// 可以调整 public virtual bool ResizableMouseMove() { if (WindowState == FormWindowState.Normal) { var retval = HitTest(PointToClient(MousePosition)); if (retval != HitTestValues.HTNOWHERE) { var mode = retval; if (mode != HitTestValues.HTCLIENT) { SetCursorHit(mode); return true; } } } return false; } /// /// 调整窗口大小(鼠标移动) /// /// 客户端坐标 /// 可以调整 public virtual bool ResizableMouseMove(Point point) { if (WindowState == FormWindowState.Normal) { var retval = HitTest(point); if (retval != HitTestValues.HTNOWHERE) { var mode = retval; if (mode != HitTestValues.HTCLIENT) { SetCursorHit(mode); return true; } } } return false; } internal bool is_resizable; /// /// 整窗口大小(鼠标按下) /// /// 可以调整 public virtual bool ResizableMouseDown() { Point pointScreen = MousePosition; var mode = HitTest(PointToClient(pointScreen)); if (mode != HitTestValues.HTCLIENT) { is_resizable = true; SetCursorHit(mode); ReleaseCapture(); SendMessage(Handle, (uint)WindowMessage.WM_NCLBUTTONDOWN, (IntPtr)mode, Macros.MAKELPARAM(pointScreen.X, pointScreen.Y)); is_resizable = false; return true; } return false; } #endregion #region 鼠标 internal HitTestValues HitTest(Point point) { float htSize = 8F * Config.Dpi, htSize2 = htSize * 2; GetWindowRect(Handle, out var lpRect); var rect = new Rectangle(Point.Empty, lpRect.Size); var hitTestValue = HitTestValues.HTCLIENT; var x = point.X; var y = point.Y; if (x < rect.Left + htSize2 && y < rect.Top + htSize2) { hitTestValue = HitTestValues.HTTOPLEFT; } else if (x >= rect.Left + htSize2 && x <= rect.Right - htSize2 && y <= rect.Top + htSize) { hitTestValue = HitTestValues.HTTOP; } else if (x > rect.Right - htSize2 && y <= rect.Top + htSize2) { hitTestValue = HitTestValues.HTTOPRIGHT; } else if (x <= rect.Left + htSize && y >= rect.Top + htSize2 && y <= rect.Bottom - htSize2) { hitTestValue = HitTestValues.HTLEFT; } else if (x >= rect.Right - htSize && y >= rect.Top * 2 + htSize && y <= rect.Bottom - htSize2) { hitTestValue = HitTestValues.HTRIGHT; } else if (x <= rect.Left + htSize2 && y >= rect.Bottom - htSize2) { hitTestValue = HitTestValues.HTBOTTOMLEFT; } else if (x > rect.Left + htSize2 && x < rect.Right - htSize2 && y >= rect.Bottom - htSize) { hitTestValue = HitTestValues.HTBOTTOM; } else if (x >= rect.Right - htSize2 && y >= rect.Bottom - htSize2) { hitTestValue = HitTestValues.HTBOTTOMRIGHT; } return hitTestValue; } internal void SetCursorHit(HitTestValues mode) { switch (mode) { case HitTestValues.HTTOP: case HitTestValues.HTBOTTOM: LoadCursors(32645); break; case HitTestValues.HTLEFT: case HitTestValues.HTRIGHT: LoadCursors(32644); break; case HitTestValues.HTTOPLEFT: case HitTestValues.HTBOTTOMRIGHT: LoadCursors(32642); break; case HitTestValues.HTTOPRIGHT: case HitTestValues.HTBOTTOMLEFT: LoadCursors(32643); break; } } internal void LoadCursors(int id) { var handle = LoadCursor(lpCursorName: Macros.MAKEINTRESOURCE(id)); var oldCursor = User32.SetCursor(handle); oldCursor.Close(); } #endregion #endregion } }