using Apewer.Internals.Interop; using System; using System.Collections.Generic; using System.Drawing; using System.IO; using System.Runtime.InteropServices; using System.Security; using System.Reflection; using System.Diagnostics; #if NETFX || NETCORE using Microsoft.Win32; using System.Drawing.Drawing2D; using System.Drawing.Imaging; using System.Drawing.Text; using System.Windows.Forms; #endif using static Apewer.Internals.Interop.SHCore; namespace Apewer.Surface { /// 窗体实用工具。 [SecuritySafeCritical] public static class FormsUtility { /// 线程锁。 public static object ThreadLocker = new object(); /// 已使用系统 DPI 设置。 public static bool UsedSystemDPI { get; private set; } internal static Nullable DpiScale { get; set; } #if NETFX || NETCORE /// 窗体启动初始化。 [STAThread] public static void StartInitialization(bool useSystemDPI = false) { Control.CheckForIllegalCrossThreadCalls = false; Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); #if NETCORE Application.SetHighDpiMode(HighDpiMode.SystemAware); #endif // Application.SetCompatibleTextRenderingDefault(true); if (useSystemDPI) UseSystemDPI(); } /// 使用系统的 DPI 设置。 public static void UseSystemDPI() { if (UsedSystemDPI) return; UsedSystemDPI = true; #if NETCORE Application.SetHighDpiMode(HighDpiMode.PerMonitorV2); #else SetProcessDpiAwareness(PROCESS_DPI_AWARENESS.Process_System_DPI_Aware); Marshal.GetLastWin32Error(); PROCESS_DPI_AWARENESS awareness; GetProcessDpiAwareness(Process.GetCurrentProcess().Handle, out awareness); Marshal.GetLastWin32Error(); #endif } /// 禁用跨线程调用检查。 public static void CrossThread() { Control.CheckForIllegalCrossThreadCalls = false; } #endif #region 线程 /// 在拥有此控件的基础窗口句柄的线程上执行指定的委托。 public static void Invoke(this Control control, Action action) { if (control == null) throw new ArgumentNullException(nameof(control)); if (action == null) throw new ArgumentNullException(nameof(action)); // control.Invoke(action as Delegate); control.Invoke(new Action(delegate () { action.Invoke(); })); } /// 在创建控件的基础句柄所在线程上异步执行指定委托。 /// public static IAsyncResult BeginInvoke(this Control control, Action action) { if (control == null) throw new ArgumentNullException(nameof(control)); if (action == null) throw new ArgumentNullException(nameof(action)); // control.BeginInvoke(action as Delegate); return control.BeginInvoke(new Action(delegate () { action.Invoke(); })); } /// 控件属于当前线程。 /// public static bool OnCurrentThread(Control control) { if (control == null) throw new ArgumentNullException(nameof(control)); var controlThreadId = User32.GetWindowThreadProcessId(new HandleRef(control, control.Handle), out int _); var currentThreadId = Kernel32.GetCurrentThreadId(); return controlThreadId == currentThreadId; } #endregion #region 颜色。 /// 获取所有可枚举的颜色。 public static Color[] EnumerableColor { get { var list = new List(); list.Add(Color.AliceBlue); list.Add(Color.AntiqueWhite); list.Add(Color.Aqua); list.Add(Color.Aquamarine); list.Add(Color.Azure); list.Add(Color.Beige); list.Add(Color.Bisque); list.Add(Color.Black); list.Add(Color.BlanchedAlmond); list.Add(Color.Blue); list.Add(Color.BlueViolet); list.Add(Color.Brown); list.Add(Color.BurlyWood); list.Add(Color.CadetBlue); list.Add(Color.Chartreuse); list.Add(Color.Chocolate); list.Add(Color.Coral); list.Add(Color.CornflowerBlue); list.Add(Color.Cornsilk); list.Add(Color.Crimson); list.Add(Color.Cyan); list.Add(Color.DarkBlue); list.Add(Color.DarkCyan); list.Add(Color.DarkGoldenrod); list.Add(Color.DarkGray); list.Add(Color.DarkGreen); list.Add(Color.DarkKhaki); list.Add(Color.DarkMagenta); list.Add(Color.DarkOliveGreen); list.Add(Color.DarkOrange); list.Add(Color.DarkOrchid); list.Add(Color.DarkRed); list.Add(Color.DarkSalmon); list.Add(Color.DarkSeaGreen); list.Add(Color.DarkSlateBlue); list.Add(Color.DarkSlateGray); list.Add(Color.DarkTurquoise); list.Add(Color.DarkViolet); list.Add(Color.DeepPink); list.Add(Color.DeepSkyBlue); list.Add(Color.DimGray); list.Add(Color.DodgerBlue); list.Add(Color.Firebrick); list.Add(Color.FloralWhite); list.Add(Color.ForestGreen); list.Add(Color.Fuchsia); list.Add(Color.Gainsboro); list.Add(Color.GhostWhite); list.Add(Color.Gold); list.Add(Color.Goldenrod); list.Add(Color.Gray); list.Add(Color.Green); list.Add(Color.GreenYellow); list.Add(Color.Honeydew); list.Add(Color.HotPink); list.Add(Color.IndianRed); list.Add(Color.Indigo); list.Add(Color.Ivory); list.Add(Color.Khaki); list.Add(Color.Lavender); list.Add(Color.LavenderBlush); list.Add(Color.LawnGreen); list.Add(Color.LemonChiffon); list.Add(Color.LightBlue); list.Add(Color.LightCoral); list.Add(Color.LightCyan); list.Add(Color.LightGoldenrodYellow); list.Add(Color.LightGray); list.Add(Color.LightGreen); list.Add(Color.LightPink); list.Add(Color.LightSalmon); list.Add(Color.LightSeaGreen); list.Add(Color.LightSkyBlue); list.Add(Color.LightSlateGray); list.Add(Color.LightSteelBlue); list.Add(Color.LightYellow); list.Add(Color.Lime); list.Add(Color.LimeGreen); list.Add(Color.Linen); list.Add(Color.Magenta); list.Add(Color.Maroon); list.Add(Color.MediumAquamarine); list.Add(Color.MediumBlue); list.Add(Color.MediumOrchid); list.Add(Color.MediumPurple); list.Add(Color.MediumSeaGreen); list.Add(Color.MediumSlateBlue); list.Add(Color.MediumSpringGreen); list.Add(Color.MediumTurquoise); list.Add(Color.MediumVioletRed); list.Add(Color.MidnightBlue); list.Add(Color.MintCream); list.Add(Color.MistyRose); list.Add(Color.Moccasin); list.Add(Color.NavajoWhite); list.Add(Color.Navy); list.Add(Color.OldLace); list.Add(Color.Olive); list.Add(Color.OliveDrab); list.Add(Color.Orange); list.Add(Color.OrangeRed); list.Add(Color.Orchid); list.Add(Color.PaleGoldenrod); list.Add(Color.PaleGreen); list.Add(Color.PaleTurquoise); list.Add(Color.PaleVioletRed); list.Add(Color.PapayaWhip); list.Add(Color.PeachPuff); list.Add(Color.Peru); list.Add(Color.Pink); list.Add(Color.Plum); list.Add(Color.PowderBlue); list.Add(Color.Purple); list.Add(Color.Red); list.Add(Color.RosyBrown); list.Add(Color.RoyalBlue); list.Add(Color.SaddleBrown); list.Add(Color.Salmon); list.Add(Color.SandyBrown); list.Add(Color.SeaGreen); list.Add(Color.SeaShell); list.Add(Color.Sienna); list.Add(Color.Silver); list.Add(Color.SkyBlue); list.Add(Color.SlateBlue); list.Add(Color.SlateGray); list.Add(Color.Snow); list.Add(Color.SpringGreen); list.Add(Color.SteelBlue); list.Add(Color.Tan); list.Add(Color.Teal); list.Add(Color.Thistle); list.Add(Color.Tomato); //list.Add(Color.Transparent); list.Add(Color.Turquoise); list.Add(Color.Violet); list.Add(Color.Wheat); list.Add(Color.White); list.Add(Color.WhiteSmoke); list.Add(Color.Yellow); list.Add(Color.YellowGreen); return list.ToArray(); } } /// 用于填充背景色。 public static Color GraceWall { get { return Color.FromArgb(0xff, 0xf7, 0xf7, 0xf7); } } /// 用于控件边框。 public static Color GraceBorder { get { return Color.FromArgb(0xff, 0xdf, 0xdf, 0xdf); } } /// 用于无效的文本、备注文本。 public static Color GraceLocked { get { return Color.FromArgb(0xff, 0x7f, 0x7f, 0x7f); } } /// 用于次级文本。 public static Color GraceMinor { get { return Color.FromArgb(0xff, 0x3f, 0x3f, 0x3f); } } /// 用于焦点状态的控件边框。 public static Color GraceSilver { get { return Color.FromArgb(0xff, 0xbf, 0xbf, 0xbf); } } /// 系统定义的颜色。 public static Color Transparent { get { return Color.Transparent; } } /// 系统定义的颜色。 public static Color Black { get { return Color.Black; } } /// 系统定义的颜色。 public static Color White { get { return Color.White; } } /// 系统定义的颜色。 public static Color Gray { get { return Color.Gray; } } /// 系统定义的颜色。 public static Color DarkGray { get { return Color.DarkGray; } } /// 系统定义的颜色。 public static Color LightGray { get { return Color.LightGray; } } /// 系统定义的颜色。 public static Color Red { get { return Color.Red; } } /// 系统定义的颜色。 public static Color Green { get { return Color.Green; } } /// 系统定义的颜色。 public static Color Blue { get { return Color.Blue; } } /// 系统定义的颜色。 public static Color Orange { get { return Color.DarkOrange; } } /// 系统定义的颜色。 public static Color Purple { get { return Color.Purple; } } /// 随机主题色。 public static Color RandomColor { get { var colors = EnumerableColor; return colors[NumberUtility.Random(colors.Length - 1)]; } } /// 计算 Alpha 合成颜色(基色),基色均需计算。 /// 前景色 Alpha 值。 /// 背景色(基色)。 /// 前景色(基色)。 /// 颜色深度,最大值。 /// 合成后的颜色(基色)。 public static int MixAlpha(int alpha, int fore, int back, int depth = 255) { int b = back, f = fore; if (b > depth) b = depth; if (b < 0) b = 0; if (f > depth) f = depth; if (f < 0) f = 0; int v = fore * alpha / depth + back * (depth - alpha) / depth; if (v > depth) v = depth; if (v < 0) v = 0; return v; } /// 按 Alpha 混合不透明的颜色。 /// 背景色。 /// 前景色。 /// 前景 Alpha 值。 /// 混合后的颜色。 public static Color MixAlpha(Color backColor, Color foreColor, int foreAlpha) { var r = MixAlpha(backColor.R, foreColor.R, foreAlpha); var g = MixAlpha(backColor.G, foreColor.G, foreAlpha); var b = MixAlpha(backColor.B, foreColor.B, foreAlpha); var a = MixAlpha(backColor.A, foreColor.A, foreAlpha); return Color.FromArgb(a, r, g, b); } #endregion #region 屏幕。 #if NETFX || NETCORE /// 获取屏幕的截图。 public static Bitmap[] ScreenShot() { var list = new List(); var all = Screen.AllScreens; foreach (var screen in all) { int vw = screen.Bounds.Width; int vh = screen.Bounds.Height; int vd = screen.BitsPerPixel; Bitmap b = new Bitmap(vw, vh, PixelFormat.Format32bppArgb); Graphics g = Graphics.FromImage(b); g.CopyFromScreen(0, 0, 0, 0, new System.Drawing.Size(vw, vh)); g.Dispose(); list.Add(b); } return list.ToArray(); } /// 获取指定屏幕的截图。 /// 屏幕号。 internal static Bitmap ScreenShot(int screen) { var a = Screen.AllScreens; if ((a.Length > 0) && (screen >= 0) && (screen < a.Length)) { try { int w = a[screen].Bounds.Width; int h = a[screen].Bounds.Height; int d = a[screen].BitsPerPixel; Bitmap b = new Bitmap(w, h, PixelFormat.Format32bppArgb); Graphics g = Graphics.FromImage(b); g.CopyFromScreen(0, 0, 0, 0, new System.Drawing.Size(w, h)); g.Dispose(); return b; } catch { } } return new Bitmap(0, 0, PixelFormat.Format32bppArgb); } /// 获取指定屏幕的截图。 /// 屏幕,若为 Null 则选择主屏幕。 internal static Bitmap ScreenShot(Screen screen) { if (screen == null) { try { int w = Screen.PrimaryScreen.Bounds.Width; int h = Screen.PrimaryScreen.Bounds.Height; int d = Screen.PrimaryScreen.BitsPerPixel; Bitmap b = new Bitmap(w, h, PixelFormat.Format32bppArgb); Graphics g = Graphics.FromImage(b); g.CopyFromScreen(0, 0, 0, 0, new System.Drawing.Size(w, h)); g.Dispose(); return b; } catch { } } return new Bitmap(0, 0, PixelFormat.Format32bppArgb); } #endif #endregion #region Aero /// 获取 DWM 的 Composition 启用状态。 public static bool DwmIsCompositionEnabled { get => DwmApi.DwmIsCompositionEnabled(); } #endregion #region 窗体。 #if NETFX || NETCORE /// 移动窗体。 public static void MoveForm(Form form) { if (form != null) MoveForm(form.Handle); } /// 移动窗体。 public static void MoveForm(IntPtr form) { User32.ReleaseCapture(); User32.SendMessage(form, 0x112, new IntPtr(Constant.SC_MOVE + 2), new IntPtr(0)); } /// 启用鼠标穿透。 public static void MousePenetration(Form form) { if (form != null) MousePenetration(form.Handle); } /// 启用鼠标穿透。 public static void MousePenetration(IntPtr form) { int intExTemp = User32.GetWindowLong(form, Constant.GWL_EXSTYLE); int oldGWLEx = User32.SetWindowLong(form, Constant.GWL_EXSTYLE, Constant.WS_EX_TRANSPARENT | Constant.WS_EX_LAYERED); } /// 将窗体最大化,不覆盖任务栏。 /// 窗体。 public static void ToMaximum(Form form) { if (form != null) { var s = Screen.FromControl(form); var r = s.WorkingArea; if ((form.MaximumSize.Width < r.Width) || (form.MaximumSize.Height < r.Height)) { form.MaximumSize = r.Size; } form.Location = r.Location; form.Size = r.Size; } } /// 用指定图像绘制窗体,窗体与图像的大小必须一致。 /// 要绘制的窗体。 /// 要使用的图像。 public static void UpdateShadow(Form form, Image image) { if ((form != null) && (image != null)) { Bitmap vbitmap; if ((form.Width != image.Width) || (form.Height != image.Height)) { vbitmap = new Bitmap(image.GetThumbnailImage(form.Width, form.Height, null, IntPtr.Zero)); } else { vbitmap = new Bitmap(image); } var screendc = User32.GetDC(IntPtr.Zero); var location = new Internals.Interop.Point(form.Left, form.Top); var size = new Internals.Interop.Size(form.Width, form.Height); var compatibledc = Gdi32.CreateCompatibleDC(screendc); var handle = vbitmap.GetHbitmap(Color.FromArgb(0)); var oldbitmap = Gdi32.SelectObject(compatibledc, handle); var srcloc = new Internals.Interop.Point(0, 0); var blendfunction = new BlendFunction(); blendfunction.blendop = Constant.AC_SRC_OVER; blendfunction.sourceconstantalpha = byte.Parse("255"); blendfunction.alphaformat = Constant.AC_SRC_ALPHA; blendfunction.blendflags = 0; User32.UpdateLayeredWindow(form.Handle, screendc, ref location, ref size, compatibledc, ref srcloc, 0, ref blendfunction, Constant.ULW_ALPHA); if (handle != IntPtr.Zero) { Gdi32.SelectObject(compatibledc, oldbitmap); Gdi32.DeleteObject(handle); } User32.ReleaseDC(IntPtr.Zero, screendc); Gdi32.DeleteDC(compatibledc); } } /// 为窗体启用阴影。 /// 要启用阴影的窗体。 public static void EnableShadow(Form form) { if (form == null) return; int vformclass = User32.GetClassLong(form.Handle, Constant.GCL_STYLE); User32.SetClassLong(form.Handle, Constant.GCL_STYLE, vformclass | Constant.CS_DROPSHADOW); } /// 恢复任务栏中窗体标题的右键菜单。 public static void SetTaskMenu(Form form) { if (form != null) { var hwnd = form.Handle; var href = new HandleRef(form, hwnd); int windowLong = (User32.GetWindowLong(hwnd, -16)); User32.SetWindowLong(hwnd, -16, windowLong | Constant.WS_SYSMENU | Constant.WS_MINIMIZEBOX); } } #endif #endregion #region 控件。 #if NETFX || NETCORE /// 在主界面中移动控件,由目标控件取代当前控件,形成切换控件的动画。 /// 当前显示的控件。 /// 将要显示的目标控件。 public static void AnimateGoPanel(Control current, Control target) { AnimateGoPanel(current.Location, current.Size, 0, 10, current, target, true); } /// 在主界面中移动控件,由目标控件取代当前控件,形成切换控件的动画。 /// 当前显示的控件。 /// 将要显示的目标控件。 /// 向左移动。 public static void AnimateGoPanel(Control current, Control target, bool next) { AnimateGoPanel(current.Location, current.Size, 0, 10, current, target, next); } /// 在主界面中移动控件,由目标控件取代当前控件,形成切换控件的动画。 /// 控件左上角坐标。 /// 控件大小。 /// 当前控件和目标控件的间距,若值小于 0 则更正为 0 。 /// 移动的次数,若值小于 0 则更正为 20。 /// 当前显示的控件。 /// 将要显示的目标控件。 /// 向左移动。 public static void AnimateGoPanel(System.Drawing.Point point, System.Drawing.Size size, int span, int frame, Control current, Control target, bool next = true) { int s = (span < 0) ? span : 0; int step = (current.Width + s) / ((frame < 1) ? 20 : frame); int x = point.X; int y = point.Y; current.Size = size; target.Size = size; current.Location = point; if (next) { target.Location = new System.Drawing.Point(size.Width, point.Y); current.Visible = true; target.Visible = true; Application.DoEvents(); while (target.Left > x) { s = ((target.Left - x) < step) ? (target.Left - x) : step; target.Left -= s; current.Left -= s; Application.DoEvents(); System.Threading.Thread.Sleep(1); } } else { target.Location = new System.Drawing.Point(x - size.Width, x); current.Visible = true; target.Visible = true; Application.DoEvents(); while (target.Left < x) { s = ((x - target.Left) < step) ? x - target.Left : step; target.Left += s; current.Left += s; Application.DoEvents(); System.Threading.Thread.Sleep(1); } } current.Visible = false; } /// 设置窗体置顶。 public static void SetTopMost(IntPtr form, bool value = true) { if (form == null || form == IntPtr.Zero) return; User32.SetWindowPos(form, new IntPtr(value ? -1 : -2), 0, 0, 0, 0, 3); } /// 设置窗体置顶。 public static void SetTopMost(Form form, bool value = true) { if (form != null) SetTopMost(form.Handle, value); } /// 释放系统资源。 public static void Dispose(Control control) { if (control == null) return; if (control.InvokeRequired) { control.Invoke(() => Dispose(control)); return; } Dispose(control.Controls); if (control is Form form) { try { if (form.Visible) form.Close(); } catch { } } RuntimeUtility.Dispose(control); } /// 释放系统资源。 public static void Dispose(Control.ControlCollection controls) { if (controls == null) return; var count = controls.Count; if (count < 1) return; var children = new Control[count]; controls.CopyTo(children, 0); foreach (var child in children) { controls.Remove(child); Dispose(child); } } #endif #endregion #region 绘图。 #if NETFX || NETCORE /// 绘制内边框。 /// 源图像。 /// 边框颜色。 public static bool PaintBorder(ref Image image, Color border) { if (image != null) { var g = Graphics.FromImage(image); var p = new Pen(border); g.DrawRectangle(p, 0, 0, image.Width - 1, image.Height - 1); p.Dispose(); g.Dispose(); return true; } else return false; } /// 绘制内边框。 /// 源图像。 /// 边框颜色。 public static bool PaintBorder(ref Bitmap image, Color border) { if (image != null) { var g = Graphics.FromImage(image); var p = new Pen(border); g.DrawRectangle(p, 0, 0, image.Width - 1, image.Height - 1); p.Dispose(); g.Dispose(); return true; } else return false; } /// 绘制内边框。 /// 源图像。 /// 边框颜色。 /// 背景颜色。 public static bool PaintBorder(ref Image image, Color border, Color wall) { if (image != null) { var g = Graphics.FromImage(image); var p = new Pen(border); g.Clear(wall); g.DrawRectangle(p, 0, 0, image.Width - 1, image.Height - 1); p.Dispose(); g.Dispose(); return true; } else return false; } /// 建立带有圆角样式的路径。 /// 建立矩形路径的区域。 /// 圆角的大小。 /// 建立的路径。 public static GraphicsPath CreatePath(Rectangle rect, int radius = 0) { GraphicsPath path = new GraphicsPath(); int r = (radius < 0) ? 0 : radius; switch (r) { case 0: path.AddRectangle(rect); break; default: path.AddArc(rect.X, rect.Y, r, r, 180, 90); path.AddArc(rect.Right - r - 1, rect.Y, r, r, 270, 90); path.AddArc(rect.Right - r - 1, rect.Bottom - r - 1, r, r, 0, 90); path.AddArc(rect.X, rect.Bottom - r - 1, r, r, 90, 90); break; } path.CloseFigure(); return path; } /// /// /// /// /// public static GraphicsPath GetRadiusPath(PointF location, SizeF size, float radius) { var loc = location; var rds = Math.Abs(radius); var path = new GraphicsPath(); float x, y, r; r = rds * 2; // 左上角。 x = loc.X; y = loc.Y; path.AddArc(x, y, r, r, 180, 90); // 右上角。 x = loc.X + size.Width - rds * 2; y = loc.Y; path.AddArc(x, y, r, r, 270, 90); // 左下角。 x = loc.X; y = loc.Y + size.Height - rds * 2; path.AddArc(x, y, r, r, 0, 90); // 右下角。 x = loc.X + size.Width - rds * 2; y = loc.Y + size.Height - rds * 2; path.AddArc(x, y, r, r, 90, 90); // 边框直线:上、下、左、右。 path.AddLine((float)(loc.X + rds), (float)loc.Y, (float)(loc.X + size.Width - rds), (float)loc.Y); path.AddLine((float)(loc.X + rds), (float)(loc.Y + size.Height), (float)(loc.X + size.Width - rds), (float)(loc.Y + size.Height)); path.AddLine((float)loc.X, (float)(loc.Y + rds), (float)loc.X, (float)(loc.Y + size.Height - rds)); path.AddLine((float)(loc.X + size.Width), (float)(loc.Y + rds), (float)(loc.X + size.Width), (float)(loc.Y + size.Height - rds)); return path; } /// 获取指定文件中的图标总数。 public static int GetIconsCount(string path) { if (!File.Exists(path)) return 0; var count = User32.PrivateExtractIcons(path, 0, 0, 0, null, null, 0, 0); return count; } /// 获取指定文件中的图标。 public static Bitmap[] GetIconsBitmap(string path = null, int size = 256) { if (string.IsNullOrEmpty(path)) path = Application.ExecutablePath; if (!File.Exists(path)) return null; var count = User32.PrivateExtractIcons(path, 0, 0, 0, null, null, 0, 0); var ptrs = new IntPtr[count]; var ids = new int[count]; var succeed = User32.PrivateExtractIcons(path, 0, size, size, ptrs, ids, count, 0); var images = new Bitmap[count]; for (var i = 0; i < succeed; i++) { if (ptrs[i] == IntPtr.Zero) continue; using (var icon = Icon.FromHandle(ptrs[i])) { var bitmap = icon.ToBitmap(); images[i] = bitmap; } User32.DestroyIcon(ptrs[i]); } return images; } /// 从文件获取图标。 public static Icon GetExecutableIcon(string path) { try { return Icon.ExtractAssociatedIcon(path); } catch { return null; } } #endif #endregion #region 字体。 private const string FontYahei = "Microsoft Yahei"; private const string FontSimsun = "Simsun"; private const string GuiFontRegKey = @"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\GRE_Initialize"; private static string _fontname = ""; /// 存在微软雅黑字体。 public static bool MsyhExist { get => File.Exists("c:\\windows\\fonts\\msyh.ttc"); } /// 获取默认字体名称。 public static string DefaultFontName { get { if (!string.IsNullOrEmpty(_fontname)) return _fontname; try { if (File.Exists("c:\\windows\\fonts\\msyh.ttc")) return FontYahei; else return FontSimsun; } catch { return FontSimsun; } } } /// 获取默认字体名称。 public static string GuiFontName { get => Registry.GetValue(GuiFontRegKey, "GUIFont.Facename", "Arial") as string; } /// 获取默认字体大小。 public static float GuiFontSize { get => Convert.ToSingle(Registry.GetValue(GuiFontRegKey, "GUIFont.Height", 9F)); } #if NETFX || NETCORE /// 获取默认字体。 public static Font GuiFont { get => new Font(GuiFontName, GuiFontSize); } /// 获取默认字体。 public static Font DefaultFont { get { return new Font(DefaultFontName, 9); } } /// 获取大小为 9 的默认字体。 public static Font NewFont() { return new Font(DefaultFontName, 9); } /// 获取指定大小的默认字体。 public static Font NewFont(float size) { return new Font(DefaultFontName, size); } /// 获取指定大小的默认字体。 public static Font NewFont(float size, bool bold) { return new Font(DefaultFontName, size, bold ? FontStyle.Bold : FontStyle.Regular); } /// 从文件加载字体,并获取指定字体。 /// 文件路径。 /// 文件中的 Font Family 索引,默认取第一个(索引 0)。 /// 已存在的 Font Family,如果指定的索引处不存在 Font Family,则返回 NULL 值。 public static FontFamily LoadFont(string path, int index = 0) { if (index < 0) return null; if (string.IsNullOrEmpty(path)) return null; if (!File.Exists(path)) return null; try { var pfc = new PrivateFontCollection(); pfc.AddFontFile(path); var fs = pfc.Families; if (fs.Length > 0 && index < fs.Length) return fs[index]; } catch { } return null; } #if NET40 || NET461 /// public static List ListFileFont(string path) { try { var collection = System.Windows.Media.Fonts.GetFontFamilies(path); var list = new List(collection.Count); foreach (var item in collection) list.Add(item); return list; } catch { } return new List(); } /// public static List ListSystemFont() { var collection = System.Windows.Media.Fonts.SystemFontFamilies; var list = new List(collection.Count); foreach (var item in collection) list.Add(item); return list; } /// 枚举指定字体中的所有字符。 public static List EnumerateFontChars(IEnumerable typefaces) { var chars = new List(); if (typefaces != null) { foreach (var typeface in typefaces) { var subs = EnumerateFontChars(typeface); if (subs != null) chars.AddRange(subs); } } return chars; } /// 枚举指定字体中的所有字符。 public static char[] EnumerateFontChars(System.Windows.Media.Typeface typeface) { System.Windows.Media.GlyphTypeface glyph; var tried = typeface.TryGetGlyphTypeface(out glyph); if (glyph == null) return null; var map = glyph.CharacterToGlyphMap; var keys = map.Keys; var chars = new List(keys.Count); for (int i = 0; i < keys.Count; i++) { var index = System.Linq.Enumerable.ElementAt(keys, i); try { var c = Convert.ToChar(index); chars.Add(c); } catch { } } return chars.ToArray(); } #endif /// 获取已安装的字体。 public static List ListInstalledFonts() { var list = new List(); int ret = 0; // Win32 API 返回值,非零值均为异常。 // 初始化 FontCollection。 var collection = new Internals.FontCollection(); ret = GdiPlus.GdipNewInstalledFontCollection(out collection.NativePointer); if (ret != 0) return list; // 获取字体总数。 int found1 = 0; ret = GdiPlus.GdipGetFontCollectionFamilyCount(new HandleRef(collection, collection.NativePointer), out found1); if (ret != 0) return list; // 获取字体指针。 var ptrs = new IntPtr[found1]; int found2 = 0; ret = GdiPlus.GdipGetFontCollectionFamilyList(new HandleRef(collection, collection.NativePointer), found1, ptrs, out found2); if (ret != 0) return list; // 获取字体列表。 list.Capacity = found2; for (int i = 0; i < found2; i++) { IntPtr cloned; GdiPlus.GdipCloneFontFamily(new HandleRef(null, ptrs[i]), out cloned); try { var flags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.CreateInstance; var args = new object[] { cloned }; var instance = Activator.CreateInstance(typeof(FontFamily), flags, null, args, null, null); var item = instance as FontFamily; if (item != null) list.Add(item); } catch { } } list.Capacity = list.Count; return list; } private static bool GlyphExists(char c, Font font) { using (var dummy = Graphics.FromImage(new Bitmap(1, 1))) { IntPtr hdc = dummy.GetHdc(); var pgi = new ushort[1]; try { IntPtr hfont = font.ToHfont(); Gdi32.SelectObject(hdc, hfont); string str = c.ToString(); Gdi32.GetGlyphIndices(hdc, str, str.Length, pgi, Constant.GGI_MARK_NONEXISTING_GLYPHS); } catch { } dummy.ReleaseHdc(hdc); // 0xFFFF 表示字形不存在。 return (pgi[0] != 0xffff); } } #endif #endregion #region WndProc /// 允许鼠标调整窗体大小。此方法对 FormBorderStyle 为 None 的窗体生效。 /// 已处理事件。 /// /// public static bool AllowResizeForm(this Form form, ref Message m, int padding = 4) { if (form == null) throw new ArgumentNullException(nameof(form)); if (form.FormBorderStyle != FormBorderStyle.None) return false; if (padding < 0) throw new ArgumentOutOfRangeException(nameof(padding)); const int HT_LEFT = 10; const int HT_RIGHT = 11; const int HT_TOP = 12; const int HT_TOP_LEFT = 13; const int HT_TOP_RIGHT = 14; const int HT_BOTTOM = 15; const int HT_BOTTOM_LEFT = 16; const int HT_BOTTOM_RIGHT = 17; switch (m.Msg) { case 0x0084: var clientSize = form.ClientSize; var screenPoint = new System.Drawing.Point((int)m.LParam & 0xFFFF, (int)m.LParam >> 16 & 0xFFFF); var point = form.PointToClient(screenPoint); if (point.X <= padding) { if (point.Y <= padding) m.Result = (IntPtr)HT_TOP_LEFT; else if (point.Y >= clientSize.Height - padding) m.Result = (IntPtr)HT_BOTTOM_LEFT; else m.Result = (IntPtr)HT_LEFT; return true; } else if (point.X >= clientSize.Width - padding) { if (point.Y <= padding) m.Result = (IntPtr)HT_TOP_RIGHT; else if (point.Y >= clientSize.Height - padding) m.Result = (IntPtr)HT_BOTTOM_RIGHT; else m.Result = (IntPtr)HT_RIGHT; return true; } else if (point.Y <= padding) { m.Result = (IntPtr)HT_TOP; return true; } else if (point.Y >= clientSize.Height - padding) { m.Result = (IntPtr)HT_BOTTOM; return true; } break; } return false; } /// 允许移动窗体。左键点击时修改消息,认为鼠标点在非客户区(标题栏)。 /// 已处理事件。 /// public static bool AllowMoveForm(this Form form, ref Message m) { if (form == null) throw new ArgumentNullException(nameof(form)); switch (m.Msg) { // 左键点击时修改消息,认为鼠标点在非客户区(标题栏)。 case 0x0201: m.Msg = 0x00A1; m.LParam = IntPtr.Zero; m.WParam = new IntPtr(2); return true; } return false; } #endregion } }