From 42fea95843db364a8b6402ff28f654ac22eb5b7a Mon Sep 17 00:00:00 2001 From: Tom <17379620@qq.com> Date: Sat, 21 Sep 2024 15:19:59 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=9B=81=20=E4=BF=AE=E5=A4=8D=20Window=20?= =?UTF-8?q?=E5=9D=90=E6=A0=87=E5=A4=A7=E5=B0=8F=20=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/AntdUI/Controls/Breadcrumb.cs | 9 +- src/AntdUI/Controls/Divider.cs | 14 +- src/AntdUI/Controls/Pagination.cs | 13 +- src/AntdUI/Controls/Progress.cs | 7 +- src/AntdUI/Controls/Segmented.cs | 7 +- src/AntdUI/Controls/Spin.cs | 3 +- src/AntdUI/Controls/Tabs/Tabs.cs | 6 +- src/AntdUI/Controls/Tree.cs | 8 +- src/AntdUI/Forms/BaseForm.cs | 2 +- .../Forms/LayeredWindow/LayeredFormDrawer.cs | 4 +- .../Forms/LayeredWindow/LayeredFormMask.cs | 2 +- .../LayeredWindow/LayeredFormMenuDown.cs | 3 +- .../Forms/LayeredWindow/LayeredFormModal.cs | 2 +- .../Forms/LayeredWindow/LayeredFormPopover.cs | 2 +- .../Forms/LayeredWindow/LayeredFormPreview.cs | 7 +- .../LayeredWindow/LayeredFormSelectDown.cs | 3 +- .../LayeredFormSelectMultiple.cs | 3 +- src/AntdUI/Forms/Lib/DarkUI.cs | 2 +- src/AntdUI/Forms/Window.cs | 67 +- src/AntdUI/Lib/Helper.cs | 2167 ----------------- src/AntdUI/Lib/Helper/Helper.DPI.cs | 174 ++ src/AntdUI/Lib/Helper/Helper.GDI.cs | 1044 ++++++++ src/AntdUI/Lib/Helper/Helper.Mask.cs | 84 + src/AntdUI/Lib/Helper/Helper.RECT.cs | 712 ++++++ src/AntdUI/Lib/Helper/Helper.cs | 232 ++ src/AntdUI/Lib/Helper/OS.cs | 76 + 26 files changed, 2379 insertions(+), 2274 deletions(-) delete mode 100644 src/AntdUI/Lib/Helper.cs create mode 100644 src/AntdUI/Lib/Helper/Helper.DPI.cs create mode 100644 src/AntdUI/Lib/Helper/Helper.GDI.cs create mode 100644 src/AntdUI/Lib/Helper/Helper.Mask.cs create mode 100644 src/AntdUI/Lib/Helper/Helper.RECT.cs create mode 100644 src/AntdUI/Lib/Helper/Helper.cs create mode 100644 src/AntdUI/Lib/Helper/OS.cs diff --git a/src/AntdUI/Controls/Breadcrumb.cs b/src/AntdUI/Controls/Breadcrumb.cs index 43875028..5a6b2075 100644 --- a/src/AntdUI/Controls/Breadcrumb.cs +++ b/src/AntdUI/Controls/Breadcrumb.cs @@ -218,6 +218,7 @@ namespace AntdUI #region 渲染 + readonly StringFormat s_f = Helper.SF_ALL(); protected override void OnPaint(PaintEventArgs e) { if (items == null || items.Count == 0) return; @@ -226,7 +227,7 @@ namespace AntdUI using (var brush = new SolidBrush(fore ?? Style.Db.TextSecondary)) using (var brush_active = new SolidBrush(ForeActive ?? Style.Db.Text)) { - foreach (var it in hs) g.DrawStr("/", Font, brush, it, Helper.stringFormatCenter); + foreach (var it in hs) g.DrawStr("/", Font, brush, it, s_f); for (int i = 0; i < items.Count; i++) { var it = items[i]; @@ -235,7 +236,7 @@ namespace AntdUI { //最后一个 PaintImg(g, it, brush_active.Color, it.IconSvg, it.Icon); - g.DrawStr(it.Text, Font, brush_active, it.RectText, Helper.stringFormatCenter); + g.DrawStr(it.Text, Font, brush_active, it.RectText, s_f); } else { @@ -249,12 +250,12 @@ namespace AntdUI } } PaintImg(g, it, brush_active.Color, it.IconSvg, it.Icon); - g.DrawStr(it.Text, Font, brush_active, it.RectText, Helper.stringFormatCenter); + g.DrawStr(it.Text, Font, brush_active, it.RectText, s_f); } else { PaintImg(g, it, brush.Color, it.IconSvg, it.Icon); - g.DrawStr(it.Text, Font, brush, it.RectText, Helper.stringFormatCenter); + g.DrawStr(it.Text, Font, brush, it.RectText, s_f); } } } diff --git a/src/AntdUI/Controls/Divider.cs b/src/AntdUI/Controls/Divider.cs index 35072946..8744f175 100644 --- a/src/AntdUI/Controls/Divider.cs +++ b/src/AntdUI/Controls/Divider.cs @@ -141,7 +141,7 @@ namespace AntdUI #endregion - StringFormat s_f = Helper.SF_Ellipsis(); + readonly StringFormat s_f_all = Helper.SF_ALL(), s_f = Helper.SF_Ellipsis(); protected override void OnPaint(PaintEventArgs e) { var _rect = ClientRectangle; @@ -155,7 +155,7 @@ namespace AntdUI if (Vertical) { var text_ = string.Join(Environment.NewLine, text.ToCharArray()); - var size = g.MeasureString(text_, Font, 0, Helper.stringFormatCenter).Size(); + var size = g.MeasureString(text_, Font, 0, s_f_all).Size(); int f_margin = (int)(rect.Height * orientationMargin), font_margin = (int)(size.Width * textPadding); float x = rect.X + (rect.Width - thickness) / 2F; @@ -212,13 +212,13 @@ namespace AntdUI var font_irect = new Rectangle(rect.X + f_margin + font_margin, rect.Y + (rect.Height - size.Height) / 2, size.Width, size.Height); g.FillRectangle(brush, new RectangleF(rect.X, y, f_margin, thickness)); g.FillRectangle(brush, new RectangleF(font_irect.Right + font_margin, y, rect.Width - size.Width - f_margin - font_margin * 2F, thickness)); - PaintText(g, text, font_irect, Helper.stringFormatCenter, Enabled); + PaintText(g, text, font_irect, s_f_all, Enabled); } else { var font_irect = new Rectangle(rect.X, rect.Y + (rect.Height - size.Height) / 2, size.Width, size.Height); g.FillRectangle(brush, new RectangleF(font_irect.Right + font_margin, y, rect.Width - size.Width - font_margin, thickness)); - PaintText(g, text, font_irect, Helper.stringFormatCenter, Enabled); + PaintText(g, text, font_irect, s_f_all, Enabled); } break; case TOrientation.Right: @@ -227,20 +227,20 @@ namespace AntdUI var font_irect = new Rectangle(rect.Right - size.Width - f_margin - font_margin, rect.Y + (rect.Height - size.Height) / 2, size.Width, size.Height); g.FillRectangle(brush, new RectangleF(rect.X, y, rect.Width - size.Width - f_margin - font_margin * 2F, thickness)); g.FillRectangle(brush, new RectangleF(font_irect.Right + font_margin, y, f_margin, thickness)); - PaintText(g, text, font_irect, Helper.stringFormatCenter, Enabled); + PaintText(g, text, font_irect, s_f_all, Enabled); } else { var font_irect = new Rectangle(rect.Right - size.Width, rect.Y + (rect.Height - size.Height) / 2, size.Width, size.Height); g.FillRectangle(brush, new RectangleF(rect.X, y, rect.Width - size.Width - font_margin, thickness)); - PaintText(g, text, font_irect, Helper.stringFormatCenter, Enabled); + PaintText(g, text, font_irect, s_f_all, Enabled); } break; default: float f_w = (rect.Width - size.Width) / 2 - f_margin - font_margin; g.FillRectangle(brush, new RectangleF(rect.X, y, f_w, thickness)); g.FillRectangle(brush, new RectangleF(rect.X + f_w + size.Width + (f_margin + font_margin) * 2F, y, f_w, thickness)); - PaintText(g, text, _rect, Helper.stringFormatCenter, Enabled); + PaintText(g, text, _rect, s_f_all, Enabled); break; } } diff --git a/src/AntdUI/Controls/Pagination.cs b/src/AntdUI/Controls/Pagination.cs index 28d9e514..2374c2cf 100644 --- a/src/AntdUI/Controls/Pagination.cs +++ b/src/AntdUI/Controls/Pagination.cs @@ -284,6 +284,7 @@ namespace AntdUI #region 渲染 + readonly StringFormat s_f = Helper.SF_NoWrap(); protected override void OnPaint(PaintEventArgs e) { if (buttons.Length < 2) return; @@ -327,7 +328,7 @@ namespace AntdUI using (var brush = new SolidBrush(fore)) { - if (showTotal != null) g.DrawStr(showTotal, Font, brush, rect_text, Helper.stringFormatCenter2); + if (showTotal != null) g.DrawStr(showTotal, Font, brush, rect_text, s_f); for (int i = 2; i < buttons.Length; i++) { var btn = buttons[i]; @@ -342,7 +343,7 @@ namespace AntdUI { using (var brush_prog = new SolidBrush(Style.Db.TextQuaternary)) { - g.DrawStr("•••", Font, brush_prog, btn.rect, Helper.stringFormatCenter2); + g.DrawStr("•••", Font, brush_prog, btn.rect, s_f); } } else @@ -357,7 +358,7 @@ namespace AntdUI } } } - g.DrawStr(btn.key, Font, brush, btn.rect, Helper.stringFormatCenter2); + g.DrawStr(btn.key, Font, brush, btn.rect, s_f); } } } @@ -383,13 +384,13 @@ namespace AntdUI using (var brush = new SolidBrush(Style.Db.TextQuaternary)) { - if (showTotal != null) g.DrawStr(showTotal, Font, brush, rect_text, Helper.stringFormatCenter2); + if (showTotal != null) g.DrawStr(showTotal, Font, brush, rect_text, s_f); for (int i = 2; i < buttons.Length; i++) { var btn = buttons[i]; if (btn.prog > 0) { - g.DrawStr("•••", Font, brush, btn.rect, Helper.stringFormatCenter2); + g.DrawStr("•••", Font, brush, btn.rect, s_f); } else { @@ -403,7 +404,7 @@ namespace AntdUI } } } - g.DrawStr(btn.key, Font, brush, btn.rect, Helper.stringFormatCenter2); + g.DrawStr(btn.key, Font, brush, btn.rect, s_f); } } } diff --git a/src/AntdUI/Controls/Progress.cs b/src/AntdUI/Controls/Progress.cs index 6b32e75d..3df20d11 100644 --- a/src/AntdUI/Controls/Progress.cs +++ b/src/AntdUI/Controls/Progress.cs @@ -472,8 +472,7 @@ namespace AntdUI #region 渲染 - StringFormat s_c = Helper.SF_ALL(); - StringFormat s_r = Helper.SF_ALL(lr: StringAlignment.Far); + readonly StringFormat s_c = Helper.SF_ALL(), s_r = Helper.SF_ALL(lr: StringAlignment.Far), s_l = Helper.SF_ALL(lr: StringAlignment.Near); protected override void OnPaint(PaintEventArgs e) { var rect_t = ClientRectangle; @@ -507,8 +506,8 @@ namespace AntdUI if (icon_rect.Width == 0 || icon_rect.Height == 0) return; using (var brush = new SolidBrush(fore ?? Style.Db.Text)) { - if (showText) g.DrawStr((_value_show * 100F).ToString("F" + ShowTextDot) + text, Font, brush, new RectangleF(text_rect.X + 8, text_rect.Y, text_rect.Width - 8, text_rect.Height), Helper.stringFormatLeft); - else g.DrawStr(text, Font, brush, new RectangleF(text_rect.X + 8, text_rect.Y, text_rect.Width - 8, text_rect.Height), Helper.stringFormatLeft); + if (showText) g.DrawStr((_value_show * 100F).ToString("F" + ShowTextDot) + text, Font, brush, new RectangleF(text_rect.X + 8, text_rect.Y, text_rect.Width - 8, text_rect.Height), s_l); + else g.DrawStr(text, Font, brush, new RectangleF(text_rect.X + 8, text_rect.Y, text_rect.Width - 8, text_rect.Height), s_l); } float w = radius * Config.Dpi; diff --git a/src/AntdUI/Controls/Segmented.cs b/src/AntdUI/Controls/Segmented.cs index dbacf6c8..9b7ad4e5 100644 --- a/src/AntdUI/Controls/Segmented.cs +++ b/src/AntdUI/Controls/Segmented.cs @@ -790,6 +790,7 @@ namespace AntdUI #region 渲染 + readonly StringFormat s_f = Helper.SF_ALL(); protected override void OnPaint(PaintEventArgs e) { if (items == null || items.Count == 0) return; @@ -903,7 +904,7 @@ namespace AntdUI using (var brush_active = new SolidBrush(enabled ? (foreactive ?? Style.Db.Text) : Style.Db.TextQuaternary)) { if (PaintImg(g, it, brush_active.Color, it.IconActiveSvg, it.IconActive)) PaintImg(g, it, brush_active.Color, it.IconSvg, it.Icon); - g.DrawStr(it.Text, Font, brush_active, it.RectText, Helper.stringFormatCenter); + g.DrawStr(it.Text, Font, brush_active, it.RectText, s_f); } } else @@ -913,13 +914,13 @@ namespace AntdUI using (var brush_active = new SolidBrush(ForeHover ?? Style.Db.HoverColor)) { PaintImg(g, it, brush_active.Color, it.IconSvg, it.Icon); - g.DrawStr(it.Text, Font, brush_active, it.RectText, Helper.stringFormatCenter); + g.DrawStr(it.Text, Font, brush_active, it.RectText, s_f); } } else { PaintImg(g, it, brush.Color, it.IconSvg, it.Icon); - g.DrawStr(it.Text, Font, brush, it.RectText, Helper.stringFormatCenter); + g.DrawStr(it.Text, Font, brush, it.RectText, s_f); } } } diff --git a/src/AntdUI/Controls/Spin.cs b/src/AntdUI/Controls/Spin.cs index 36fcd5f4..7adb4bf8 100644 --- a/src/AntdUI/Controls/Spin.cs +++ b/src/AntdUI/Controls/Spin.cs @@ -266,6 +266,7 @@ namespace AntdUI }, 10); } + readonly StringFormat s_f = Helper.SF_ALL(); public void Paint(Graphics g, Rectangle rect, string? text, Color color, Font? font, Control control) { if (prog_size == 0) prog_size = g.MeasureString(text ?? Config.NullText, font ?? control.Font).Height; @@ -279,7 +280,7 @@ namespace AntdUI rect_prog.Offset(0, -size2); using (var brush = new SolidBrush(control.ForeColor)) { - g.DrawStr(text, font ?? control.Font, brush, new RectangleF(rect.X, y, rect.Width, prog_size), Helper.stringFormatCenter); + g.DrawStr(text, font ?? control.Font, brush, new RectangleF(rect.X, y, rect.Width, prog_size), s_f); } } using (var brush = new Pen(color, size)) diff --git a/src/AntdUI/Controls/Tabs/Tabs.cs b/src/AntdUI/Controls/Tabs/Tabs.cs index 349587fc..72477a63 100644 --- a/src/AntdUI/Controls/Tabs/Tabs.cs +++ b/src/AntdUI/Controls/Tabs/Tabs.cs @@ -408,7 +408,7 @@ namespace AntdUI #region 渲染 - StringFormat s_c = Helper.SF_ALL(); + readonly StringFormat s_c = Helper.SF_ALL(), s_f = Helper.SF_NoWrap(); protected override void OnPaint(PaintEventArgs e) { if (items == null || items.Count == 0 || !_tabMenuVisible) return; @@ -455,7 +455,7 @@ namespace AntdUI g.DrawEllipse(pen, rect_badge); } } - g.DrawStr(page.Badge, font, brush_fore, rect_badge, Helper.stringFormatCenter2); + g.DrawStr(page.Badge, font, brush_fore, rect_badge, s_f); } else { @@ -472,7 +472,7 @@ namespace AntdUI } } } - g.DrawStr(page.Badge, font, brush_fore, rect_badge, Helper.stringFormatCenter2); + g.DrawStr(page.Badge, font, brush_fore, rect_badge, s_f); } } } diff --git a/src/AntdUI/Controls/Tree.cs b/src/AntdUI/Controls/Tree.cs index b0075564..25bb4bc2 100644 --- a/src/AntdUI/Controls/Tree.cs +++ b/src/AntdUI/Controls/Tree.cs @@ -510,7 +510,7 @@ namespace AntdUI } } - StringFormat sf_center = Helper.SF_Ellipsis(); + readonly StringFormat s_c = Helper.SF_Ellipsis(), s_l = Helper.SF_ALL(lr: StringAlignment.Near); void PaintItem(Graphics g, TreeItem item, SolidBrush fore, SolidBrush fore_active, SolidBrush hover, SolidBrush active, SolidBrush brushTextTertiary, float radius, int sx, int sy) { if (item.Select) @@ -684,11 +684,11 @@ namespace AntdUI color = item.Fore.Value; using (var brush = new SolidBrush(color)) { - g.DrawStr(item.Text, Font, brush, item.txt_rect, blockNode ? Helper.stringFormatLeft : sf_center); + g.DrawStr(item.Text, Font, brush, item.txt_rect, blockNode ? s_l : s_c); } } - else g.DrawStr(item.Text, Font, fore, item.txt_rect, blockNode ? Helper.stringFormatLeft : sf_center); - if (item.SubTitle != null) g.DrawStr(item.SubTitle, Font, brushTextTertiary, item.subtxt_rect, Helper.stringFormatLeft); + else g.DrawStr(item.Text, Font, fore, item.txt_rect, blockNode ? s_l : s_c); + if (item.SubTitle != null) g.DrawStr(item.SubTitle, Font, brushTextTertiary, item.subtxt_rect, s_l); if (item.Icon != null) g.DrawImage(item.Icon, item.ico_rect); else if (item.IconSvg != null) { diff --git a/src/AntdUI/Forms/BaseForm.cs b/src/AntdUI/Forms/BaseForm.cs index 8c5da4f2..aa21a65f 100644 --- a/src/AntdUI/Forms/BaseForm.cs +++ b/src/AntdUI/Forms/BaseForm.cs @@ -184,7 +184,7 @@ namespace AntdUI public void AutoDpi(float dpi, Control control) { - if (dpi != 1F) Helper.DpiAuto(dpi, control); + Helper.DpiAuto(dpi, control); } #endregion diff --git a/src/AntdUI/Forms/LayeredWindow/LayeredFormDrawer.cs b/src/AntdUI/Forms/LayeredWindow/LayeredFormDrawer.cs index 7a9b87c7..6835feca 100644 --- a/src/AntdUI/Forms/LayeredWindow/LayeredFormDrawer.cs +++ b/src/AntdUI/Forms/LayeredWindow/LayeredFormDrawer.cs @@ -50,7 +50,7 @@ namespace AntdUI padding = (int)Math.Round(config.Padding * Config.Dpi); Padding = new Padding(padding); - var version = Helper.OSVersion; + var version = OS.Version; if (version.Major >= 10 && version.Build > 22000) FrmRadius = 8; //Win11 if (config.Form is Window) { @@ -72,7 +72,7 @@ namespace AntdUI else { config.Content.Tag = config.Content.Size; - if (Config.Dpi != 1F) Helper.DpiAuto(Config.Dpi, config.Content); + Helper.DpiAuto(Config.Dpi, config.Content); } config.Content.Size = new Size(tempContent.Width, tempContent.Height); LoadContent(); diff --git a/src/AntdUI/Forms/LayeredWindow/LayeredFormMask.cs b/src/AntdUI/Forms/LayeredWindow/LayeredFormMask.cs index 46769eb0..43dd152e 100644 --- a/src/AntdUI/Forms/LayeredWindow/LayeredFormMask.cs +++ b/src/AntdUI/Forms/LayeredWindow/LayeredFormMask.cs @@ -34,7 +34,7 @@ namespace AntdUI if (form.WindowState != FormWindowState.Maximized) { if (form is BorderlessForm borderless) Radius = (int)(borderless.Radius * Config.Dpi); - else if (Helper.OSVersionWin11) Radius = (int)(8 * Config.Dpi); //Win11 + else if (OS.Win11) Radius = (int)(8 * Config.Dpi); //Win11 if (form is Window || form is FormNoBar) { //无边框处理 diff --git a/src/AntdUI/Forms/LayeredWindow/LayeredFormMenuDown.cs b/src/AntdUI/Forms/LayeredWindow/LayeredFormMenuDown.cs index 7ca6b8df..28c0b9dc 100644 --- a/src/AntdUI/Forms/LayeredWindow/LayeredFormMenuDown.cs +++ b/src/AntdUI/Forms/LayeredWindow/LayeredFormMenuDown.cs @@ -265,6 +265,7 @@ namespace AntdUI #endregion + readonly StringFormat s_f = Helper.SF_NoWrap(); public override Bitmap PrintBit() { var rect = TargetRectXY; @@ -302,7 +303,7 @@ namespace AntdUI { string emptytext = Localization.Provider?.GetLocalizedString("NoData") ?? "暂无数据"; using (var brush = new SolidBrush(Color.FromArgb(180, Style.Db.Text))) - { g.DrawStr(emptytext, Font, brush, rect_read, Helper.stringFormatCenter2); } + { g.DrawStr(emptytext, Font, brush, rect_read, s_f); } } else { diff --git a/src/AntdUI/Forms/LayeredWindow/LayeredFormModal.cs b/src/AntdUI/Forms/LayeredWindow/LayeredFormModal.cs index 03cd58cc..994091ba 100644 --- a/src/AntdUI/Forms/LayeredWindow/LayeredFormModal.cs +++ b/src/AntdUI/Forms/LayeredWindow/LayeredFormModal.cs @@ -161,7 +161,7 @@ namespace AntdUI if (config.Content is Control control) { w = (int)Math.Round(control.Width * dpi); - if (dpi != 1F) Helper.DpiAuto(dpi, control); + Helper.DpiAuto(dpi, control); wp = w - paddingx * 2; Controls.Add(control); control.Disposed += (a, b) => diff --git a/src/AntdUI/Forms/LayeredWindow/LayeredFormPopover.cs b/src/AntdUI/Forms/LayeredWindow/LayeredFormPopover.cs index ab3f64cc..098d2382 100644 --- a/src/AntdUI/Forms/LayeredWindow/LayeredFormPopover.cs +++ b/src/AntdUI/Forms/LayeredWindow/LayeredFormPopover.cs @@ -71,7 +71,7 @@ namespace AntdUI } } tempContent = new Bitmap(control.Width, control.Height); - if (Config.Dpi != 1F) Helper.DpiAuto(Config.Dpi, control); + Helper.DpiAuto(Config.Dpi, control); control.Size = new Size(tempContent.Width, tempContent.Height); control.DrawToBitmap(tempContent, new Rectangle(0, 0, tempContent.Width, tempContent.Height)); SetSize(w + padding2, h + padding2); diff --git a/src/AntdUI/Forms/LayeredWindow/LayeredFormPreview.cs b/src/AntdUI/Forms/LayeredWindow/LayeredFormPreview.cs index 8393dca2..2709d9d6 100644 --- a/src/AntdUI/Forms/LayeredWindow/LayeredFormPreview.cs +++ b/src/AntdUI/Forms/LayeredWindow/LayeredFormPreview.cs @@ -41,7 +41,7 @@ namespace AntdUI if (form.WindowState != FormWindowState.Maximized) { if (form is BorderlessForm borderless) Radius = (int)(borderless.Radius * Config.Dpi); - else if (Helper.OSVersionWin11) Radius = (int)(8 * Config.Dpi); //Win11 + else if (OS.Win11) Radius = (int)(8 * Config.Dpi); //Win11 if (form is Window || form is FormNoBar) { //无边框处理 @@ -313,6 +313,7 @@ namespace AntdUI #endregion + readonly StringFormat s_f = Helper.SF_NoWrap(); public override Bitmap PrintBit() { var original_bmp = new Bitmap(TargetRect.Width, TargetRect.Height); @@ -359,7 +360,7 @@ namespace AntdUI rect_loading.Offset(0, loading_size); using (var brush = new SolidBrush(Style.Db.PrimaryColor)) { - g.DrawString(LoadingProgressStr, Font, brush, rect_loading, Helper.stringFormatCenter2); + g.DrawString(LoadingProgressStr, Font, brush, rect_loading, s_f); } } } @@ -375,7 +376,7 @@ namespace AntdUI rect_loading.Offset(0, loading_size); using (var brush = new SolidBrush(Style.Db.ErrorColor)) { - g.DrawString(LoadingProgressStr, Font, brush, rect_loading, Helper.stringFormatCenter2); + g.DrawString(LoadingProgressStr, Font, brush, rect_loading, s_f); } } } diff --git a/src/AntdUI/Forms/LayeredWindow/LayeredFormSelectDown.cs b/src/AntdUI/Forms/LayeredWindow/LayeredFormSelectDown.cs index c0eafba4..dd006252 100644 --- a/src/AntdUI/Forms/LayeredWindow/LayeredFormSelectDown.cs +++ b/src/AntdUI/Forms/LayeredWindow/LayeredFormSelectDown.cs @@ -772,6 +772,7 @@ namespace AntdUI #endregion + readonly StringFormat s_f = Helper.SF_NoWrap(); public override Bitmap PrintBit() { var rect = TargetRectXY; @@ -791,7 +792,7 @@ namespace AntdUI { string emptytext = Localization.Provider?.GetLocalizedString("NoData") ?? "暂无数据"; using (var brush = new SolidBrush(Color.FromArgb(180, Style.Db.Text))) - { g.DrawStr(emptytext, Font, brush, rect_read, Helper.stringFormatCenter2); } + { g.DrawStr(emptytext, Font, brush, rect_read, s_f); } } else { diff --git a/src/AntdUI/Forms/LayeredWindow/LayeredFormSelectMultiple.cs b/src/AntdUI/Forms/LayeredWindow/LayeredFormSelectMultiple.cs index 271cea7b..887bb786 100644 --- a/src/AntdUI/Forms/LayeredWindow/LayeredFormSelectMultiple.cs +++ b/src/AntdUI/Forms/LayeredWindow/LayeredFormSelectMultiple.cs @@ -515,6 +515,7 @@ namespace AntdUI #endregion + readonly StringFormat s_f = Helper.SF_NoWrap(); public override Bitmap PrintBit() { var rect = TargetRectXY; @@ -534,7 +535,7 @@ namespace AntdUI { string emptytext = Localization.Provider?.GetLocalizedString("NoData") ?? "暂无数据"; using (var brush = new SolidBrush(Color.FromArgb(180, Style.Db.Text))) - { g.DrawStr(emptytext, Font, brush, rect_read, Helper.stringFormatCenter2); } + { g.DrawStr(emptytext, Font, brush, rect_read, s_f); } } else { diff --git a/src/AntdUI/Forms/Lib/DarkUI.cs b/src/AntdUI/Forms/Lib/DarkUI.cs index 9f91a869..4aebabac 100644 --- a/src/AntdUI/Forms/Lib/DarkUI.cs +++ b/src/AntdUI/Forms/Lib/DarkUI.cs @@ -44,7 +44,7 @@ namespace AntdUI static bool IsWindows10OrGreater(int build = -1) { - var os = Helper.OSVersion; + var os = OS.Version; return os.Major >= 10 && os.Build >= build; } } diff --git a/src/AntdUI/Forms/Window.cs b/src/AntdUI/Forms/Window.cs index 6e1acc4f..1415d004 100644 --- a/src/AntdUI/Forms/Window.cs +++ b/src/AntdUI/Forms/Window.cs @@ -17,10 +17,8 @@ // QQ: 17379620 using System; -using System.Collections.Specialized; using System.ComponentModel; using System.Drawing; -using System.Reflection; using System.Runtime.InteropServices; using System.Windows.Forms; using Vanara.PInvoke; @@ -91,6 +89,8 @@ namespace AntdUI SetWindowPos(handle, HWND.NULL, 0, 0, 0, 0, SetWindowPosFlags.SWP_NOZORDER | SetWindowPosFlags.SWP_NOOWNERZORDER | SetWindowPosFlags.SWP_NOMOVE | SetWindowPosFlags.SWP_NOSIZE | SetWindowPosFlags.SWP_FRAMECHANGED); DisableProcessWindowsGhosting(); HandMessage(); + DwmArea(); + if (sizeInit.HasValue) ClientSize = sizeInit.Value; } private void InvalidateNonclient() @@ -385,7 +385,6 @@ namespace AntdUI bool WmNCCalcSize(ref System.Windows.Forms.Message m) { if (FormBorderStyle == FormBorderStyle.None) return false; - if (ISZoomed()) { #if NET40 @@ -403,8 +402,10 @@ namespace AntdUI else return true; } + internal Size? sizeInit; bool WmNCActivate(ref System.Windows.Forms.Message m) { + if (sizeInit == null) sizeInit = ClientSize; if (m.HWnd == IntPtr.Zero) return false; if (IsIconic(m.HWnd)) return false; m.Result = DefWindowProc(m.HWnd, (uint)m.Msg, m.WParam, new IntPtr(-1)); @@ -436,66 +437,8 @@ namespace AntdUI }; } - protected override void SetBoundsCore(int x, int y, int width, int height, BoundsSpecified specified) - { - if (_shouldPerformMaximiazedState && winState != WState.Maximize) - { - if (y != Top) y = Top; - if (x != Left) x = Left; - _shouldPerformMaximiazedState = false; - } - var size = PatchWindowSizeInRestoreWindowBoundsIfNecessary(width, height); - base.SetBoundsCore(x, y, size.Width, size.Height, specified); - } - - protected override Rectangle GetScaledBounds(Rectangle bounds, SizeF factor, BoundsSpecified specified) - { - var rect = base.GetScaledBounds(bounds, factor, specified); - if (!GetStyle(ControlStyles.FixedWidth) && (specified & BoundsSpecified.Width) != BoundsSpecified.None) - { - var clientWidth = bounds.Width;// - sz.Width; - rect.Width = (int)Math.Round((double)(clientWidth * factor.Width));// + sz.Width; - } - if (!GetStyle(ControlStyles.FixedHeight) && (specified & BoundsSpecified.Height) != BoundsSpecified.None) - { - var clientHeight = bounds.Height;// - sz.Height; - rect.Height = (int)Math.Round((double)(clientHeight * factor.Height));// + sz.Height; - } - return rect; - } - - bool _shouldPerformMaximiazedState = false; - - Size PatchWindowSizeInRestoreWindowBoundsIfNecessary(int width, int height) - { - if (WindowState == FormWindowState.Normal) - { - var restoredWindowBoundsSpecified = typeof(Form).GetField("restoredWindowBoundsSpecified", BindingFlags.NonPublic | BindingFlags.Instance) ?? typeof(Form).GetField("_restoredWindowBoundsSpecified", BindingFlags.NonPublic | BindingFlags.Instance); - var restoredSpecified = (BoundsSpecified)restoredWindowBoundsSpecified!.GetValue(this)!; - - if ((restoredSpecified & BoundsSpecified.Size) != BoundsSpecified.None) - { - var formStateExWindowBoundsFieldInfo = typeof(Form).GetField("FormStateExWindowBoundsWidthIsClientSize", BindingFlags.NonPublic | BindingFlags.Static); - var formStateExFieldInfo = typeof(Form).GetField("formStateEx", BindingFlags.NonPublic | BindingFlags.Instance) ?? typeof(Form).GetField("_formStateEx", BindingFlags.NonPublic | BindingFlags.Instance); - var restoredBoundsFieldInfo = typeof(Form).GetField("restoredWindowBounds", BindingFlags.NonPublic | BindingFlags.Instance) ?? typeof(Form).GetField("_restoredWindowBounds", BindingFlags.NonPublic | BindingFlags.Instance); - - if (formStateExWindowBoundsFieldInfo != null && formStateExFieldInfo != null && restoredBoundsFieldInfo != null) - { - var restoredWindowBounds = (Rectangle)restoredBoundsFieldInfo.GetValue(this)!; - var section = (BitVector32.Section)formStateExWindowBoundsFieldInfo.GetValue(this)!; - var vector = (BitVector32)formStateExFieldInfo.GetValue(this)!; - if (vector[section] == 1) - { - width = restoredWindowBounds.Width;// + borders.Horizontal; - height = restoredWindowBounds.Height; - } - } - } - } - return new Size(width, height); - } - #endregion + } public enum WState diff --git a/src/AntdUI/Lib/Helper.cs b/src/AntdUI/Lib/Helper.cs deleted file mode 100644 index df6aa393..00000000 --- a/src/AntdUI/Lib/Helper.cs +++ /dev/null @@ -1,2167 +0,0 @@ -// 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.Collections; -using System.Collections.Generic; -using System.Drawing; -using System.Drawing.Drawing2D; -using System.Drawing.Imaging; -using System.Windows.Forms; - -namespace AntdUI -{ - public static class Helper - { - internal readonly static StringFormat stringFormatCenter = SF_ALL(); - internal readonly static StringFormat stringFormatCenter2 = SF_NoWrap(); - internal readonly static StringFormat stringFormatLeft = SF_ALL(lr: StringAlignment.Near); - - #region 文本布局 - - /// - /// 文本布局 - /// - /// 垂直(上下) - /// 水平(前后) - public static StringFormat SF(StringAlignment tb = StringAlignment.Center, StringAlignment lr = StringAlignment.Center) - { - return new StringFormat(StringFormat.GenericTypographic) { LineAlignment = tb, Alignment = lr }; - } - - /// - /// 文本布局(不换行) - /// - /// 垂直(上下) - /// 水平(前后) - public static StringFormat SF_NoWrap(StringAlignment tb = StringAlignment.Center, StringAlignment lr = StringAlignment.Center) - { - var sf = new StringFormat(StringFormat.GenericTypographic) { LineAlignment = tb, Alignment = lr }; - sf.FormatFlags |= StringFormatFlags.NoWrap; - return sf; - } - - /// - /// 文本布局(超出省略号) - /// - /// 垂直(上下) - /// 水平(前后) - public static StringFormat SF_Ellipsis(StringAlignment tb = StringAlignment.Center, StringAlignment lr = StringAlignment.Center) - { - return new StringFormat(StringFormat.GenericTypographic) { LineAlignment = tb, Alignment = lr, Trimming = StringTrimming.EllipsisCharacter }; - } - - /// - /// 文本布局(超出省略号+不换行) - /// - /// 垂直(上下) - /// 水平(前后) - public static StringFormat SF_ALL(StringAlignment tb = StringAlignment.Center, StringAlignment lr = StringAlignment.Center) - { - var sf = new StringFormat(StringFormat.GenericTypographic) { LineAlignment = tb, Alignment = lr, Trimming = StringTrimming.EllipsisCharacter }; - sf.FormatFlags |= StringFormatFlags.NoWrap; - return sf; - } - - public static StringFormat SF_MEASURE_FONT() - { - var sf = new StringFormat(StringFormat.GenericTypographic) { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center }; - sf.FormatFlags |= StringFormatFlags.MeasureTrailingSpaces; - return sf; - } - - #endregion - - #region 渲染帮助 - - #region 图片渲染 - - public static void PaintImg(this Graphics g, RectangleF rect, Image image, TFit fit, float radius, bool round) - { - if (round || radius > 0) - { - using (var bmp = new Bitmap((int)rect.Width, (int)rect.Height)) - { - using (var g2 = Graphics.FromImage(bmp).High()) - { - PaintImg(g2, new RectangleF(0, 0, rect.Width, rect.Height), image, fit); - } - using (var brush = new TextureBrush(bmp, WrapMode.Clamp)) - { - brush.TranslateTransform(rect.X, rect.Y); - if (round) g.FillEllipse(brush, rect); - else - { - using (var path = rect.RoundPath(radius)) - { - g.FillPath(brush, path); - } - } - } - } - } - else PaintImg(g, rect, image, fit); - } - public static void PaintImg(this Graphics g, RectangleF rect, Image image, TFit fit, float radius, TShape shape) - { - if (shape == TShape.Circle || shape == TShape.Round || radius > 0) - { - using (var bmp = new Bitmap((int)rect.Width, (int)rect.Height)) - { - using (var g2 = Graphics.FromImage(bmp).High()) - { - PaintImg(g2, new RectangleF(0, 0, rect.Width, rect.Height), image, fit); - } - using (var brush = new TextureBrush(bmp, WrapMode.Clamp)) - { - brush.TranslateTransform(rect.X, rect.Y); - if (shape == TShape.Circle) g.FillEllipse(brush, rect); - else - { - using (var path = rect.RoundPath(radius)) - { - g.FillPath(brush, path); - } - } - } - } - } - else PaintImg(g, rect, image, fit); - } - - internal static void PaintImg(this Graphics g, RectangleF rect, Image image, TFit fit) - { - switch (fit) - { - case TFit.Fill: - g.DrawImage(image, rect); - break; - case TFit.None: - g.DrawImage(image, new RectangleF(rect.X + (rect.Width - image.Width) / 2, rect.Y + (rect.Height - image.Height) / 2, image.Width, image.Height)); - break; - case TFit.Contain: - PaintImgContain(g, image, rect); - break; - case TFit.Cover: - PaintImgCover(g, image, rect); - break; - } - } - internal static void PaintImgCover(this Graphics g, Image image, RectangleF rect) - { - float originWidth = image.Width, originHeight = image.Height; - if (originWidth == originHeight) - { - if (rect.Width == rect.Height) g.DrawImage(image, rect); - else if (rect.Width > rect.Height) g.DrawImage(image, new RectangleF(0, (rect.Height - rect.Width) / 2, rect.Width, rect.Width)); - else g.DrawImage(image, new RectangleF((rect.Width - rect.Height) / 2, 0, rect.Height, rect.Height)); - return; - } - float destWidth = rect.Width, destHeight = rect.Height; - float currentWidth, currentHeight; - if ((originWidth * destHeight) > (originHeight * destWidth)) - { - currentHeight = destHeight; - currentWidth = (originWidth * destHeight) / originHeight; - } - else - { - currentWidth = destWidth; - currentHeight = (destWidth * originHeight) / originWidth; - } - g.DrawImage(image, new RectangleF(rect.X + (destWidth - currentWidth) / 2, rect.Y + (destHeight - currentHeight) / 2, currentWidth, currentHeight), new RectangleF(0, 0, originWidth, originHeight), GraphicsUnit.Pixel); - } - internal static void PaintImgContain(this Graphics g, Image image, RectangleF rect) - { - float originWidth = image.Width, originHeight = image.Height; - if (originWidth == originHeight) - { - if (rect.Width == rect.Height) g.DrawImage(image, rect); - else if (rect.Width > rect.Height) g.DrawImage(image, new RectangleF((rect.Width - rect.Height) / 2, 0, rect.Height, rect.Height)); - else g.DrawImage(image, new RectangleF(0, (rect.Height - rect.Width) / 2, rect.Width, rect.Width)); - return; - } - float destWidth = rect.Width, destHeight = rect.Height; - float currentWidth, currentHeight; - if ((originWidth * destHeight) > (originHeight * destWidth)) - { - currentWidth = destWidth; - currentHeight = (destWidth * originHeight) / originWidth; - } - else - { - currentHeight = destHeight; - currentWidth = (originWidth * destHeight) / originHeight; - } - g.DrawImage(image, new RectangleF(rect.X + (destWidth - currentWidth) / 2, rect.Y + (destHeight - currentHeight) / 2, currentWidth, currentHeight), new RectangleF(0, 0, originWidth, originHeight), GraphicsUnit.Pixel); - } - - #endregion - - #region 图标渲染 - - internal static void PaintIcons(this Graphics g, TType icon, Rectangle rect) - { - switch (icon) - { - case TType.Success: - using (var bmp = SvgExtend.GetImgExtend(SvgDb.IcoSuccess, rect, Style.Db.Success)) - { - if (bmp == null) return; - g.DrawImage(bmp, rect); - } - break; - case TType.Info: - using (var bmp = SvgExtend.GetImgExtend(SvgDb.IcoInfo, rect, Style.Db.Info)) - { - if (bmp == null) return; - g.DrawImage(bmp, rect); - } - break; - case TType.Warn: - using (var bmp = SvgExtend.GetImgExtend(SvgDb.IcoWarn, rect, Style.Db.Warning)) - { - if (bmp == null) return; - g.DrawImage(bmp, rect); - } - break; - case TType.Error: - using (var bmp = SvgExtend.GetImgExtend(SvgDb.IcoError, rect, Style.Db.Error)) - { - if (bmp == null) return; - g.DrawImage(bmp, rect); - } - break; - } - } - internal static void PaintIcons(this Graphics g, TType icon, Rectangle rect, Color back) - { - using (var brush = new SolidBrush(back)) - { - g.FillEllipse(brush, new Rectangle(rect.X + 1, rect.Y + 1, rect.Width - 2, rect.Height - 2)); - } - switch (icon) - { - case TType.Success: - using (var bmp = SvgExtend.GetImgExtend(SvgDb.IcoSuccess, rect, Style.Db.Success)) - { - if (bmp == null) return; - g.DrawImage(bmp, rect); - } - break; - case TType.Info: - using (var bmp = SvgExtend.GetImgExtend(SvgDb.IcoInfo, rect, Style.Db.Info)) - { - if (bmp == null) return; - g.DrawImage(bmp, rect); - } - break; - case TType.Warn: - using (var bmp = SvgExtend.GetImgExtend(SvgDb.IcoWarn, rect, Style.Db.Warning)) - { - if (bmp == null) return; - g.DrawImage(bmp, rect); - } - break; - case TType.Error: - using (var bmp = SvgExtend.GetImgExtend(SvgDb.IcoError, rect, Style.Db.Error)) - { - if (bmp == null) return; - g.DrawImage(bmp, rect); - } - break; - } - } - internal static void PaintIconGhosts(this Graphics g, TType icon, Rectangle rect, Color color) - { - switch (icon) - { - case TType.Success: - using (var bmp = SvgExtend.GetImgExtend(SvgDb.IcoSuccessGhost, rect, color)) - { - if (bmp == null) return; - g.DrawImage(bmp, rect); - } - break; - case TType.Info: - using (var bmp = SvgExtend.GetImgExtend(SvgDb.IcoInfoGhost, rect, color)) - { - if (bmp == null) return; - g.DrawImage(bmp, rect); - } - break; - case TType.Warn: - using (var bmp = SvgExtend.GetImgExtend(SvgDb.IcoWarnGhost, rect, color)) - { - if (bmp == null) return; - g.DrawImage(bmp, rect); - } - break; - case TType.Error: - using (var bmp = SvgExtend.GetImgExtend(SvgDb.IcoErrorGhost, rect, color)) - { - if (bmp == null) return; - g.DrawImage(bmp, rect); - } - break; - } - } - internal static void PaintIconClose(this Graphics g, Rectangle rect, Color color) - { - PaintIconCore(g, rect, SvgDb.IcoErrorGhost, color); - } - internal static void PaintIconClose(this Graphics g, Rectangle rect, Color color, float dot) - { - PaintIconCore(g, rect, SvgDb.IcoErrorGhost, color, dot); - } - - /// - /// 绘制带圆背景的镂空图标 - /// - internal static void PaintIconCoreGhost(this Graphics g, Rectangle rect, string svg, Color back, Color fore) - { - using (var brush = new SolidBrush(back)) - { - g.FillEllipse(brush, rect); - } - using (var bmp = SvgExtend.GetImgExtend(svg, rect, fore)) - { - if (bmp == null) return; - g.DrawImage(bmp, rect); - } - } - internal static void PaintIconCore(this Graphics g, Rectangle rect, string svg, Color back, Color fore) - { - using (var brush = new SolidBrush(back)) - { - g.FillEllipse(brush, new Rectangle(rect.X + 1, rect.Y + 1, rect.Width - 2, rect.Height - 2)); - } - using (var bmp = SvgExtend.GetImgExtend(svg, rect, fore)) - { - if (bmp == null) return; - g.DrawImage(bmp, rect); - } - } - internal static void PaintIconCore(this Graphics g, Rectangle rect, string svg, Color color) - { - using (var bmp = SvgExtend.GetImgExtend(svg, rect, color)) - { - if (bmp == null) return; - g.DrawImage(bmp, rect); - } - } - internal static void PaintIconCore(this Graphics g, Rectangle rect, string svg, Color color, float dot) - { - int size = (int)(rect.Height * dot); - var rect_ico = new Rectangle(rect.X + (rect.Width - size) / 2, rect.Y + (rect.Height - size) / 2, size, size); - using (var bmp = SvgExtend.GetImgExtend(svg, rect_ico, color)) - { - if (bmp == null) return; - g.DrawImage(bmp, rect_ico); - } - } - - #endregion - - public static Brush BrushEx(this string? code, Rectangle rect, Color def) - { - if (code != null) - { - var arr = code.Split(','); - if (arr.Length > 1) - { - if (arr.Length > 2 && float.TryParse(arr[0], out float deg)) return new LinearGradientBrush(rect, arr[1].Trim().ToColor(), arr[2].Trim().ToColor(), 270 + deg); - else return new LinearGradientBrush(rect, arr[0].Trim().ToColor(), arr[1].Trim().ToColor(), 270F); - } - } - return new SolidBrush(def); - } - - public static Graphics High(this Graphics g) - { - Config.SetDpi(g); - g.SmoothingMode = SmoothingMode.AntiAlias; - g.InterpolationMode = InterpolationMode.HighQualityBicubic; - g.PixelOffsetMode = PixelOffsetMode.HighQuality; - if (Config.TextRenderingHint.HasValue) g.TextRenderingHint = Config.TextRenderingHint.Value; - return g; - } - public static Graphics HighLay(this Graphics g) - { - Config.SetDpi(g); - g.SmoothingMode = SmoothingMode.AntiAlias; - g.InterpolationMode = InterpolationMode.HighQualityBicubic; - g.PixelOffsetMode = PixelOffsetMode.HighQuality; - g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias; - return g; - } - - public static void GDI(Action action) - { - using (var bmp = new Bitmap(1, 1)) - { - using (var g = Graphics.FromImage(bmp)) - { - Config.SetDpi(g); - action(g); - } - } - } - - public static T GDI(Func action) - { - using (var bmp = new Bitmap(1, 1)) - { - using (var g = Graphics.FromImage(bmp)) - { - Config.SetDpi(g); - return action(g); - } - } - } - - public static void DrawImage(this Graphics g, Bitmap bmp, Rectangle rect, float opacity) - { - using (var attributes = new ImageAttributes()) - { - var matrix = new ColorMatrix { Matrix33 = opacity }; - attributes.SetColorMatrix(matrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap); - g.DrawImage(bmp, rect, 0, 0, bmp.Width, bmp.Height, GraphicsUnit.Pixel, attributes); - } - } - - public static void DrawImage(this Graphics g, Image bmp, Rectangle rect, float opacity) - { - if (opacity == 1F) - { - g.DrawImage(bmp, rect); - return; - } - using (var attributes = new ImageAttributes()) - { - var matrix = new ColorMatrix { Matrix33 = opacity }; - attributes.SetColorMatrix(matrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap); - g.DrawImage(bmp, rect, 0, 0, bmp.Width, bmp.Height, GraphicsUnit.Pixel, attributes); - } - } - - #endregion - - #region 区域 - - /// - /// 得到容器标准坐标 - /// - /// 区域 - /// 字体高度 - /// 左边图标 - /// 右边图标 - /// 左右翻转 - /// 多选 - internal static RectTextLR IconRect(this Rectangle rect, int text_height, bool icon_l, bool icon_r, bool right, bool muit, float gap_ratio = .4F, float sp_ratio = .25F, float icon_ratio = .7F) - { - var rectlr = new RectTextLR(); - int sps = (int)(text_height * gap_ratio), h = (int)(text_height * icon_ratio), sps2 = sps * 2; - if (muit) - { - if (icon_l && icon_r) - { - int sp = (int)(text_height * sp_ratio); - rectlr.text = new Rectangle(rect.X + sps + h + sp, rect.Y + sps, rect.Width - ((sps + h + sp) * 2), rect.Height - sps2); - - rectlr.l = new Rectangle(rect.X + sps, rect.Y + sps + (text_height - h) / 2, h, h); - rectlr.r = new Rectangle(rectlr.text.Right + sp, rectlr.l.Y, h, h); - if (right) - { - var r = rectlr.r; - rectlr.r = rectlr.l; - rectlr.l = r; - return rectlr; - } - } - else if (icon_l) - { - int sp = (int)(text_height * sp_ratio); - if (right) - { - rectlr.text = new Rectangle(rect.X + sps, rect.Y + sps, rect.Width - sps2 - h - sp, rect.Height - sps2); - rectlr.l = new Rectangle(rectlr.text.Right + sp, rect.Y + sps + (text_height - h) / 2, h, h); - return rectlr; - } - rectlr.text = new Rectangle(rect.X + sps + h + sp, rect.Y + sps, rect.Width - sps2 - h - sp, rect.Height - sps2); - rectlr.l = new Rectangle(rect.X + sps, rect.Y + sps + (text_height - h) / 2, h, h); - } - else if (icon_r) - { - int sp = (int)(text_height * sp_ratio); - if (right) - { - rectlr.text = new Rectangle(rect.X + sps + h + sp, rect.Y + sps, rect.Width - sps2 - h - sp, rect.Height - sps2); - rectlr.r = new Rectangle(rect.X + sps, rect.Y + sps + (text_height - h) / 2, h, h); - return rectlr; - } - rectlr.text = new Rectangle(rect.X + sps, rect.Y + sps, rect.Width - sps2 - h - sp, rect.Height - sps2); - rectlr.r = new Rectangle(rectlr.text.Right + sp, rect.Y + sps + (text_height - h) / 2, h, h); - } - else rectlr.text = new Rectangle(rect.X + sps, rect.Y + sps, rect.Width - sps2, rect.Height - sps2); - } - else - { - if (icon_l && icon_r) - { - int sp = (int)(text_height * sp_ratio); - rectlr.text = new Rectangle(rect.X + sps + h + sp, rect.Y + (rect.Height - text_height) / 2, rect.Width - ((sps + h + sp) * 2), text_height); - - rectlr.l = new Rectangle(rect.X + sps, rect.Y + (rect.Height - h) / 2, h, h); - rectlr.r = new Rectangle(rectlr.text.Right + sp, rectlr.l.Y, h, h); - if (right) - { - var r = rectlr.r; - rectlr.r = rectlr.l; - rectlr.l = r; - return rectlr; - } - } - else if (icon_l) - { - int sp = (int)(text_height * sp_ratio); - if (right) - { - rectlr.text = new Rectangle(rect.X + sps, rect.Y + (rect.Height - text_height) / 2, rect.Width - sps2 - h - sp, text_height); - rectlr.l = new Rectangle(rectlr.text.Right + sp, rect.Y + (rect.Height - h) / 2, h, h); - return rectlr; - } - rectlr.text = new Rectangle(rect.X + sps + h + sp, rect.Y + (rect.Height - text_height) / 2, rect.Width - sps2 - h - sp, text_height); - rectlr.l = new Rectangle(rect.X + sps, rect.Y + (rect.Height - h) / 2, h, h); - } - else if (icon_r) - { - int sp = (int)(text_height * sp_ratio); - if (right) - { - rectlr.text = new Rectangle(rect.X + sps + h + sp, rect.Y + (rect.Height - text_height) / 2, rect.Width - sps2 - h - sp, text_height); - rectlr.r = new Rectangle(rect.X + sps, rect.Y + (rect.Height - h) / 2, h, h); - return rectlr; - } - rectlr.text = new Rectangle(rect.X + sps, rect.Y + (rect.Height - text_height) / 2, rect.Width - sps2 - h - sp, text_height); - rectlr.r = new Rectangle(rectlr.text.Right + sp, rect.Y + (rect.Height - h) / 2, h, h); - } - else rectlr.text = new Rectangle(rect.X + sps, rect.Y + (rect.Height - text_height) / 2, rect.Width - sps2, text_height); - } - return rectlr; - } - internal static RectTextLR IconRect(this Rectangle rect, float text_height, bool icon_l, bool icon_r, bool right, bool muit, float gap_ratio = .4F, float sp_ratio = .25F, float icon_ratio = .7F) - { - return rect.IconRect((int)Math.Round(text_height), icon_l, icon_r, right, muit, gap_ratio, sp_ratio, icon_ratio); - } - - internal static void IconRectL(this Rectangle rect, SizeF font_size, out Rectangle icon_rect, out Rectangle text_rect, float size = 0.8F) - { - int h = (int)(font_size.Height * size); - int dot_size_ = h / 2; - int dot_txt_left = h * 2; - - icon_rect = new Rectangle(rect.X + dot_size_, rect.Y + (rect.Height - h) / 2, h, h); - text_rect = new Rectangle(rect.X + dot_txt_left, rect.Y, rect.Width - dot_txt_left, rect.Height); - } - - #region 三角 - - internal static PointF[] TriangleLines(this Rectangle rect, float prog, float d = 0.7F) - { - float size = rect.Width * d, size2 = size / 2; - float x = rect.X + rect.Width / 2F, y = rect.Y + rect.Height / 2F; - if (prog == 0) - { - return new PointF[] { - new PointF(x - size2, y), - new PointF(x + size2,y) - }; - } - else if (prog > 0) - { - float h = size2 * prog, h2 = h / 2; - return new PointF[] { - new PointF(x - size2,y + h2), - new PointF(x, y - h2), - new PointF(x + size2,y + h2) - }; - } - else - { - float h = size2 * -prog, h2 = h / 2; - return new PointF[] { - new PointF(x - size2,y - h2), - new PointF(x, y + h2), - new PointF(x + size2,y - h2) - }; - } - } - - internal static PointF[] TriangleLines(this TAlignMini align, RectangleF rect, float b = 0.375F) - { - float size = rect.Height * b, size2 = size / 2F; - float x = rect.X + rect.Width / 2F, y = rect.Y + rect.Height / 2F; - float h2 = size2 / 2; - - switch (align) - { - case TAlignMini.Top: - return new PointF[] { - new PointF(x - size2,y + h2), - new PointF(x, y - h2), - new PointF(x + size2,y + h2) - }; - case TAlignMini.Bottom: - return new PointF[] { - new PointF(x - size2,y - h2), - new PointF(x, y + h2), - new PointF(x + size2,y - h2) - }; - case TAlignMini.Left: - return new PointF[] { - new PointF(x + h2,y - size2), - new PointF(x - h2, y), - new PointF(x + h2,y + size2) - }; - case TAlignMini.Right: - default: - return new PointF[] { - new PointF(x - h2,y - size2), - new PointF(x + h2, y), - new PointF(x - h2,y + size2) - }; - } - } - - #endregion - - #region DisplayRectangle - - public static Rectangle DeflateRect(this Rectangle rect, Padding padding) - { - rect.X += padding.Left; - rect.Y += padding.Top; - rect.Width -= padding.Horizontal; - rect.Height -= padding.Vertical; - return rect; - } - - public static Rectangle DeflateRect(this Rectangle rect, Padding padding, ShadowConfig config, TAlignMini align, float borderWidth = 0F) - { - if (config.Shadow > 0) - { - int shadow = (int)(config.Shadow * Config.Dpi), s2 = shadow * 2, shadowOffsetX = Math.Abs((int)(config.ShadowOffsetX * Config.Dpi)), shadowOffsetY = Math.Abs((int)(config.ShadowOffsetY * Config.Dpi)); - int x, y, w, h; - switch (align) - { - case TAlignMini.Top: - x = rect.X + padding.Left; - w = rect.Width - padding.Horizontal; - - y = rect.Y + padding.Top + shadow; - h = rect.Height - padding.Vertical - shadow; - break; - case TAlignMini.Bottom: - x = rect.X + padding.Left; - w = rect.Width - padding.Horizontal; - - y = rect.Y + padding.Top; - h = rect.Height - padding.Vertical - shadow; - break; - case TAlignMini.Left: - y = rect.Y + padding.Top; - h = rect.Height - padding.Vertical; - - x = rect.X + padding.Left + shadow; - w = rect.Width - padding.Horizontal - shadow; - break; - case TAlignMini.Right: - y = rect.Y + padding.Top; - h = rect.Height - padding.Vertical; - - x = rect.X + padding.Left; - w = rect.Width - padding.Horizontal - shadow; - break; - case TAlignMini.None: - default: - x = rect.X + padding.Left + shadow; - y = rect.Y + padding.Top + shadow; - w = rect.Width - padding.Horizontal - s2; - h = rect.Height - padding.Vertical - s2; - break; - } - - if (config.ShadowOffsetX < 0) - { - x += shadowOffsetX; - w -= shadowOffsetX; - } - if (config.ShadowOffsetY < 0) - { - y += shadowOffsetY; - h -= shadowOffsetY; - } - - if (borderWidth > 0) - { - int pr = (int)Math.Ceiling(borderWidth * Config.Dpi), pr2 = pr * 2; - return new Rectangle(x + pr, y + pr, w - pr2, h - pr2); - } - return new Rectangle(x, y, w, h); - } - else - { - if (borderWidth > 0) - { - int pr = (int)Math.Ceiling(borderWidth * Config.Dpi), pr2 = pr * 2; - return new Rectangle(rect.X + padding.Left + pr, rect.Y + padding.Top + pr, rect.Width - padding.Horizontal - pr2, rect.Height - padding.Vertical - pr2); - } - return new Rectangle(rect.X + padding.Left, rect.Y + padding.Top, rect.Width - padding.Horizontal, rect.Height - padding.Vertical); - } - } - - #endregion - - public static Rectangle PaddingRect(this Rectangle rect, ShadowConfig config, TAlignMini align, float borderWidth = 0F) - { - if (config.Shadow > 0) - { - int shadow = (int)(config.Shadow * Config.Dpi), s2 = shadow * 2, shadowOffsetX = Math.Abs((int)(config.ShadowOffsetX * Config.Dpi)), shadowOffsetY = Math.Abs((int)(config.ShadowOffsetY * Config.Dpi)); - - int x, y, w, h; - switch (align) - { - case TAlignMini.Top: - x = rect.X; - w = rect.Width; - - y = rect.Y + shadow; - h = rect.Height - shadow; - break; - case TAlignMini.Bottom: - x = rect.X; - w = rect.Width; - - y = rect.Y; - h = rect.Height - shadow; - break; - case TAlignMini.Left: - y = rect.Y; - h = rect.Height; - - x = rect.X + shadow; - w = rect.Width - shadow; - break; - case TAlignMini.Right: - y = rect.Y; - h = rect.Height; - - x = rect.X; - w = rect.Width - shadow; - break; - case TAlignMini.None: - default: - x = rect.X + shadow; - y = rect.Y + shadow; - w = rect.Width - s2; - h = rect.Height - s2; - break; - } - - if (config.ShadowOffsetX < 0) - { - x += shadowOffsetX; - w -= shadowOffsetX; - } - if (config.ShadowOffsetY < 0) - { - y += shadowOffsetY; - h -= shadowOffsetY; - } - - if (borderWidth > 0) - { - int pr = (int)Math.Ceiling(borderWidth * Config.Dpi / 2F), pr2 = pr * 2; - return new Rectangle(x + pr, y + pr, w - pr2, h - pr2); - } - return new Rectangle(x, y, w, h); - } - else - { - if (borderWidth > 0) - { - int pr = (int)Math.Ceiling((borderWidth * Config.Dpi) / 2F), pr2 = pr * 2; - return new Rectangle(rect.X + pr, rect.Y + pr, rect.Width - pr2, rect.Height - pr2); - } - return rect; - } - } - public static Rectangle PaddingRect(this Rectangle rect, Padding padding, int x, int y, int r, int b) - { - return new Rectangle(rect.X + padding.Left + x, rect.Y + padding.Top + y, rect.Width - padding.Horizontal - r, rect.Height - padding.Vertical - b); - } - public static Rectangle PaddingRect(this Rectangle rect, params Padding[] paddings) - { - foreach (var padding in paddings) - { - rect.X += padding.Left; - rect.Y += padding.Top; - rect.Width -= padding.Horizontal; - rect.Height -= padding.Vertical; - } - return rect; - } - - /// - /// 获取边距 - /// - /// 区域 - /// 边距 - /// 边框 - public static Rectangle PaddingRect(this Rectangle rect, Padding padding, float size = 0F) - { - if (size > 0) - { - int pr = (int)Math.Round(size), pr2 = pr * 2; - return new Rectangle(rect.X + padding.Left + pr, rect.Y + padding.Top + pr, rect.Width - padding.Horizontal - pr2, rect.Height - padding.Vertical - pr2); - } - return new Rectangle(rect.X + padding.Left, rect.Y + padding.Top, rect.Width - padding.Horizontal, rect.Height - padding.Vertical); - } - public static Rectangle PaddingRect(this Rectangle rect, Padding padding, int x, int y, int r, int b, float size = 0F) - { - if (size > 0) - { - int pr = (int)Math.Round(size), pr2 = pr * 2; - return new Rectangle(rect.X + padding.Left + pr + x, rect.Y + padding.Top + pr + y, rect.Width - padding.Horizontal - pr2 - r, rect.Height - padding.Vertical - pr2 - b); - } - return new Rectangle(rect.X + padding.Left + x, rect.Y + padding.Top + y, rect.Width - padding.Horizontal - r, rect.Height - padding.Vertical - b); - } - - /// - /// 得到真实渲染区域 - /// - /// 容器区域 - /// 动画区域 - /// 形状 - /// 连接左边 - /// 连接右边 - internal static Rectangle ReadRect(this Rectangle rect, float size, TShape shape, bool joinLeft, bool joinRight) - { - if (shape == TShape.Circle) - { - int pr = (int)Math.Round(size), pr2 = pr * 2; - if (rect.Width > rect.Height) - { - int h = rect.Height - pr2; - return new Rectangle(rect.X + (rect.Width - h) / 2, rect.Y + pr, h, h); - } - else - { - int w = rect.Width - pr2; - return new Rectangle(rect.X + pr, rect.Y + (rect.Height - w) / 2, w, w); - } - } - return ReadRect(rect, size, joinLeft, joinRight); - } - - /// - /// 得到真实渲染区域 - /// - /// 容器区域 - /// 动画区域 - /// 连接左边 - /// 连接右边 - internal static Rectangle ReadRect(this Rectangle rect, float size, bool joinLeft, bool joinRight) - { - int pr = (int)Math.Round(size), pr2 = pr * 2; - if (joinLeft && joinRight) return new Rectangle(rect.X, rect.Y + pr, rect.Width, rect.Height - pr2); - else if (joinLeft) - { - var r = new Rectangle(rect.X, rect.Y + pr, rect.Width - pr, rect.Height - pr2); - rect.X = -pr; - rect.Width += pr; - return r; - } - else if (joinRight) - { - var r = new Rectangle(rect.Width - (rect.Width - pr), rect.Y + pr, rect.Width - pr, rect.Height - pr2); - rect.X = 0; - rect.Width += pr; - return r; - } - return new Rectangle(rect.X + pr, rect.Y + pr, rect.Width - pr2, rect.Height - pr2); - } - - #endregion - - #region Align - - internal static void SetAlignment(this ContentAlignment textAlign, ref StringFormat stringFormat) - { - switch (textAlign) - { - case ContentAlignment.TopLeft: - stringFormat.Alignment = StringAlignment.Near; - stringFormat.LineAlignment = StringAlignment.Near; - //内容在垂直方向上顶部对齐,在水平方向上左边对齐 - break; - case ContentAlignment.TopCenter: - stringFormat.Alignment = StringAlignment.Center; - stringFormat.LineAlignment = StringAlignment.Near; - //内容在垂直方向上顶部对齐,在水平方向上居中对齐 - - break; - case ContentAlignment.TopRight: - //内容在垂直方向上顶部对齐,在水平方向上右边对齐 - stringFormat.Alignment = StringAlignment.Far; - stringFormat.LineAlignment = StringAlignment.Near; - break; - case ContentAlignment.MiddleLeft: - //内容在垂直方向上中间对齐,在水平方向上左边对齐 - stringFormat.Alignment = StringAlignment.Near; - stringFormat.LineAlignment = StringAlignment.Center; - - break; - case ContentAlignment.MiddleCenter: - //内容在垂直方向上中间对齐,在水平方向上居中对齐 - stringFormat.Alignment = StringAlignment.Center; - stringFormat.LineAlignment = StringAlignment.Center; - break; - case ContentAlignment.MiddleRight: - //内容在垂直方向上中间对齐,在水平方向上右边对齐 - stringFormat.Alignment = StringAlignment.Far; - stringFormat.LineAlignment = StringAlignment.Center; - - break; - case ContentAlignment.BottomLeft: - //内容在垂直方向上底边对齐,在水平方向上左边对齐 - stringFormat.Alignment = StringAlignment.Near; - stringFormat.LineAlignment = StringAlignment.Far; - break; - case ContentAlignment.BottomCenter: - //内容在垂直方向上底边对齐,在水平方向上居中对齐 - stringFormat.Alignment = StringAlignment.Center; - stringFormat.LineAlignment = StringAlignment.Far; - - break; - case ContentAlignment.BottomRight: - //内容在垂直方向上底边对齐,在水平方向上右边对齐 - stringFormat.Alignment = StringAlignment.Far; - stringFormat.LineAlignment = StringAlignment.Far; - break; - } - } - internal static void SetAlignment(this HorizontalAlignment textAlign, ref StringFormat stringFormat) - { - switch (textAlign) - { - case HorizontalAlignment.Left: - //内容在垂直方向上中间对齐,在水平方向上左边对齐 - stringFormat.Alignment = StringAlignment.Near; - break; - case HorizontalAlignment.Center: - //内容在垂直方向上中间对齐,在水平方向上居中对齐 - stringFormat.Alignment = StringAlignment.Center; - break; - case HorizontalAlignment.Right: - //内容在垂直方向上中间对齐,在水平方向上右边对齐 - stringFormat.Alignment = StringAlignment.Far; - break; - } - } - /// - /// 转换大致位置 - /// - /// 方向 - internal static TAlignMini AlignMini(this TAlign align) - { - if (align == TAlign.BL || align == TAlign.Bottom || align == TAlign.BR) - return TAlignMini.Bottom; - else if (align == TAlign.TL || align == TAlign.Top || align == TAlign.TR) - return TAlignMini.Top; - else if (align == TAlign.RT || align == TAlign.Right || align == TAlign.RB) - return TAlignMini.Right; - else if (align == TAlign.LT || align == TAlign.Left || align == TAlign.LB) - return TAlignMini.Left; - return TAlignMini.None; - } - - /// - /// 转换反向大致位置 - /// - /// 方向 - /// 是否竖向 - internal static TAlign AlignMiniReverse(this TAlign align, bool vertical) - { - if (vertical) - { - if (align == TAlign.TL || align == TAlign.BL || align == TAlign.LB || align == TAlign.Left || align == TAlign.LT) return TAlign.Right; - return TAlign.Left; - } - else - { - if (align == TAlign.TL || align == TAlign.Top || align == TAlign.TR || align == TAlign.RT) return TAlign.Bottom; - return TAlign.Top; - } - } - - #endregion - - /// - /// 得到三角绘制区域 - /// - /// 方向 - /// 三角大小 - /// 全局区域 - /// 内容区域 - internal static PointF[] AlignLines(this TAlign align, float arrow_size, RectangleF rect, RectangleF rect_read) - { - if (align == TAlign.Top) - { - //↑上 - float x = rect.Width / 2F, y = rect_read.Y + rect_read.Height; - return new PointF[] { new PointF(x - arrow_size, y), new PointF(x + arrow_size, y), new PointF(x, y + arrow_size) }; - } - else if (align == TAlign.Bottom) - { - //↓ 下 - float x = rect.Width / 2F, y = rect_read.Y - arrow_size; - return new PointF[] { new PointF(x, y), new PointF(x - arrow_size, y + arrow_size), new PointF(x + arrow_size, y + arrow_size) }; - } - else if (align == TAlign.Left || align == TAlign.LT || align == TAlign.LB) - { - //← 左 - float x = rect_read.X + rect_read.Width, y = rect.Height / 2F; - return new PointF[] { new PointF(x, y - arrow_size), new PointF(x, y + arrow_size), new PointF(x + arrow_size, y) }; - } - else if (align == TAlign.Right || align == TAlign.RT || align == TAlign.RB) - { - //→ 右 - float x = rect_read.X - arrow_size, y = rect.Height / 2F; - return new PointF[] { new PointF(x, y), new PointF(x + arrow_size, y - arrow_size), new PointF(x + arrow_size, y + arrow_size) }; - } - - #region 下 - - else if (align == TAlign.BL) - { - //↙ 下左 - float x = rect_read.X + arrow_size * 3F, y = rect_read.Y - arrow_size; - return new PointF[] { new PointF(x, y), new PointF(x - arrow_size, y + arrow_size), new PointF(x + arrow_size, y + arrow_size) }; - } - else if (align == TAlign.BR) - { - //↘ 下右 - float x = rect_read.X + rect_read.Width - arrow_size * 3F, y = rect_read.Y - arrow_size; - return new PointF[] { new PointF(x, y), new PointF(x - arrow_size, y + arrow_size), new PointF(x + arrow_size, y + arrow_size) }; - } - - #endregion - - #region 上 - - else if (align == TAlign.TL) - { - //↖ 上左 - float x = rect_read.X + arrow_size * 3F, y = rect_read.Y + rect_read.Height; - return new PointF[] { new PointF(x - arrow_size, y), new PointF(x + arrow_size, y), new PointF(x, y + arrow_size) }; - } - else if (align == TAlign.TR) - { - //↗ 上右 - float x = rect_read.X + rect_read.Width - arrow_size * 3F, y = rect_read.Y + rect_read.Height; - return new PointF[] { new PointF(x - arrow_size, y), new PointF(x + arrow_size, y), new PointF(x, y + arrow_size) }; - } - - #endregion - - else - { - //↑上 - float x = rect.Width / 2F, y = rect_read.Y + rect_read.Height; - return new PointF[] { new PointF(x - arrow_size, y), new PointF(x + arrow_size, y), new PointF(x, y + arrow_size) }; - } - } - - /// - /// 弹出坐标 - /// - /// 方向 - /// 控件坐标 - /// 控件大小 - /// 提示框宽度 - /// 提示框高度 - internal static Point AlignPoint(this TAlign align, Point point, Size size, int width, int height) - { - switch (align) - { - case TAlign.Top: - return new Point(point.X + (size.Width - width) / 2, point.Y - height); - case TAlign.TL: - return new Point(point.X, point.Y - height); - case TAlign.TR: - return new Point(point.X + size.Width - width, point.Y - height); - case TAlign.Bottom: - return new Point(point.X + (size.Width - width) / 2, point.Y + size.Height); - case TAlign.BL: - return new Point(point.X, point.Y + size.Height); - case TAlign.BR: - return new Point(point.X + size.Width - width, point.Y + size.Height); - case TAlign.Left: - case TAlign.LT: - case TAlign.LB: - return new Point(point.X - width, point.Y + (size.Height - height) / 2); - case TAlign.Right: - case TAlign.RT: - case TAlign.RB: - return new Point(point.X + size.Width, point.Y + (size.Height - height) / 2); - default: - return new Point(point.X + (size.Width - width) / 2, point.Y - height); - } - } - - internal static Point AlignPoint(this TAlign align, Rectangle rect, Rectangle size) - { - return AlignPoint(align, rect.Location, rect.Size, size.Width, size.Height); - } - - internal static Point AlignPoint(this TAlign align, Rectangle rect, int width, int height) - { - return AlignPoint(align, rect.Location, rect.Size, width, height); - } - - #region 圆角 - - public static GraphicsPath RoundPath(this Rectangle rect, float radius) - { - return RoundPathCore(rect, radius); - } - - public static GraphicsPath RoundPath(this RectangleF rect, float radius) - { - return RoundPathCore(rect, radius); - } - - internal static GraphicsPath RoundPath(this RectangleF rect, float radius, TShape shape) - { - return RoundPath(rect, radius, shape == TShape.Round); - } - - internal static GraphicsPath RoundPath(this Rectangle rect, float radius, bool round) - { - if (round) return CapsulePathCore(rect); - return RoundPathCore(rect, radius); - } - - internal static GraphicsPath RoundPath(this RectangleF rect, float radius, bool round) - { - if (round) return CapsulePathCore(rect); - return RoundPathCore(rect, radius); - } - - internal static GraphicsPath RoundPath(this Rectangle rect, float radius, TAlignMini shadowAlign) - { - switch (shadowAlign) - { - case TAlignMini.Top: return RoundPath(rect, radius, true, true, false, false); - case TAlignMini.Bottom: return RoundPath(rect, radius, false, false, true, true); - case TAlignMini.Left: return RoundPath(rect, radius, true, false, false, true); - case TAlignMini.Right: return RoundPath(rect, radius, false, true, true, false); - case TAlignMini.None: - default: return RoundPathCore(rect, radius); - } - } - - /// - /// 自定义圆角 - /// - /// 区域 - /// 圆角大小 - /// ↖ - /// ↗ - /// ↘ - /// ↙ - public static GraphicsPath RoundPath(this Rectangle rect, float radius, bool TL, bool TR, bool BR, bool BL) - { - var path = new GraphicsPath(); - if (radius <= 0F) path.AddRectangle(rect); - else - { - float diameter = radius * 2F; - var arc = new RectangleF(rect.X, rect.Y, diameter, diameter); - - // TL - if (TL) path.AddArc(arc, 180, 90); - else path.AddLine(rect.X, rect.Y, rect.Right - diameter, rect.Y); - - // TR - arc.X = rect.Right - diameter; - if (TR) path.AddArc(arc, 270, 90); - else path.AddLine(rect.Right, rect.Y, rect.Right, rect.Bottom - diameter); - - // BR - arc.Y = rect.Bottom - diameter; - if (BR) path.AddArc(arc, 0, 90); - else path.AddLine(rect.Right, rect.Bottom, rect.X + diameter, rect.Bottom); - - // BL - arc.X = rect.Left; - if (BL) path.AddArc(arc, 90, 90); - else path.AddLine(rect.X, rect.Bottom, rect.X, rect.Y + diameter); - - path.CloseFigure(); - } - return path; - } - - /// - /// 自定义圆角 - /// - /// 区域 - /// 圆角大小 - /// ↖ - /// ↗ - /// ↘ - /// ↙ - public static GraphicsPath RoundPath(this RectangleF rect, float radius, bool TL, bool TR, bool BR, bool BL) - { - var path = new GraphicsPath(); - if (radius <= 0F) path.AddRectangle(rect); - else - { - float diameter = radius * 2F; - var arc = new RectangleF(rect.X, rect.Y, diameter, diameter); - - // TL - if (TL) path.AddArc(arc, 180, 90); - else path.AddLine(rect.X, rect.Y, rect.Right - diameter, rect.Y); - - // TR - arc.X = rect.Right - diameter; - if (TR) path.AddArc(arc, 270, 90); - else path.AddLine(rect.Right, rect.Y, rect.Right, rect.Bottom - diameter); - - // BR - arc.Y = rect.Bottom - diameter; - if (BR) path.AddArc(arc, 0, 90); - else path.AddLine(rect.Right, rect.Bottom, rect.X + diameter, rect.Bottom); - - // BL - arc.X = rect.Left; - if (BL) path.AddArc(arc, 90, 90); - else path.AddLine(rect.X, rect.Bottom, rect.X, rect.Y + diameter); - - path.CloseFigure(); - } - return path; - } - - static GraphicsPath RoundPathCore(RectangleF rect, float radius) - { - var path = new GraphicsPath(); - if (radius > 0F) - { - if (radius >= (Math.Min(rect.Width, rect.Height) / 2F)) AddCapsule(path, rect); - else - { - float diameter = radius * 2F; - var arc = new RectangleF(rect.X, rect.Y, diameter, diameter); - - // TL - path.AddArc(arc, 180, 90); - - // TR - arc.X = rect.Right - diameter; - path.AddArc(arc, 270, 90); - - // BR - arc.Y = rect.Bottom - diameter; - path.AddArc(arc, 0, 90); - - // BL - arc.X = rect.Left; - path.AddArc(arc, 90, 90); - - path.CloseFigure(); - } - } - else path.AddRectangle(rect); - return path; - } - static GraphicsPath CapsulePathCore(RectangleF rect) - { - var path = new GraphicsPath(); - AddCapsule(path, rect); - return path; - } - static void AddCapsule(GraphicsPath path, RectangleF rect) - { - float diameter; - RectangleF arc; - if (rect.Width > 0 && rect.Height > 0) - { - if (rect.Width > rect.Height) - { - // Horizontal capsule - diameter = rect.Height; - SizeF sizeF = new SizeF(diameter, diameter); - arc = new RectangleF(rect.Location, sizeF); - path.AddArc(arc, 90, 180); - arc.X = rect.Right - diameter; - path.AddArc(arc, 270, 180); - } - else if (rect.Width < rect.Height) - { - // Vertical capsule - diameter = rect.Width; - SizeF sizeF = new SizeF(diameter, diameter); - arc = new RectangleF(rect.Location, sizeF); - path.AddArc(arc, 180, 180); - arc.Y = rect.Bottom - diameter; - path.AddArc(arc, 0, 180); - } - else - { - // Circle - path.AddEllipse(rect); - } - } - else path.AddEllipse(rect); - path.CloseFigure(); - } - - #endregion - - #region 图像处理 - - #region 模糊 - - public static void Blur(Bitmap bmp, int range) - { - Blur(bmp, range, new Rectangle(0, 0, bmp.Width, bmp.Height)); - } - public static void Blur(Bitmap bmp, int range, Rectangle rect) - { - if (range > 1) - { - using (UnsafeBitmap unsafeBitmap = new UnsafeBitmap(bmp, true)) - { - BlurHorizontal(unsafeBitmap, range, rect); - BlurVertical(unsafeBitmap, range, rect); - BlurHorizontal(unsafeBitmap, range, rect); - BlurVertical(unsafeBitmap, range, rect); - } - } - } - - private static void BlurHorizontal(UnsafeBitmap unsafeBitmap, int range, Rectangle rect) - { - int left = rect.X; - int top = rect.Y; - int right = rect.Right; - int bottom = rect.Bottom; - int halfRange = range / 2; - ColorBgra[] newColors = new ColorBgra[unsafeBitmap.Width]; - - for (int y = top; y < bottom; y++) - { - int hits = 0; - int r = 0; - int g = 0; - int b = 0; - int a = 0; - - for (int x = left - halfRange; x < right; x++) - { - int oldPixel = x - halfRange - 1; - if (oldPixel >= left) - { - ColorBgra color = unsafeBitmap.GetPixel(oldPixel, y); - - if (color.Bgra != 0) - { - r -= color.Red; - g -= color.Green; - b -= color.Blue; - a -= color.Alpha; - } - - hits--; - } - - int newPixel = x + halfRange; - if (newPixel < right) - { - ColorBgra color = unsafeBitmap.GetPixel(newPixel, y); - - if (color.Bgra != 0) - { - r += color.Red; - g += color.Green; - b += color.Blue; - a += color.Alpha; - } - - hits++; - } - - if (x >= left) - { - newColors[x] = new ColorBgra((byte)(b / hits), (byte)(g / hits), (byte)(r / hits), (byte)(a / hits)); - } - } - - for (int x = left; x < right; x++) - { - unsafeBitmap.SetPixel(x, y, newColors[x]); - } - } - } - - private static void BlurVertical(UnsafeBitmap unsafeBitmap, int range, Rectangle rect) - { - int left = rect.X; - int top = rect.Y; - int right = rect.Right; - int bottom = rect.Bottom; - int halfRange = range / 2; - ColorBgra[] newColors = new ColorBgra[unsafeBitmap.Height]; - - for (int x = left; x < right; x++) - { - int hits = 0; - int r = 0; - int g = 0; - int b = 0; - int a = 0; - - for (int y = top - halfRange; y < bottom; y++) - { - int oldPixel = y - halfRange - 1; - if (oldPixel >= top) - { - ColorBgra color = unsafeBitmap.GetPixel(x, oldPixel); - - if (color.Bgra != 0) - { - r -= color.Red; - g -= color.Green; - b -= color.Blue; - a -= color.Alpha; - } - - hits--; - } - - int newPixel = y + halfRange; - if (newPixel < bottom) - { - ColorBgra color = unsafeBitmap.GetPixel(x, newPixel); - - if (color.Bgra != 0) - { - r += color.Red; - g += color.Green; - b += color.Blue; - a += color.Alpha; - } - - hits++; - } - - if (y >= top) - { - newColors[y] = new ColorBgra((byte)(b / hits), (byte)(g / hits), (byte)(r / hits), (byte)(a / hits)); - } - } - - for (int y = top; y < bottom; y++) - { - unsafeBitmap.SetPixel(x, y, newColors[y]); - } - } - } - - #endregion - - #region 阴影 - - public static Bitmap PaintShadow(this GraphicsPath path, int width, int height, int range = 10) - { - return PaintShadow(path, width, height, Color.Black, range); - } - public static Bitmap PaintShadow(this GraphicsPath path, int width, int height, Color color, int range = 10) - { - var bmp_shadow = new Bitmap(width, height); - using (var g = Graphics.FromImage(bmp_shadow)) - { - using (var brush = new SolidBrush(color)) - { - g.FillPath(brush, path); - } - Blur(bmp_shadow, range); - } - return bmp_shadow; - } - - #endregion - - #endregion - - #region 其他 - - #region 徽标 - - public static void PaintBadge(this IControl control, Graphics g) - { - control.PaintBadge(control.ReadRectangle, g); - } - - public static void PaintBadge(this IControl control, RectangleF rect, Graphics g) - { - var color = control.BadgeBack ?? Style.Db.Error; - if (control.Badge != null) - { - using (var brush_fore = new SolidBrush(Style.Db.ErrorColor)) - { - float borsize = 1F * Config.Dpi; - using (var font = new Font(control.Font.FontFamily, control.Font.Size * control.BadgeSize)) - { - if (string.IsNullOrEmpty(control.Badge) || control.Badge == "" || control.Badge == " ") - { - var size = (int)Math.Floor(g.MeasureString(Config.NullText, font).Width / 2); - var rect_badge = new RectangleF(rect.Right - size - control.BadgeOffsetX * Config.Dpi, control.BadgeOffsetY * Config.Dpi, size, size); - - using (var brush = new SolidBrush(color)) - { - if (control.BadgeMode) - { - float b2 = borsize * 2, rr = size * 0.2F, rr2 = rr * 2; - g.FillEllipse(brush_fore, new RectangleF(rect_badge.X - borsize, rect_badge.Y - borsize, rect_badge.Width + b2, rect_badge.Height + b2)); - using (var path = rect_badge.RoundPath(1, true)) - { - path.AddEllipse(new RectangleF(rect_badge.X + rr, rect_badge.Y + rr, rect_badge.Width - rr2, rect_badge.Height - rr2)); - g.FillPath(brush, path); - } - } - else - { - g.FillEllipse(brush, rect_badge); - using (var pen = new Pen(brush_fore.Color, borsize)) - { - g.DrawEllipse(pen, rect_badge); - } - } - } - } - else - { - var size = g.MeasureString(control.Badge, font); - var size_badge = size.Height * 1.2F; - if (size.Height > size.Width) - { - var rect_badge = new RectangleF(rect.Right - size_badge - control.BadgeOffsetX * Config.Dpi, control.BadgeOffsetY * Config.Dpi, size_badge, size_badge); - using (var brush = new SolidBrush(color)) - { - g.FillEllipse(brush, rect_badge); - using (var pen = new Pen(brush_fore.Color, borsize)) - { - g.DrawEllipse(pen, rect_badge); - } - } - g.DrawStr(control.Badge, font, brush_fore, rect_badge, stringFormatCenter2); - } - else - { - var w_badge = size.Width * 1.2F; - var rect_badge = new RectangleF(rect.Right - w_badge - control.BadgeOffsetX * Config.Dpi, control.BadgeOffsetY * Config.Dpi, w_badge, size_badge); - using (var brush = new SolidBrush(color)) - { - using (var path = rect_badge.RoundPath(rect_badge.Height)) - { - g.FillPath(brush, path); - using (var pen = new Pen(brush_fore.Color, borsize)) - { - g.DrawPath(pen, path); - } - } - } - g.DrawStr(control.Badge, font, brush_fore, rect_badge, stringFormatCenter2); - } - } - } - } - } - } - - public static void PaintBadge(this IControl control, DateBadge badge, Font font, RectangleF rect, Graphics g) - { - var color = badge.Fill ?? control.BadgeBack ?? Style.Db.Error; - using (var brush_fore = new SolidBrush(Style.Db.ErrorColor)) - { - float borsize = 1F * Config.Dpi; - if (badge.Count == 0) - { - var rect_badge = new RectangleF(rect.Right - 10F, rect.Top + 2F, 8, 8); - using (var brush = new SolidBrush(color)) - { - g.FillEllipse(brush, rect_badge); - using (var pen = new Pen(brush_fore.Color, borsize)) - { - g.DrawEllipse(pen, rect_badge); - } - } - } - else - { - string countStr; - if (badge.Count == 999) countStr = "999"; - else if (badge.Count > 1000) countStr = (badge.Count / 1000).ToString().Substring(0, 1) + "K+"; - else if (badge.Count > 99) countStr = "99+"; - else countStr = badge.Count.ToString(); - - var size = g.MeasureString(countStr, font); - var size_badge = size.Height * 1.2F; - if (size.Height > size.Width) - { - var rect_badge = new RectangleF(rect.Right - size_badge + 6F, rect.Top - 8F, size_badge, size_badge); - using (var brush = new SolidBrush(color)) - { - g.FillEllipse(brush, rect_badge); - using (var pen = new Pen(brush_fore.Color, borsize)) - { - g.DrawEllipse(pen, rect_badge); - } - } - g.DrawStr(countStr, font, brush_fore, rect_badge, stringFormatCenter2); - } - else - { - var w_badge = size.Width * 1.2F; - var rect_badge = new RectangleF(rect.Right - w_badge + 6F, rect.Top - 8F, w_badge, size_badge); - using (var brush = new SolidBrush(color)) - { - using (var path = rect_badge.RoundPath(rect_badge.Height)) - { - g.FillPath(brush, path); - using (var pen = new Pen(brush_fore.Color, borsize)) - { - g.DrawPath(pen, path); - } - } - } - g.DrawStr(countStr, font, brush_fore, rect_badge, stringFormatCenter2); - } - } - } - } - - #endregion - - public static void PaintShadow(this Graphics g, ShadowConfig config, Rectangle _rect, Rectangle rect, float radius, bool round) - { - int shadow = (int)(config.Shadow * Config.Dpi), shadowOffsetX = (int)(config.ShadowOffsetX * Config.Dpi), shadowOffsetY = (int)(config.ShadowOffsetY * Config.Dpi); - using (var bmp_shadow = new Bitmap(_rect.Width, _rect.Height)) - { - using (var g_shadow = Graphics.FromImage(bmp_shadow)) - { - using (var path = RoundPath(rect, radius, round)) - { - using (var brush = config.ShadowColor.Brush(Style.Db.TextBase)) - { - g_shadow.FillPath(brush, path); - } - } - Blur(bmp_shadow, shadow); - } - using (var attributes = new ImageAttributes()) - { - var matrix = new ColorMatrix - { - Matrix33 = config.ShadowOpacity - }; - attributes.SetColorMatrix(matrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap); - g.DrawImage(bmp_shadow, new Rectangle(_rect.X + shadowOffsetX, _rect.Y + shadowOffsetY, _rect.Width, _rect.Height), 0, 0, _rect.Width, _rect.Height, GraphicsUnit.Pixel, attributes); - } - } - } - - #endregion - - public static float Calculate(this float val, float add) - { - return (float)Math.Round(val + add, 3); - } - - /// - /// SizeF转Size(向上取整) - /// - /// SizeF - public static Size Size(this SizeF size) - { - return new Size((int)Math.Ceiling(size.Width), (int)Math.Ceiling(size.Height)); - } - - /// - /// SizeF转Size(向上取整) - /// - /// SizeF - public static Size Size(this SizeF size, float p) - { - return new Size((int)Math.Ceiling(size.Width + p), (int)Math.Ceiling(size.Height + p)); - } - - public static Color ToColor(float alpha, Color color) - { - return ToColor((int)alpha, color); - } - - public static Color ToColorN(float val, Color color) - { - return ToColor((int)(val * color.A), color); - } - - public static Color ToColor(int alpha, Color color) - { - if (alpha > 255) alpha = 255; - else if (alpha < 0) alpha = 0; - return Color.FromArgb(alpha, color); - } - - #region DPI - - internal static void DpiAuto(float dpi, Control control) - { - var dir = DpiSuspend(control.Controls); - if (control is Form form) DpiLS(dpi, form); - else DpiLS(dpi, control); - DpiResume(dir, control.Controls); - } - - static Dictionary DpiSuspend(Control.ControlCollection controls) - { - var dir = new Dictionary(controls.Count); - foreach (Control control in controls) - { - if (control.Dock != DockStyle.None || control.Anchor != (AnchorStyles.Left | AnchorStyles.Top)) dir.Add(control, new AnchorDock(control)); - if (controls.Count > 0) DpiSuspend(ref dir, control.Controls); - } - return dir; - } - static void DpiSuspend(ref Dictionary dir, Control.ControlCollection controls) - { - foreach (Control control in controls) - { - if (control.Dock != DockStyle.None || control.Anchor != (AnchorStyles.Left | AnchorStyles.Top)) dir.Add(control, new AnchorDock(control)); - if (controls.Count > 0) DpiSuspend(ref dir, control.Controls); - } - } - - static void DpiResume(Dictionary dir, Control.ControlCollection controls) - { - foreach (Control control in controls) - { - if (dir.TryGetValue(control, out var find)) - { - control.Dock = find.Dock; - control.Anchor = find.Anchor; - } - if (controls.Count > 0) DpiResume(dir, control.Controls); - } - } - - static void DpiLS(float dpi, Control control) - { - var size = new Size((int)(control.Width * dpi), (int)(control.Height * dpi)); - var point = new Point((int)(control.Left * dpi), (int)(control.Top * dpi)); - - if (!control.MinimumSize.IsEmpty) control.MinimumSize = new Size((int)(control.MinimumSize.Width * dpi), (int)(control.MinimumSize.Height * dpi)); - if (!control.MaximumSize.IsEmpty) control.MaximumSize = new Size((int)(control.MaximumSize.Width * dpi), (int)(control.MaximumSize.Height * dpi)); - control.Padding = SetPadding(dpi, control.Padding); - control.Margin = SetPadding(dpi, control.Margin); - control.Size = size; - control.Location = point; - if (control is TableLayoutPanel tableLayout) - { - foreach (ColumnStyle it in tableLayout.ColumnStyles) - { - if (it.SizeType == SizeType.Absolute) it.Width = it.Width * dpi; - } - foreach (RowStyle it in tableLayout.RowStyles) - { - if (it.SizeType == SizeType.Absolute) it.Height = it.Height * dpi; - } - } - else if (control is TabControl tab && tab.ItemSize.Width > 1 && tab.ItemSize.Height > 1) - { - tab.ItemSize = new Size((int)(tab.ItemSize.Width * dpi), (int)(tab.ItemSize.Height * dpi)); - } - else if (control is Panel panel) panel.padding = SetPadding(dpi, panel.padding); - DpiLSS(dpi, control); - } - static void DpiLS(float dpi, Form form) - { - Size size; - Point point; - var csize = form.ClientSize; - size = new Size((int)(csize.Width * dpi), (int)(csize.Height * dpi)); - var screen = Screen.FromPoint(form.Location); - if (size.Width > screen.WorkingArea.Width && size.Height > screen.WorkingArea.Height) - { - if (form.Width > screen.WorkingArea.Width && form.Height > screen.WorkingArea.Height) - { - size = screen.WorkingArea.Size; - point = screen.WorkingArea.Location; - } - else - { - size = form.Size; - point = form.Location; - } - } - else - { - if (size.Width > screen.WorkingArea.Width) size.Width = screen.WorkingArea.Width; - if (size.Height > screen.WorkingArea.Height) size.Height = screen.WorkingArea.Height; - point = new Point(form.Left + (form.Width - size.Width) / 2, form.Top + (form.Height - size.Height) / 2); - if (point.X < 0 || point.Y < 0) point = form.Location; - } - - if (!form.MinimumSize.IsEmpty) form.MinimumSize = new Size((int)(form.MinimumSize.Width * dpi), (int)(form.MinimumSize.Height * dpi)); - if (!form.MaximumSize.IsEmpty) form.MaximumSize = new Size((int)(form.MaximumSize.Width * dpi), (int)(form.MaximumSize.Height * dpi)); - form.Padding = SetPadding(dpi, form.Padding); - form.Margin = SetPadding(dpi, form.Margin); - - DpiLSS(dpi, form); - form.ClientSize = size; - form.Location = point; - } - - static void DpiLSS(float dpi, Control control) - { - if (control.Controls.Count > 0) - { - if (control is Pagination || control is Input) return; - foreach (Control it in control.Controls) DpiLS(dpi, it); - } - } - - internal static Padding SetPadding(float dpi, Padding padding) - { - if (padding.All == 0) return padding; - else if (padding.All > 0) return new Padding((int)(padding.All * dpi)); - else return new Padding((int)(padding.Left * dpi), (int)(padding.Top * dpi), (int)(padding.Right * dpi), (int)(padding.Bottom * dpi)); - } - - #endregion - - public static Form? FindPARENT(this Control? control) - { - if (control == null) return null; - if (control is DoubleBufferForm formd) - { - if (control.Tag is Form form) return form; - else if (control.Parent != null) return FindPARENT(control.Parent); - return formd; - } - else if (control is Form form) return form; - else if (control.Parent != null) return FindPARENT(control.Parent); - return null; - } - public static bool SetTopMost(this Control? control, IntPtr hand) - { - var form = control.FindPARENT(); - if (form != null && form.TopMost) - { - SetTopMost(hand); - return true; - } - return false; - } - - public static void SetTopMost(IntPtr hand) - { - Vanara.PInvoke.User32.SetWindowPos(hand, new IntPtr(-1), 0, 0, 0, 0, Vanara.PInvoke.User32.SetWindowPosFlags.SWP_NOACTIVATE); - } - - public static SolidBrush Brush(this Color? color, Color default_color) - { - if (color.HasValue) return new SolidBrush(color.Value); - return new SolidBrush(default_color); - } - - public static SolidBrush Brush(this Color? color, Color default_color, Color enabled_color, bool enabled) - { - if (enabled) - { - if (color.HasValue) return new SolidBrush(color.Value); - return new SolidBrush(default_color); - } - else return new SolidBrush(enabled_color); - } - - #region 获取OS版本 - -#if NET40 || NET46 || NET48 - public static Version OSVersion - { - get - { - try - { - var osVersionInfo = new OSVERSIONINFOEX { OSVersionInfoSize = System.Runtime.InteropServices.Marshal.SizeOf(typeof(OSVERSIONINFOEX)) }; - if (RtlGetVersion(ref osVersionInfo) == 0) return new Version(osVersionInfo.MajorVersion, osVersionInfo.MinorVersion, osVersionInfo.BuildNumber); - } - catch { } - return Environment.OSVersion.Version; - } - } - - [System.Runtime.InteropServices.DllImport("ntdll.dll", SetLastError = true, CharSet = System.Runtime.InteropServices.CharSet.Unicode)] - internal static extern int RtlGetVersion(ref OSVERSIONINFOEX versionInfo); - - internal struct OSVERSIONINFOEX - { - internal int OSVersionInfoSize; - internal int MajorVersion; - internal int MinorVersion; - internal int BuildNumber; - internal int PlatformId; - [System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValTStr, SizeConst = 128)] - internal string CSDVersion; - internal ushort ServicePackMajor; - internal ushort ServicePackMinor; - internal short SuiteMask; - internal byte ProductType; - internal byte Reserved; - } -#else - public static Version OSVersion - { - get => Environment.OSVersion.Version; - } -#endif - - public static bool OSVersionWin11 - { - get - { - var version = OSVersion; - if (version.Major >= 10 && version.Build > 22000) return true; - return false; - } - } - - #endregion - - /// - /// 叠加蒙版 - /// - /// 父窗口 - public static ILayeredFormOpacity FormMask(this Form owner) - { - var mask = new LayeredFormMask(owner); - mask.Show(owner); - return mask; - } - - /// - /// 叠加蒙版(可关闭) - /// - /// 父窗口 - /// 点击蒙层是否允许关闭 - /// 操作对象 - public static ILayeredFormOpacity FormMask(this Form owner, bool MaskClosable, ILayeredForm form) - { - var mask = new LayeredFormMask(owner); - if (MaskClosable) - { - try - { - mask.Click += (s1, e1) => - { - form.IClose(); - }; - } - catch { } - } - mask.Show(owner); - return mask; - } - - /// - /// 叠加蒙版(可关闭) - /// - /// 父窗口 - /// 点击蒙层是否允许关闭 - /// 操作对象 - public static ILayeredFormOpacity FormMask(this Form owner, bool MaskClosable, Form form) - { - var mask = new LayeredFormMask(owner); - if (MaskClosable) - { - try - { - mask.Click += (s1, e1) => - { - form.Close(); - }; - } - catch { } - } - mask.Show(owner); - return mask; - } - - public static bool Wait(this System.Threading.WaitHandle handle) - { - try - { - handle.WaitOne(); - return false; - } - catch - { - return true; - } - } - - public static bool Wait(this System.Threading.CancellationTokenSource? token) - { - try - { - if (token == null || token.IsCancellationRequested) return true; - return false; - } - catch - { - return true; - } - } - - public static bool Wait(this System.Threading.CancellationTokenSource? token, Control control) - { - try - { - if (token == null || token.IsCancellationRequested || control.IsDisposed) return true; - return false; - } - catch - { - return true; - } - } - - public static bool ListExceed(this IList? list, int index) - { - if (list == null || list.Count <= index || index < 0) return true; - return false; - } - - public static bool DateExceed(DateTime date, DateTime? min, DateTime? max) - { - if (min.HasValue && min.Value >= date) return false; - if (max.HasValue && max.Value <= date) return false; - return true; - } - - public static bool DateExceedRelax(DateTime date, DateTime? min, DateTime? max) - { - if (min.HasValue && min.Value > date) return false; - if (max.HasValue && max.Value < date) return false; - return true; - } - - #region 剪贴板 - - public static string? ClipboardGetText(this Control control) - { - if (control.InvokeRequired) - { - string? r = null; - control.Invoke(new Action(() => - { - r = ClipboardGetText(); - })); - return r; - } - return ClipboardGetText(); - } - public static string? ClipboardGetText() - { - try - { - return Clipboard.GetText(); - } - catch - { - return Win32.GetClipBoardText(); - } - } - public static bool ClipboardSetText(this Control control, string? text) - { - if (control.InvokeRequired) - { - bool r = false; - control.Invoke(new Action(() => - { - r = ClipboardSetText(text); - })); - return r; - } - return ClipboardSetText(text); - } - public static bool ClipboardSetText(string? text) - { - try - { - if (text == null) Clipboard.Clear(); - else Clipboard.SetText(text); - return true; - } - catch - { - if (Win32.SetClipBoardText(text)) return true; - } - return false; - } - - #endregion - } - - internal class AnchorDock - { - public AnchorDock(Control control) - { - Dock = control.Dock; - Anchor = control.Anchor; - control.Dock = DockStyle.None; - control.Anchor = AnchorStyles.Left | AnchorStyles.Top; - } - public DockStyle Dock { get; set; } - public AnchorStyles Anchor { get; set; } - } - - public class RectTextLR - { - public Rectangle text { get; set; } - public Rectangle l { get; set; } - public Rectangle r { get; set; } - } -} \ No newline at end of file diff --git a/src/AntdUI/Lib/Helper/Helper.DPI.cs b/src/AntdUI/Lib/Helper/Helper.DPI.cs new file mode 100644 index 00000000..24f14e30 --- /dev/null +++ b/src/AntdUI/Lib/Helper/Helper.DPI.cs @@ -0,0 +1,174 @@ +// 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.Collections.Generic; +using System.Drawing; +using System.Windows.Forms; + +namespace AntdUI +{ + partial class Helper + { + internal static void DpiAuto(float dpi, Control control) + { + if (dpi == 1F) + { + if (control is Window window && window.StartPosition == FormStartPosition.CenterScreen) + { + var size = window.sizeInit ?? control.Size; + var screen = Screen.FromPoint(window.Location).WorkingArea; + window.Location = new Point(screen.X + (screen.Width - size.Width) / 2, screen.Y + (screen.Height - size.Height) / 2); + } + return; + } + var dir = DpiSuspend(control.Controls); + if (control is Form form) DpiLS(dpi, form); + else DpiLS(dpi, control); + DpiResume(dir, control.Controls); + } + + static Dictionary DpiSuspend(Control.ControlCollection controls) + { + var dir = new Dictionary(controls.Count); + foreach (Control control in controls) + { + if (control.Dock != DockStyle.None || control.Anchor != (AnchorStyles.Left | AnchorStyles.Top)) dir.Add(control, new AnchorDock(control)); + if (controls.Count > 0) DpiSuspend(ref dir, control.Controls); + } + return dir; + } + static void DpiSuspend(ref Dictionary dir, Control.ControlCollection controls) + { + foreach (Control control in controls) + { + if (control.Dock != DockStyle.None || control.Anchor != (AnchorStyles.Left | AnchorStyles.Top)) dir.Add(control, new AnchorDock(control)); + if (controls.Count > 0) DpiSuspend(ref dir, control.Controls); + } + } + + static void DpiResume(Dictionary dir, Control.ControlCollection controls) + { + foreach (Control control in controls) + { + if (dir.TryGetValue(control, out var find)) + { + control.Dock = find.Dock; + control.Anchor = find.Anchor; + } + if (controls.Count > 0) DpiResume(dir, control.Controls); + } + } + + static void DpiLS(float dpi, Control control) + { + var size = new Size((int)(control.Width * dpi), (int)(control.Height * dpi)); + var point = new Point((int)(control.Left * dpi), (int)(control.Top * dpi)); + + if (!control.MinimumSize.IsEmpty) control.MinimumSize = new Size((int)(control.MinimumSize.Width * dpi), (int)(control.MinimumSize.Height * dpi)); + if (!control.MaximumSize.IsEmpty) control.MaximumSize = new Size((int)(control.MaximumSize.Width * dpi), (int)(control.MaximumSize.Height * dpi)); + control.Padding = SetPadding(dpi, control.Padding); + control.Margin = SetPadding(dpi, control.Margin); + control.Size = size; + control.Location = point; + if (control is TableLayoutPanel tableLayout) + { + foreach (ColumnStyle it in tableLayout.ColumnStyles) + { + if (it.SizeType == SizeType.Absolute) it.Width = it.Width * dpi; + } + foreach (RowStyle it in tableLayout.RowStyles) + { + if (it.SizeType == SizeType.Absolute) it.Height = it.Height * dpi; + } + } + else if (control is TabControl tab && tab.ItemSize.Width > 1 && tab.ItemSize.Height > 1) + { + tab.ItemSize = new Size((int)(tab.ItemSize.Width * dpi), (int)(tab.ItemSize.Height * dpi)); + } + else if (control is Panel panel) panel.padding = SetPadding(dpi, panel.padding); + DpiLSS(dpi, control); + } + static void DpiLS(float dpi, Form form) + { + if (form is Window window) + { + DpiLS(dpi, window, window.sizeInit ?? window.ClientSize, out var point, out var size); + Size max = window.MaximumSize, min = window.MinimumSize; + window.MaximumSize = window.MinimumSize = window.ClientSize = size; + window.Location = point; + window.MinimumSize = min; + window.MaximumSize = max; + } + else + { + DpiLS(dpi, form, form.ClientSize, out var point, out var size); + form.ClientSize = size; + form.Location = point; + } + } + + static void DpiLS(float dpi, Form form, Size csize, out Point point, out Size size) + { + size = new Size((int)(csize.Width * dpi), (int)(csize.Height * dpi)); + var screen = Screen.FromPoint(form.Location).WorkingArea; + if (size.Width > screen.Width && size.Height > screen.Height) + { + if (csize.Width > screen.Width && csize.Height > screen.Height) + { + size = screen.Size; + point = screen.Location; + } + else + { + size = csize; + point = form.Location; + } + } + else + { + if (size.Width > screen.Width) size.Width = screen.Width; + if (size.Height > screen.Height) size.Height = screen.Height; + point = new Point(form.Left + (csize.Width - size.Width) / 2, form.Top + (csize.Height - size.Height) / 2); + if (point.X < 0 || point.Y < 0) point = form.Location; + } + if (form.StartPosition == FormStartPosition.CenterScreen) point = new Point(screen.X + (screen.Width - size.Width) / 2, screen.Y + (screen.Height - size.Height) / 2); + if (!form.MinimumSize.IsEmpty) form.MinimumSize = new Size((int)(form.MinimumSize.Width * dpi), (int)(form.MinimumSize.Height * dpi)); + if (!form.MaximumSize.IsEmpty) form.MaximumSize = new Size((int)(form.MaximumSize.Width * dpi), (int)(form.MaximumSize.Height * dpi)); + form.Padding = SetPadding(dpi, form.Padding); + form.Margin = SetPadding(dpi, form.Margin); + + DpiLSS(dpi, form); + } + + static void DpiLSS(float dpi, Control control) + { + if (control.Controls.Count > 0) + { + if (control is Pagination || control is Input) return; + foreach (Control it in control.Controls) DpiLS(dpi, it); + } + } + + internal static Padding SetPadding(float dpi, Padding padding) + { + if (padding.All == 0) return padding; + else if (padding.All > 0) return new Padding((int)(padding.All * dpi)); + else return new Padding((int)(padding.Left * dpi), (int)(padding.Top * dpi), (int)(padding.Right * dpi), (int)(padding.Bottom * dpi)); + } + } +} \ No newline at end of file diff --git a/src/AntdUI/Lib/Helper/Helper.GDI.cs b/src/AntdUI/Lib/Helper/Helper.GDI.cs new file mode 100644 index 00000000..ccb14c64 --- /dev/null +++ b/src/AntdUI/Lib/Helper/Helper.GDI.cs @@ -0,0 +1,1044 @@ +// 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.Drawing; +using System.Drawing.Drawing2D; +using System.Drawing.Imaging; + +namespace AntdUI +{ + partial class Helper + { + #region 文本布局 + + /// + /// 文本布局 + /// + /// 垂直(上下) + /// 水平(前后) + public static StringFormat SF(StringAlignment tb = StringAlignment.Center, StringAlignment lr = StringAlignment.Center) + { + return new StringFormat(StringFormat.GenericTypographic) { LineAlignment = tb, Alignment = lr }; + } + + /// + /// 文本布局(不换行) + /// + /// 垂直(上下) + /// 水平(前后) + public static StringFormat SF_NoWrap(StringAlignment tb = StringAlignment.Center, StringAlignment lr = StringAlignment.Center) + { + var sf = new StringFormat(StringFormat.GenericTypographic) { LineAlignment = tb, Alignment = lr }; + sf.FormatFlags |= StringFormatFlags.NoWrap; + return sf; + } + + /// + /// 文本布局(超出省略号) + /// + /// 垂直(上下) + /// 水平(前后) + public static StringFormat SF_Ellipsis(StringAlignment tb = StringAlignment.Center, StringAlignment lr = StringAlignment.Center) + { + return new StringFormat(StringFormat.GenericTypographic) { LineAlignment = tb, Alignment = lr, Trimming = StringTrimming.EllipsisCharacter }; + } + + /// + /// 文本布局(超出省略号+不换行) + /// + /// 垂直(上下) + /// 水平(前后) + public static StringFormat SF_ALL(StringAlignment tb = StringAlignment.Center, StringAlignment lr = StringAlignment.Center) + { + var sf = new StringFormat(StringFormat.GenericTypographic) { LineAlignment = tb, Alignment = lr, Trimming = StringTrimming.EllipsisCharacter }; + sf.FormatFlags |= StringFormatFlags.NoWrap; + return sf; + } + + public static StringFormat SF_MEASURE_FONT() + { + var sf = new StringFormat(StringFormat.GenericTypographic) { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center }; + sf.FormatFlags |= StringFormatFlags.MeasureTrailingSpaces; + return sf; + } + + #endregion + + /// + /// 画刷(渐变色) + /// + /// 渐变代码H5 + /// 区域 + /// 默认颜色 + public static Brush BrushEx(this string? code, Rectangle rect, Color def) + { + if (code != null) + { + var arr = code.Split(','); + if (arr.Length > 1) + { + if (arr.Length > 2 && float.TryParse(arr[0], out float deg)) return new LinearGradientBrush(rect, arr[1].Trim().ToColor(), arr[2].Trim().ToColor(), 270 + deg); + else return new LinearGradientBrush(rect, arr[0].Trim().ToColor(), arr[1].Trim().ToColor(), 270F); + } + } + return new SolidBrush(def); + } + + public static Graphics High(this Graphics g) + { + Config.SetDpi(g); + g.SmoothingMode = SmoothingMode.AntiAlias; + g.InterpolationMode = InterpolationMode.HighQualityBicubic; + g.PixelOffsetMode = PixelOffsetMode.HighQuality; + if (Config.TextRenderingHint.HasValue) g.TextRenderingHint = Config.TextRenderingHint.Value; + return g; + } + public static Graphics HighLay(this Graphics g) + { + Config.SetDpi(g); + g.SmoothingMode = SmoothingMode.AntiAlias; + g.InterpolationMode = InterpolationMode.HighQualityBicubic; + g.PixelOffsetMode = PixelOffsetMode.HighQuality; + g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias; + return g; + } + + public static void GDI(Action action) + { + using (var bmp = new Bitmap(1, 1)) + { + using (var g = Graphics.FromImage(bmp)) + { + Config.SetDpi(g); + action(g); + } + } + } + + public static T GDI(Func action) + { + using (var bmp = new Bitmap(1, 1)) + { + using (var g = Graphics.FromImage(bmp)) + { + Config.SetDpi(g); + return action(g); + } + } + } + + public static SolidBrush Brush(this Color? color, Color default_color) + { + if (color.HasValue) return new SolidBrush(color.Value); + return new SolidBrush(default_color); + } + + public static SolidBrush Brush(this Color? color, Color default_color, Color enabled_color, bool enabled) + { + if (enabled) + { + if (color.HasValue) return new SolidBrush(color.Value); + return new SolidBrush(default_color); + } + else return new SolidBrush(enabled_color); + } + + #region 圆角 + + public static GraphicsPath RoundPath(this Rectangle rect, float radius) + { + return RoundPathCore(rect, radius); + } + + public static GraphicsPath RoundPath(this RectangleF rect, float radius) + { + return RoundPathCore(rect, radius); + } + + internal static GraphicsPath RoundPath(this RectangleF rect, float radius, TShape shape) + { + return RoundPath(rect, radius, shape == TShape.Round); + } + + internal static GraphicsPath RoundPath(this Rectangle rect, float radius, bool round) + { + if (round) return CapsulePathCore(rect); + return RoundPathCore(rect, radius); + } + + internal static GraphicsPath RoundPath(this RectangleF rect, float radius, bool round) + { + if (round) return CapsulePathCore(rect); + return RoundPathCore(rect, radius); + } + + internal static GraphicsPath RoundPath(this Rectangle rect, float radius, TAlignMini shadowAlign) + { + switch (shadowAlign) + { + case TAlignMini.Top: return RoundPath(rect, radius, true, true, false, false); + case TAlignMini.Bottom: return RoundPath(rect, radius, false, false, true, true); + case TAlignMini.Left: return RoundPath(rect, radius, true, false, false, true); + case TAlignMini.Right: return RoundPath(rect, radius, false, true, true, false); + case TAlignMini.None: + default: return RoundPathCore(rect, radius); + } + } + + /// + /// 自定义圆角 + /// + /// 区域 + /// 圆角大小 + /// ↖ + /// ↗ + /// ↘ + /// ↙ + public static GraphicsPath RoundPath(this Rectangle rect, float radius, bool TL, bool TR, bool BR, bool BL) + { + var path = new GraphicsPath(); + if (radius <= 0F) path.AddRectangle(rect); + else + { + float diameter = radius * 2F; + var arc = new RectangleF(rect.X, rect.Y, diameter, diameter); + + // TL + if (TL) path.AddArc(arc, 180, 90); + else path.AddLine(rect.X, rect.Y, rect.Right - diameter, rect.Y); + + // TR + arc.X = rect.Right - diameter; + if (TR) path.AddArc(arc, 270, 90); + else path.AddLine(rect.Right, rect.Y, rect.Right, rect.Bottom - diameter); + + // BR + arc.Y = rect.Bottom - diameter; + if (BR) path.AddArc(arc, 0, 90); + else path.AddLine(rect.Right, rect.Bottom, rect.X + diameter, rect.Bottom); + + // BL + arc.X = rect.Left; + if (BL) path.AddArc(arc, 90, 90); + else path.AddLine(rect.X, rect.Bottom, rect.X, rect.Y + diameter); + + path.CloseFigure(); + } + return path; + } + + /// + /// 自定义圆角 + /// + /// 区域 + /// 圆角大小 + /// ↖ + /// ↗ + /// ↘ + /// ↙ + public static GraphicsPath RoundPath(this RectangleF rect, float radius, bool TL, bool TR, bool BR, bool BL) + { + var path = new GraphicsPath(); + if (radius <= 0F) path.AddRectangle(rect); + else + { + float diameter = radius * 2F; + var arc = new RectangleF(rect.X, rect.Y, diameter, diameter); + + // TL + if (TL) path.AddArc(arc, 180, 90); + else path.AddLine(rect.X, rect.Y, rect.Right - diameter, rect.Y); + + // TR + arc.X = rect.Right - diameter; + if (TR) path.AddArc(arc, 270, 90); + else path.AddLine(rect.Right, rect.Y, rect.Right, rect.Bottom - diameter); + + // BR + arc.Y = rect.Bottom - diameter; + if (BR) path.AddArc(arc, 0, 90); + else path.AddLine(rect.Right, rect.Bottom, rect.X + diameter, rect.Bottom); + + // BL + arc.X = rect.Left; + if (BL) path.AddArc(arc, 90, 90); + else path.AddLine(rect.X, rect.Bottom, rect.X, rect.Y + diameter); + + path.CloseFigure(); + } + return path; + } + + static GraphicsPath RoundPathCore(RectangleF rect, float radius) + { + var path = new GraphicsPath(); + if (radius > 0F) + { + if (radius >= (Math.Min(rect.Width, rect.Height) / 2F)) AddCapsule(path, rect); + else + { + float diameter = radius * 2F; + var arc = new RectangleF(rect.X, rect.Y, diameter, diameter); + + // TL + path.AddArc(arc, 180, 90); + + // TR + arc.X = rect.Right - diameter; + path.AddArc(arc, 270, 90); + + // BR + arc.Y = rect.Bottom - diameter; + path.AddArc(arc, 0, 90); + + // BL + arc.X = rect.Left; + path.AddArc(arc, 90, 90); + + path.CloseFigure(); + } + } + else path.AddRectangle(rect); + return path; + } + static GraphicsPath CapsulePathCore(RectangleF rect) + { + var path = new GraphicsPath(); + AddCapsule(path, rect); + return path; + } + static void AddCapsule(GraphicsPath path, RectangleF rect) + { + float diameter; + RectangleF arc; + if (rect.Width > 0 && rect.Height > 0) + { + if (rect.Width > rect.Height) + { + // Horizontal capsule + diameter = rect.Height; + SizeF sizeF = new SizeF(diameter, diameter); + arc = new RectangleF(rect.Location, sizeF); + path.AddArc(arc, 90, 180); + arc.X = rect.Right - diameter; + path.AddArc(arc, 270, 180); + } + else if (rect.Width < rect.Height) + { + // Vertical capsule + diameter = rect.Width; + SizeF sizeF = new SizeF(diameter, diameter); + arc = new RectangleF(rect.Location, sizeF); + path.AddArc(arc, 180, 180); + arc.Y = rect.Bottom - diameter; + path.AddArc(arc, 0, 180); + } + else + { + // Circle + path.AddEllipse(rect); + } + } + else path.AddEllipse(rect); + path.CloseFigure(); + } + + #endregion + + #region 图片渲染 + + public static void PaintImg(this Graphics g, RectangleF rect, Image image, TFit fit, float radius, bool round) + { + if (round || radius > 0) + { + using (var bmp = new Bitmap((int)rect.Width, (int)rect.Height)) + { + using (var g2 = Graphics.FromImage(bmp).High()) + { + PaintImg(g2, new RectangleF(0, 0, rect.Width, rect.Height), image, fit); + } + using (var brush = new TextureBrush(bmp, WrapMode.Clamp)) + { + brush.TranslateTransform(rect.X, rect.Y); + if (round) g.FillEllipse(brush, rect); + else + { + using (var path = rect.RoundPath(radius)) + { + g.FillPath(brush, path); + } + } + } + } + } + else PaintImg(g, rect, image, fit); + } + public static void PaintImg(this Graphics g, RectangleF rect, Image image, TFit fit, float radius, TShape shape) + { + if (shape == TShape.Circle || shape == TShape.Round || radius > 0) + { + using (var bmp = new Bitmap((int)rect.Width, (int)rect.Height)) + { + using (var g2 = Graphics.FromImage(bmp).High()) + { + PaintImg(g2, new RectangleF(0, 0, rect.Width, rect.Height), image, fit); + } + using (var brush = new TextureBrush(bmp, WrapMode.Clamp)) + { + brush.TranslateTransform(rect.X, rect.Y); + if (shape == TShape.Circle) g.FillEllipse(brush, rect); + else + { + using (var path = rect.RoundPath(radius)) + { + g.FillPath(brush, path); + } + } + } + } + } + else PaintImg(g, rect, image, fit); + } + + internal static void PaintImg(this Graphics g, RectangleF rect, Image image, TFit fit) + { + switch (fit) + { + case TFit.Fill: + g.DrawImage(image, rect); + break; + case TFit.None: + g.DrawImage(image, new RectangleF(rect.X + (rect.Width - image.Width) / 2, rect.Y + (rect.Height - image.Height) / 2, image.Width, image.Height)); + break; + case TFit.Contain: + PaintImgContain(g, image, rect); + break; + case TFit.Cover: + PaintImgCover(g, image, rect); + break; + } + } + internal static void PaintImgCover(this Graphics g, Image image, RectangleF rect) + { + float originWidth = image.Width, originHeight = image.Height; + if (originWidth == originHeight) + { + if (rect.Width == rect.Height) g.DrawImage(image, rect); + else if (rect.Width > rect.Height) g.DrawImage(image, new RectangleF(0, (rect.Height - rect.Width) / 2, rect.Width, rect.Width)); + else g.DrawImage(image, new RectangleF((rect.Width - rect.Height) / 2, 0, rect.Height, rect.Height)); + return; + } + float destWidth = rect.Width, destHeight = rect.Height; + float currentWidth, currentHeight; + if ((originWidth * destHeight) > (originHeight * destWidth)) + { + currentHeight = destHeight; + currentWidth = (originWidth * destHeight) / originHeight; + } + else + { + currentWidth = destWidth; + currentHeight = (destWidth * originHeight) / originWidth; + } + g.DrawImage(image, new RectangleF(rect.X + (destWidth - currentWidth) / 2, rect.Y + (destHeight - currentHeight) / 2, currentWidth, currentHeight), new RectangleF(0, 0, originWidth, originHeight), GraphicsUnit.Pixel); + } + internal static void PaintImgContain(this Graphics g, Image image, RectangleF rect) + { + float originWidth = image.Width, originHeight = image.Height; + if (originWidth == originHeight) + { + if (rect.Width == rect.Height) g.DrawImage(image, rect); + else if (rect.Width > rect.Height) g.DrawImage(image, new RectangleF((rect.Width - rect.Height) / 2, 0, rect.Height, rect.Height)); + else g.DrawImage(image, new RectangleF(0, (rect.Height - rect.Width) / 2, rect.Width, rect.Width)); + return; + } + float destWidth = rect.Width, destHeight = rect.Height; + float currentWidth, currentHeight; + if ((originWidth * destHeight) > (originHeight * destWidth)) + { + currentWidth = destWidth; + currentHeight = (destWidth * originHeight) / originWidth; + } + else + { + currentHeight = destHeight; + currentWidth = (originWidth * destHeight) / originHeight; + } + g.DrawImage(image, new RectangleF(rect.X + (destWidth - currentWidth) / 2, rect.Y + (destHeight - currentHeight) / 2, currentWidth, currentHeight), new RectangleF(0, 0, originWidth, originHeight), GraphicsUnit.Pixel); + } + + #endregion + + #region 图标渲染 + + internal static void PaintIcons(this Graphics g, TType icon, Rectangle rect) + { + switch (icon) + { + case TType.Success: + using (var bmp = SvgExtend.GetImgExtend(SvgDb.IcoSuccess, rect, Style.Db.Success)) + { + if (bmp == null) return; + g.DrawImage(bmp, rect); + } + break; + case TType.Info: + using (var bmp = SvgExtend.GetImgExtend(SvgDb.IcoInfo, rect, Style.Db.Info)) + { + if (bmp == null) return; + g.DrawImage(bmp, rect); + } + break; + case TType.Warn: + using (var bmp = SvgExtend.GetImgExtend(SvgDb.IcoWarn, rect, Style.Db.Warning)) + { + if (bmp == null) return; + g.DrawImage(bmp, rect); + } + break; + case TType.Error: + using (var bmp = SvgExtend.GetImgExtend(SvgDb.IcoError, rect, Style.Db.Error)) + { + if (bmp == null) return; + g.DrawImage(bmp, rect); + } + break; + } + } + internal static void PaintIcons(this Graphics g, TType icon, Rectangle rect, Color back) + { + using (var brush = new SolidBrush(back)) + { + g.FillEllipse(brush, new Rectangle(rect.X + 1, rect.Y + 1, rect.Width - 2, rect.Height - 2)); + } + switch (icon) + { + case TType.Success: + using (var bmp = SvgExtend.GetImgExtend(SvgDb.IcoSuccess, rect, Style.Db.Success)) + { + if (bmp == null) return; + g.DrawImage(bmp, rect); + } + break; + case TType.Info: + using (var bmp = SvgExtend.GetImgExtend(SvgDb.IcoInfo, rect, Style.Db.Info)) + { + if (bmp == null) return; + g.DrawImage(bmp, rect); + } + break; + case TType.Warn: + using (var bmp = SvgExtend.GetImgExtend(SvgDb.IcoWarn, rect, Style.Db.Warning)) + { + if (bmp == null) return; + g.DrawImage(bmp, rect); + } + break; + case TType.Error: + using (var bmp = SvgExtend.GetImgExtend(SvgDb.IcoError, rect, Style.Db.Error)) + { + if (bmp == null) return; + g.DrawImage(bmp, rect); + } + break; + } + } + internal static void PaintIconGhosts(this Graphics g, TType icon, Rectangle rect, Color color) + { + switch (icon) + { + case TType.Success: + using (var bmp = SvgExtend.GetImgExtend(SvgDb.IcoSuccessGhost, rect, color)) + { + if (bmp == null) return; + g.DrawImage(bmp, rect); + } + break; + case TType.Info: + using (var bmp = SvgExtend.GetImgExtend(SvgDb.IcoInfoGhost, rect, color)) + { + if (bmp == null) return; + g.DrawImage(bmp, rect); + } + break; + case TType.Warn: + using (var bmp = SvgExtend.GetImgExtend(SvgDb.IcoWarnGhost, rect, color)) + { + if (bmp == null) return; + g.DrawImage(bmp, rect); + } + break; + case TType.Error: + using (var bmp = SvgExtend.GetImgExtend(SvgDb.IcoErrorGhost, rect, color)) + { + if (bmp == null) return; + g.DrawImage(bmp, rect); + } + break; + } + } + internal static void PaintIconClose(this Graphics g, Rectangle rect, Color color) + { + PaintIconCore(g, rect, SvgDb.IcoErrorGhost, color); + } + internal static void PaintIconClose(this Graphics g, Rectangle rect, Color color, float dot) + { + PaintIconCore(g, rect, SvgDb.IcoErrorGhost, color, dot); + } + + /// + /// 绘制带圆背景的镂空图标 + /// + internal static void PaintIconCoreGhost(this Graphics g, Rectangle rect, string svg, Color back, Color fore) + { + using (var brush = new SolidBrush(back)) + { + g.FillEllipse(brush, rect); + } + using (var bmp = SvgExtend.GetImgExtend(svg, rect, fore)) + { + if (bmp == null) return; + g.DrawImage(bmp, rect); + } + } + internal static void PaintIconCore(this Graphics g, Rectangle rect, string svg, Color back, Color fore) + { + using (var brush = new SolidBrush(back)) + { + g.FillEllipse(brush, new Rectangle(rect.X + 1, rect.Y + 1, rect.Width - 2, rect.Height - 2)); + } + using (var bmp = SvgExtend.GetImgExtend(svg, rect, fore)) + { + if (bmp == null) return; + g.DrawImage(bmp, rect); + } + } + internal static void PaintIconCore(this Graphics g, Rectangle rect, string svg, Color color) + { + using (var bmp = SvgExtend.GetImgExtend(svg, rect, color)) + { + if (bmp == null) return; + g.DrawImage(bmp, rect); + } + } + internal static void PaintIconCore(this Graphics g, Rectangle rect, string svg, Color color, float dot) + { + int size = (int)(rect.Height * dot); + var rect_ico = new Rectangle(rect.X + (rect.Width - size) / 2, rect.Y + (rect.Height - size) / 2, size, size); + using (var bmp = SvgExtend.GetImgExtend(svg, rect_ico, color)) + { + if (bmp == null) return; + g.DrawImage(bmp, rect_ico); + } + } + + #endregion + + #region 图片透明度 + + public static void DrawImage(this Graphics g, Bitmap bmp, Rectangle rect, float opacity) + { + using (var attributes = new ImageAttributes()) + { + var matrix = new ColorMatrix { Matrix33 = opacity }; + attributes.SetColorMatrix(matrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap); + g.DrawImage(bmp, rect, 0, 0, bmp.Width, bmp.Height, GraphicsUnit.Pixel, attributes); + } + } + + public static void DrawImage(this Graphics g, Image bmp, Rectangle rect, float opacity) + { + if (opacity == 1F) + { + g.DrawImage(bmp, rect); + return; + } + using (var attributes = new ImageAttributes()) + { + var matrix = new ColorMatrix { Matrix33 = opacity }; + attributes.SetColorMatrix(matrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap); + g.DrawImage(bmp, rect, 0, 0, bmp.Width, bmp.Height, GraphicsUnit.Pixel, attributes); + } + } + + #endregion + + #region 阴影/徽标 + + #region 徽标 + + public static void PaintBadge(this IControl control, Graphics g) + { + control.PaintBadge(control.ReadRectangle, g); + } + + public static void PaintBadge(this IControl control, RectangleF rect, Graphics g) + { + var color = control.BadgeBack ?? Style.Db.Error; + if (control.Badge != null) + { + using (var brush_fore = new SolidBrush(Style.Db.ErrorColor)) + { + float borsize = 1F * Config.Dpi; + using (var font = new Font(control.Font.FontFamily, control.Font.Size * control.BadgeSize)) + { + if (string.IsNullOrEmpty(control.Badge) || control.Badge == "" || control.Badge == " ") + { + var size = (int)Math.Floor(g.MeasureString(Config.NullText, font).Width / 2); + var rect_badge = new RectangleF(rect.Right - size - control.BadgeOffsetX * Config.Dpi, control.BadgeOffsetY * Config.Dpi, size, size); + + using (var brush = new SolidBrush(color)) + { + if (control.BadgeMode) + { + float b2 = borsize * 2, rr = size * 0.2F, rr2 = rr * 2; + g.FillEllipse(brush_fore, new RectangleF(rect_badge.X - borsize, rect_badge.Y - borsize, rect_badge.Width + b2, rect_badge.Height + b2)); + using (var path = rect_badge.RoundPath(1, true)) + { + path.AddEllipse(new RectangleF(rect_badge.X + rr, rect_badge.Y + rr, rect_badge.Width - rr2, rect_badge.Height - rr2)); + g.FillPath(brush, path); + } + } + else + { + g.FillEllipse(brush, rect_badge); + using (var pen = new Pen(brush_fore.Color, borsize)) + { + g.DrawEllipse(pen, rect_badge); + } + } + } + } + else + { + using (var s_f = SF_NoWrap()) + { + var size = g.MeasureString(control.Badge, font); + var size_badge = size.Height * 1.2F; + if (size.Height > size.Width) + { + var rect_badge = new RectangleF(rect.Right - size_badge - control.BadgeOffsetX * Config.Dpi, control.BadgeOffsetY * Config.Dpi, size_badge, size_badge); + using (var brush = new SolidBrush(color)) + { + g.FillEllipse(brush, rect_badge); + using (var pen = new Pen(brush_fore.Color, borsize)) + { + g.DrawEllipse(pen, rect_badge); + } + } + g.DrawStr(control.Badge, font, brush_fore, rect_badge, s_f); + } + else + { + var w_badge = size.Width * 1.2F; + var rect_badge = new RectangleF(rect.Right - w_badge - control.BadgeOffsetX * Config.Dpi, control.BadgeOffsetY * Config.Dpi, w_badge, size_badge); + using (var brush = new SolidBrush(color)) + { + using (var path = rect_badge.RoundPath(rect_badge.Height)) + { + g.FillPath(brush, path); + using (var pen = new Pen(brush_fore.Color, borsize)) + { + g.DrawPath(pen, path); + } + } + } + g.DrawStr(control.Badge, font, brush_fore, rect_badge, s_f); + } + } + } + } + } + } + } + + public static void PaintBadge(this IControl control, DateBadge badge, Font font, RectangleF rect, Graphics g) + { + var color = badge.Fill ?? control.BadgeBack ?? Style.Db.Error; + using (var brush_fore = new SolidBrush(Style.Db.ErrorColor)) + { + float borsize = 1F * Config.Dpi; + if (badge.Count == 0) + { + var rect_badge = new RectangleF(rect.Right - 10F, rect.Top + 2F, 8, 8); + using (var brush = new SolidBrush(color)) + { + g.FillEllipse(brush, rect_badge); + using (var pen = new Pen(brush_fore.Color, borsize)) + { + g.DrawEllipse(pen, rect_badge); + } + } + } + else + { + using (var s_f = SF_NoWrap()) + { + string countStr; + if (badge.Count == 999) countStr = "999"; + else if (badge.Count > 1000) countStr = (badge.Count / 1000).ToString().Substring(0, 1) + "K+"; + else if (badge.Count > 99) countStr = "99+"; + else countStr = badge.Count.ToString(); + + var size = g.MeasureString(countStr, font); + var size_badge = size.Height * 1.2F; + if (size.Height > size.Width) + { + var rect_badge = new RectangleF(rect.Right - size_badge + 6F, rect.Top - 8F, size_badge, size_badge); + using (var brush = new SolidBrush(color)) + { + g.FillEllipse(brush, rect_badge); + using (var pen = new Pen(brush_fore.Color, borsize)) + { + g.DrawEllipse(pen, rect_badge); + } + } + g.DrawStr(countStr, font, brush_fore, rect_badge, s_f); + } + else + { + var w_badge = size.Width * 1.2F; + var rect_badge = new RectangleF(rect.Right - w_badge + 6F, rect.Top - 8F, w_badge, size_badge); + using (var brush = new SolidBrush(color)) + { + using (var path = rect_badge.RoundPath(rect_badge.Height)) + { + g.FillPath(brush, path); + using (var pen = new Pen(brush_fore.Color, borsize)) + { + g.DrawPath(pen, path); + } + } + } + g.DrawStr(countStr, font, brush_fore, rect_badge, s_f); + } + } + } + } + } + + #endregion + + public static void PaintShadow(this Graphics g, ShadowConfig config, Rectangle _rect, Rectangle rect, float radius, bool round) + { + int shadow = (int)(config.Shadow * Config.Dpi), shadowOffsetX = (int)(config.ShadowOffsetX * Config.Dpi), shadowOffsetY = (int)(config.ShadowOffsetY * Config.Dpi); + using (var bmp_shadow = new Bitmap(_rect.Width, _rect.Height)) + { + using (var g_shadow = Graphics.FromImage(bmp_shadow)) + { + using (var path = RoundPath(rect, radius, round)) + { + using (var brush = config.ShadowColor.Brush(Style.Db.TextBase)) + { + g_shadow.FillPath(brush, path); + } + } + Blur(bmp_shadow, shadow); + } + using (var attributes = new ImageAttributes()) + { + var matrix = new ColorMatrix + { + Matrix33 = config.ShadowOpacity + }; + attributes.SetColorMatrix(matrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap); + g.DrawImage(bmp_shadow, new Rectangle(_rect.X + shadowOffsetX, _rect.Y + shadowOffsetY, _rect.Width, _rect.Height), 0, 0, _rect.Width, _rect.Height, GraphicsUnit.Pixel, attributes); + } + } + } + + #endregion + + #region 图像处理 + + #region 模糊 + + public static void Blur(Bitmap bmp, int range) + { + Blur(bmp, range, new Rectangle(0, 0, bmp.Width, bmp.Height)); + } + public static void Blur(Bitmap bmp, int range, Rectangle rect) + { + if (range > 1) + { + using (UnsafeBitmap unsafeBitmap = new UnsafeBitmap(bmp, true)) + { + BlurHorizontal(unsafeBitmap, range, rect); + BlurVertical(unsafeBitmap, range, rect); + BlurHorizontal(unsafeBitmap, range, rect); + BlurVertical(unsafeBitmap, range, rect); + } + } + } + + private static void BlurHorizontal(UnsafeBitmap unsafeBitmap, int range, Rectangle rect) + { + int left = rect.X; + int top = rect.Y; + int right = rect.Right; + int bottom = rect.Bottom; + int halfRange = range / 2; + ColorBgra[] newColors = new ColorBgra[unsafeBitmap.Width]; + + for (int y = top; y < bottom; y++) + { + int hits = 0; + int r = 0; + int g = 0; + int b = 0; + int a = 0; + + for (int x = left - halfRange; x < right; x++) + { + int oldPixel = x - halfRange - 1; + if (oldPixel >= left) + { + ColorBgra color = unsafeBitmap.GetPixel(oldPixel, y); + + if (color.Bgra != 0) + { + r -= color.Red; + g -= color.Green; + b -= color.Blue; + a -= color.Alpha; + } + + hits--; + } + + int newPixel = x + halfRange; + if (newPixel < right) + { + ColorBgra color = unsafeBitmap.GetPixel(newPixel, y); + + if (color.Bgra != 0) + { + r += color.Red; + g += color.Green; + b += color.Blue; + a += color.Alpha; + } + + hits++; + } + + if (x >= left) + { + newColors[x] = new ColorBgra((byte)(b / hits), (byte)(g / hits), (byte)(r / hits), (byte)(a / hits)); + } + } + + for (int x = left; x < right; x++) + { + unsafeBitmap.SetPixel(x, y, newColors[x]); + } + } + } + + private static void BlurVertical(UnsafeBitmap unsafeBitmap, int range, Rectangle rect) + { + int left = rect.X; + int top = rect.Y; + int right = rect.Right; + int bottom = rect.Bottom; + int halfRange = range / 2; + ColorBgra[] newColors = new ColorBgra[unsafeBitmap.Height]; + + for (int x = left; x < right; x++) + { + int hits = 0; + int r = 0; + int g = 0; + int b = 0; + int a = 0; + + for (int y = top - halfRange; y < bottom; y++) + { + int oldPixel = y - halfRange - 1; + if (oldPixel >= top) + { + ColorBgra color = unsafeBitmap.GetPixel(x, oldPixel); + + if (color.Bgra != 0) + { + r -= color.Red; + g -= color.Green; + b -= color.Blue; + a -= color.Alpha; + } + + hits--; + } + + int newPixel = y + halfRange; + if (newPixel < bottom) + { + ColorBgra color = unsafeBitmap.GetPixel(x, newPixel); + + if (color.Bgra != 0) + { + r += color.Red; + g += color.Green; + b += color.Blue; + a += color.Alpha; + } + + hits++; + } + + if (y >= top) + { + newColors[y] = new ColorBgra((byte)(b / hits), (byte)(g / hits), (byte)(r / hits), (byte)(a / hits)); + } + } + + for (int y = top; y < bottom; y++) + { + unsafeBitmap.SetPixel(x, y, newColors[y]); + } + } + } + + #endregion + + #region 阴影 + + public static Bitmap PaintShadow(this GraphicsPath path, int width, int height, int range = 10) + { + return PaintShadow(path, width, height, Color.Black, range); + } + public static Bitmap PaintShadow(this GraphicsPath path, int width, int height, Color color, int range = 10) + { + var bmp_shadow = new Bitmap(width, height); + using (var g = Graphics.FromImage(bmp_shadow)) + { + using (var brush = new SolidBrush(color)) + { + g.FillPath(brush, path); + } + Blur(bmp_shadow, range); + } + return bmp_shadow; + } + + #endregion + + #endregion + } +} \ No newline at end of file diff --git a/src/AntdUI/Lib/Helper/Helper.Mask.cs b/src/AntdUI/Lib/Helper/Helper.Mask.cs new file mode 100644 index 00000000..afe189b0 --- /dev/null +++ b/src/AntdUI/Lib/Helper/Helper.Mask.cs @@ -0,0 +1,84 @@ +// 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.Windows.Forms; + +namespace AntdUI +{ + partial class Helper + { + /// + /// 叠加蒙版 + /// + /// 父窗口 + public static ILayeredFormOpacity FormMask(this Form owner) + { + var mask = new LayeredFormMask(owner); + mask.Show(owner); + return mask; + } + + /// + /// 叠加蒙版(可关闭) + /// + /// 父窗口 + /// 点击蒙层是否允许关闭 + /// 操作对象 + public static ILayeredFormOpacity FormMask(this Form owner, bool MaskClosable, ILayeredForm form) + { + var mask = new LayeredFormMask(owner); + if (MaskClosable) + { + try + { + mask.Click += (s1, e1) => + { + form.IClose(); + }; + } + catch { } + } + mask.Show(owner); + return mask; + } + + /// + /// 叠加蒙版(可关闭) + /// + /// 父窗口 + /// 点击蒙层是否允许关闭 + /// 操作对象 + public static ILayeredFormOpacity FormMask(this Form owner, bool MaskClosable, Form form) + { + var mask = new LayeredFormMask(owner); + if (MaskClosable) + { + try + { + mask.Click += (s1, e1) => + { + form.Close(); + }; + } + catch { } + } + mask.Show(owner); + return mask; + } + } +} \ No newline at end of file diff --git a/src/AntdUI/Lib/Helper/Helper.RECT.cs b/src/AntdUI/Lib/Helper/Helper.RECT.cs new file mode 100644 index 00000000..d421e8cc --- /dev/null +++ b/src/AntdUI/Lib/Helper/Helper.RECT.cs @@ -0,0 +1,712 @@ +// 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.Drawing; +using System.Windows.Forms; + +namespace AntdUI +{ + partial class Helper + { + #region 区域 + + /// + /// 得到容器标准坐标 + /// + /// 区域 + /// 字体高度 + /// 左边图标 + /// 右边图标 + /// 左右翻转 + /// 多选 + internal static RectTextLR IconRect(this Rectangle rect, int text_height, bool icon_l, bool icon_r, bool right, bool muit, float gap_ratio = .4F, float sp_ratio = .25F, float icon_ratio = .7F) + { + var rectlr = new RectTextLR(); + int sps = (int)(text_height * gap_ratio), h = (int)(text_height * icon_ratio), sps2 = sps * 2; + if (muit) + { + if (icon_l && icon_r) + { + int sp = (int)(text_height * sp_ratio); + rectlr.text = new Rectangle(rect.X + sps + h + sp, rect.Y + sps, rect.Width - ((sps + h + sp) * 2), rect.Height - sps2); + + rectlr.l = new Rectangle(rect.X + sps, rect.Y + sps + (text_height - h) / 2, h, h); + rectlr.r = new Rectangle(rectlr.text.Right + sp, rectlr.l.Y, h, h); + if (right) + { + var r = rectlr.r; + rectlr.r = rectlr.l; + rectlr.l = r; + return rectlr; + } + } + else if (icon_l) + { + int sp = (int)(text_height * sp_ratio); + if (right) + { + rectlr.text = new Rectangle(rect.X + sps, rect.Y + sps, rect.Width - sps2 - h - sp, rect.Height - sps2); + rectlr.l = new Rectangle(rectlr.text.Right + sp, rect.Y + sps + (text_height - h) / 2, h, h); + return rectlr; + } + rectlr.text = new Rectangle(rect.X + sps + h + sp, rect.Y + sps, rect.Width - sps2 - h - sp, rect.Height - sps2); + rectlr.l = new Rectangle(rect.X + sps, rect.Y + sps + (text_height - h) / 2, h, h); + } + else if (icon_r) + { + int sp = (int)(text_height * sp_ratio); + if (right) + { + rectlr.text = new Rectangle(rect.X + sps + h + sp, rect.Y + sps, rect.Width - sps2 - h - sp, rect.Height - sps2); + rectlr.r = new Rectangle(rect.X + sps, rect.Y + sps + (text_height - h) / 2, h, h); + return rectlr; + } + rectlr.text = new Rectangle(rect.X + sps, rect.Y + sps, rect.Width - sps2 - h - sp, rect.Height - sps2); + rectlr.r = new Rectangle(rectlr.text.Right + sp, rect.Y + sps + (text_height - h) / 2, h, h); + } + else rectlr.text = new Rectangle(rect.X + sps, rect.Y + sps, rect.Width - sps2, rect.Height - sps2); + } + else + { + if (icon_l && icon_r) + { + int sp = (int)(text_height * sp_ratio); + rectlr.text = new Rectangle(rect.X + sps + h + sp, rect.Y + (rect.Height - text_height) / 2, rect.Width - ((sps + h + sp) * 2), text_height); + + rectlr.l = new Rectangle(rect.X + sps, rect.Y + (rect.Height - h) / 2, h, h); + rectlr.r = new Rectangle(rectlr.text.Right + sp, rectlr.l.Y, h, h); + if (right) + { + var r = rectlr.r; + rectlr.r = rectlr.l; + rectlr.l = r; + return rectlr; + } + } + else if (icon_l) + { + int sp = (int)(text_height * sp_ratio); + if (right) + { + rectlr.text = new Rectangle(rect.X + sps, rect.Y + (rect.Height - text_height) / 2, rect.Width - sps2 - h - sp, text_height); + rectlr.l = new Rectangle(rectlr.text.Right + sp, rect.Y + (rect.Height - h) / 2, h, h); + return rectlr; + } + rectlr.text = new Rectangle(rect.X + sps + h + sp, rect.Y + (rect.Height - text_height) / 2, rect.Width - sps2 - h - sp, text_height); + rectlr.l = new Rectangle(rect.X + sps, rect.Y + (rect.Height - h) / 2, h, h); + } + else if (icon_r) + { + int sp = (int)(text_height * sp_ratio); + if (right) + { + rectlr.text = new Rectangle(rect.X + sps + h + sp, rect.Y + (rect.Height - text_height) / 2, rect.Width - sps2 - h - sp, text_height); + rectlr.r = new Rectangle(rect.X + sps, rect.Y + (rect.Height - h) / 2, h, h); + return rectlr; + } + rectlr.text = new Rectangle(rect.X + sps, rect.Y + (rect.Height - text_height) / 2, rect.Width - sps2 - h - sp, text_height); + rectlr.r = new Rectangle(rectlr.text.Right + sp, rect.Y + (rect.Height - h) / 2, h, h); + } + else rectlr.text = new Rectangle(rect.X + sps, rect.Y + (rect.Height - text_height) / 2, rect.Width - sps2, text_height); + } + return rectlr; + } + + internal static void IconRectL(this Rectangle rect, SizeF font_size, out Rectangle icon_rect, out Rectangle text_rect, float size = 0.8F) + { + int h = (int)(font_size.Height * size); + int dot_size_ = h / 2; + int dot_txt_left = h * 2; + + icon_rect = new Rectangle(rect.X + dot_size_, rect.Y + (rect.Height - h) / 2, h, h); + text_rect = new Rectangle(rect.X + dot_txt_left, rect.Y, rect.Width - dot_txt_left, rect.Height); + } + + #region DisplayRectangle + + public static Rectangle DeflateRect(this Rectangle rect, Padding padding) + { + rect.X += padding.Left; + rect.Y += padding.Top; + rect.Width -= padding.Horizontal; + rect.Height -= padding.Vertical; + return rect; + } + + public static Rectangle DeflateRect(this Rectangle rect, Padding padding, ShadowConfig config, TAlignMini align, float borderWidth = 0F) + { + if (config.Shadow > 0) + { + int shadow = (int)(config.Shadow * Config.Dpi), s2 = shadow * 2, shadowOffsetX = Math.Abs((int)(config.ShadowOffsetX * Config.Dpi)), shadowOffsetY = Math.Abs((int)(config.ShadowOffsetY * Config.Dpi)); + int x, y, w, h; + switch (align) + { + case TAlignMini.Top: + x = rect.X + padding.Left; + w = rect.Width - padding.Horizontal; + + y = rect.Y + padding.Top + shadow; + h = rect.Height - padding.Vertical - shadow; + break; + case TAlignMini.Bottom: + x = rect.X + padding.Left; + w = rect.Width - padding.Horizontal; + + y = rect.Y + padding.Top; + h = rect.Height - padding.Vertical - shadow; + break; + case TAlignMini.Left: + y = rect.Y + padding.Top; + h = rect.Height - padding.Vertical; + + x = rect.X + padding.Left + shadow; + w = rect.Width - padding.Horizontal - shadow; + break; + case TAlignMini.Right: + y = rect.Y + padding.Top; + h = rect.Height - padding.Vertical; + + x = rect.X + padding.Left; + w = rect.Width - padding.Horizontal - shadow; + break; + case TAlignMini.None: + default: + x = rect.X + padding.Left + shadow; + y = rect.Y + padding.Top + shadow; + w = rect.Width - padding.Horizontal - s2; + h = rect.Height - padding.Vertical - s2; + break; + } + + if (config.ShadowOffsetX < 0) + { + x += shadowOffsetX; + w -= shadowOffsetX; + } + if (config.ShadowOffsetY < 0) + { + y += shadowOffsetY; + h -= shadowOffsetY; + } + + if (borderWidth > 0) + { + int pr = (int)Math.Ceiling(borderWidth * Config.Dpi), pr2 = pr * 2; + return new Rectangle(x + pr, y + pr, w - pr2, h - pr2); + } + return new Rectangle(x, y, w, h); + } + else + { + if (borderWidth > 0) + { + int pr = (int)Math.Ceiling(borderWidth * Config.Dpi), pr2 = pr * 2; + return new Rectangle(rect.X + padding.Left + pr, rect.Y + padding.Top + pr, rect.Width - padding.Horizontal - pr2, rect.Height - padding.Vertical - pr2); + } + return new Rectangle(rect.X + padding.Left, rect.Y + padding.Top, rect.Width - padding.Horizontal, rect.Height - padding.Vertical); + } + } + + #endregion + + public static Rectangle PaddingRect(this Rectangle rect, ShadowConfig config, TAlignMini align, float borderWidth = 0F) + { + if (config.Shadow > 0) + { + int shadow = (int)(config.Shadow * Config.Dpi), s2 = shadow * 2, shadowOffsetX = Math.Abs((int)(config.ShadowOffsetX * Config.Dpi)), shadowOffsetY = Math.Abs((int)(config.ShadowOffsetY * Config.Dpi)); + + int x, y, w, h; + switch (align) + { + case TAlignMini.Top: + x = rect.X; + w = rect.Width; + + y = rect.Y + shadow; + h = rect.Height - shadow; + break; + case TAlignMini.Bottom: + x = rect.X; + w = rect.Width; + + y = rect.Y; + h = rect.Height - shadow; + break; + case TAlignMini.Left: + y = rect.Y; + h = rect.Height; + + x = rect.X + shadow; + w = rect.Width - shadow; + break; + case TAlignMini.Right: + y = rect.Y; + h = rect.Height; + + x = rect.X; + w = rect.Width - shadow; + break; + case TAlignMini.None: + default: + x = rect.X + shadow; + y = rect.Y + shadow; + w = rect.Width - s2; + h = rect.Height - s2; + break; + } + + if (config.ShadowOffsetX < 0) + { + x += shadowOffsetX; + w -= shadowOffsetX; + } + if (config.ShadowOffsetY < 0) + { + y += shadowOffsetY; + h -= shadowOffsetY; + } + + if (borderWidth > 0) + { + int pr = (int)Math.Ceiling(borderWidth * Config.Dpi / 2F), pr2 = pr * 2; + return new Rectangle(x + pr, y + pr, w - pr2, h - pr2); + } + return new Rectangle(x, y, w, h); + } + else + { + if (borderWidth > 0) + { + int pr = (int)Math.Ceiling((borderWidth * Config.Dpi) / 2F), pr2 = pr * 2; + return new Rectangle(rect.X + pr, rect.Y + pr, rect.Width - pr2, rect.Height - pr2); + } + return rect; + } + } + public static Rectangle PaddingRect(this Rectangle rect, Padding padding, int x, int y, int r, int b) + { + return new Rectangle(rect.X + padding.Left + x, rect.Y + padding.Top + y, rect.Width - padding.Horizontal - r, rect.Height - padding.Vertical - b); + } + public static Rectangle PaddingRect(this Rectangle rect, params Padding[] paddings) + { + foreach (var padding in paddings) + { + rect.X += padding.Left; + rect.Y += padding.Top; + rect.Width -= padding.Horizontal; + rect.Height -= padding.Vertical; + } + return rect; + } + + /// + /// 获取边距 + /// + /// 区域 + /// 边距 + /// 边框 + public static Rectangle PaddingRect(this Rectangle rect, Padding padding, float size = 0F) + { + if (size > 0) + { + int pr = (int)Math.Round(size), pr2 = pr * 2; + return new Rectangle(rect.X + padding.Left + pr, rect.Y + padding.Top + pr, rect.Width - padding.Horizontal - pr2, rect.Height - padding.Vertical - pr2); + } + return new Rectangle(rect.X + padding.Left, rect.Y + padding.Top, rect.Width - padding.Horizontal, rect.Height - padding.Vertical); + } + public static Rectangle PaddingRect(this Rectangle rect, Padding padding, int x, int y, int r, int b, float size = 0F) + { + if (size > 0) + { + int pr = (int)Math.Round(size), pr2 = pr * 2; + return new Rectangle(rect.X + padding.Left + pr + x, rect.Y + padding.Top + pr + y, rect.Width - padding.Horizontal - pr2 - r, rect.Height - padding.Vertical - pr2 - b); + } + return new Rectangle(rect.X + padding.Left + x, rect.Y + padding.Top + y, rect.Width - padding.Horizontal - r, rect.Height - padding.Vertical - b); + } + + /// + /// 得到真实渲染区域 + /// + /// 容器区域 + /// 动画区域 + /// 形状 + /// 连接左边 + /// 连接右边 + internal static Rectangle ReadRect(this Rectangle rect, float size, TShape shape, bool joinLeft, bool joinRight) + { + if (shape == TShape.Circle) + { + int pr = (int)Math.Round(size), pr2 = pr * 2; + if (rect.Width > rect.Height) + { + int h = rect.Height - pr2; + return new Rectangle(rect.X + (rect.Width - h) / 2, rect.Y + pr, h, h); + } + else + { + int w = rect.Width - pr2; + return new Rectangle(rect.X + pr, rect.Y + (rect.Height - w) / 2, w, w); + } + } + return ReadRect(rect, size, joinLeft, joinRight); + } + + /// + /// 得到真实渲染区域 + /// + /// 容器区域 + /// 动画区域 + /// 连接左边 + /// 连接右边 + internal static Rectangle ReadRect(this Rectangle rect, float size, bool joinLeft, bool joinRight) + { + int pr = (int)Math.Round(size), pr2 = pr * 2; + if (joinLeft && joinRight) return new Rectangle(rect.X, rect.Y + pr, rect.Width, rect.Height - pr2); + else if (joinLeft) + { + var r = new Rectangle(rect.X, rect.Y + pr, rect.Width - pr, rect.Height - pr2); + rect.X = -pr; + rect.Width += pr; + return r; + } + else if (joinRight) + { + var r = new Rectangle(rect.Width - (rect.Width - pr), rect.Y + pr, rect.Width - pr, rect.Height - pr2); + rect.X = 0; + rect.Width += pr; + return r; + } + return new Rectangle(rect.X + pr, rect.Y + pr, rect.Width - pr2, rect.Height - pr2); + } + + #endregion + + #region 文本方向 + + internal static void SetAlignment(this ContentAlignment textAlign, ref StringFormat stringFormat) + { + switch (textAlign) + { + case ContentAlignment.TopLeft: + stringFormat.Alignment = StringAlignment.Near; + stringFormat.LineAlignment = StringAlignment.Near; + //内容在垂直方向上顶部对齐,在水平方向上左边对齐 + break; + case ContentAlignment.TopCenter: + stringFormat.Alignment = StringAlignment.Center; + stringFormat.LineAlignment = StringAlignment.Near; + //内容在垂直方向上顶部对齐,在水平方向上居中对齐 + + break; + case ContentAlignment.TopRight: + //内容在垂直方向上顶部对齐,在水平方向上右边对齐 + stringFormat.Alignment = StringAlignment.Far; + stringFormat.LineAlignment = StringAlignment.Near; + break; + case ContentAlignment.MiddleLeft: + //内容在垂直方向上中间对齐,在水平方向上左边对齐 + stringFormat.Alignment = StringAlignment.Near; + stringFormat.LineAlignment = StringAlignment.Center; + + break; + case ContentAlignment.MiddleCenter: + //内容在垂直方向上中间对齐,在水平方向上居中对齐 + stringFormat.Alignment = StringAlignment.Center; + stringFormat.LineAlignment = StringAlignment.Center; + break; + case ContentAlignment.MiddleRight: + //内容在垂直方向上中间对齐,在水平方向上右边对齐 + stringFormat.Alignment = StringAlignment.Far; + stringFormat.LineAlignment = StringAlignment.Center; + + break; + case ContentAlignment.BottomLeft: + //内容在垂直方向上底边对齐,在水平方向上左边对齐 + stringFormat.Alignment = StringAlignment.Near; + stringFormat.LineAlignment = StringAlignment.Far; + break; + case ContentAlignment.BottomCenter: + //内容在垂直方向上底边对齐,在水平方向上居中对齐 + stringFormat.Alignment = StringAlignment.Center; + stringFormat.LineAlignment = StringAlignment.Far; + + break; + case ContentAlignment.BottomRight: + //内容在垂直方向上底边对齐,在水平方向上右边对齐 + stringFormat.Alignment = StringAlignment.Far; + stringFormat.LineAlignment = StringAlignment.Far; + break; + } + } + internal static void SetAlignment(this HorizontalAlignment textAlign, ref StringFormat stringFormat) + { + switch (textAlign) + { + case HorizontalAlignment.Left: + //内容在垂直方向上中间对齐,在水平方向上左边对齐 + stringFormat.Alignment = StringAlignment.Near; + break; + case HorizontalAlignment.Center: + //内容在垂直方向上中间对齐,在水平方向上居中对齐 + stringFormat.Alignment = StringAlignment.Center; + break; + case HorizontalAlignment.Right: + //内容在垂直方向上中间对齐,在水平方向上右边对齐 + stringFormat.Alignment = StringAlignment.Far; + break; + } + } + + #endregion + + #region 三角 + + internal static PointF[] TriangleLines(this Rectangle rect, float prog, float d = 0.7F) + { + float size = rect.Width * d, size2 = size / 2; + float x = rect.X + rect.Width / 2F, y = rect.Y + rect.Height / 2F; + if (prog == 0) + { + return new PointF[] { + new PointF(x - size2, y), + new PointF(x + size2,y) + }; + } + else if (prog > 0) + { + float h = size2 * prog, h2 = h / 2; + return new PointF[] { + new PointF(x - size2,y + h2), + new PointF(x, y - h2), + new PointF(x + size2,y + h2) + }; + } + else + { + float h = size2 * -prog, h2 = h / 2; + return new PointF[] { + new PointF(x - size2,y - h2), + new PointF(x, y + h2), + new PointF(x + size2,y - h2) + }; + } + } + + internal static PointF[] TriangleLines(this TAlignMini align, RectangleF rect, float b = 0.375F) + { + float size = rect.Height * b, size2 = size / 2F; + float x = rect.X + rect.Width / 2F, y = rect.Y + rect.Height / 2F; + float h2 = size2 / 2; + + switch (align) + { + case TAlignMini.Top: + return new PointF[] { + new PointF(x - size2,y + h2), + new PointF(x, y - h2), + new PointF(x + size2,y + h2) + }; + case TAlignMini.Bottom: + return new PointF[] { + new PointF(x - size2,y - h2), + new PointF(x, y + h2), + new PointF(x + size2,y - h2) + }; + case TAlignMini.Left: + return new PointF[] { + new PointF(x + h2,y - size2), + new PointF(x - h2, y), + new PointF(x + h2,y + size2) + }; + case TAlignMini.Right: + default: + return new PointF[] { + new PointF(x - h2,y - size2), + new PointF(x + h2, y), + new PointF(x - h2,y + size2) + }; + } + } + + /// + /// 得到三角绘制区域 + /// + /// 方向 + /// 三角大小 + /// 全局区域 + /// 内容区域 + internal static PointF[] AlignLines(this TAlign align, float arrow_size, RectangleF rect, RectangleF rect_read) + { + if (align == TAlign.Top) + { + //↑上 + float x = rect.Width / 2F, y = rect_read.Y + rect_read.Height; + return new PointF[] { new PointF(x - arrow_size, y), new PointF(x + arrow_size, y), new PointF(x, y + arrow_size) }; + } + else if (align == TAlign.Bottom) + { + //↓ 下 + float x = rect.Width / 2F, y = rect_read.Y - arrow_size; + return new PointF[] { new PointF(x, y), new PointF(x - arrow_size, y + arrow_size), new PointF(x + arrow_size, y + arrow_size) }; + } + else if (align == TAlign.Left || align == TAlign.LT || align == TAlign.LB) + { + //← 左 + float x = rect_read.X + rect_read.Width, y = rect.Height / 2F; + return new PointF[] { new PointF(x, y - arrow_size), new PointF(x, y + arrow_size), new PointF(x + arrow_size, y) }; + } + else if (align == TAlign.Right || align == TAlign.RT || align == TAlign.RB) + { + //→ 右 + float x = rect_read.X - arrow_size, y = rect.Height / 2F; + return new PointF[] { new PointF(x, y), new PointF(x + arrow_size, y - arrow_size), new PointF(x + arrow_size, y + arrow_size) }; + } + + #region 下 + + else if (align == TAlign.BL) + { + //↙ 下左 + float x = rect_read.X + arrow_size * 3F, y = rect_read.Y - arrow_size; + return new PointF[] { new PointF(x, y), new PointF(x - arrow_size, y + arrow_size), new PointF(x + arrow_size, y + arrow_size) }; + } + else if (align == TAlign.BR) + { + //↘ 下右 + float x = rect_read.X + rect_read.Width - arrow_size * 3F, y = rect_read.Y - arrow_size; + return new PointF[] { new PointF(x, y), new PointF(x - arrow_size, y + arrow_size), new PointF(x + arrow_size, y + arrow_size) }; + } + + #endregion + + #region 上 + + else if (align == TAlign.TL) + { + //↖ 上左 + float x = rect_read.X + arrow_size * 3F, y = rect_read.Y + rect_read.Height; + return new PointF[] { new PointF(x - arrow_size, y), new PointF(x + arrow_size, y), new PointF(x, y + arrow_size) }; + } + else if (align == TAlign.TR) + { + //↗ 上右 + float x = rect_read.X + rect_read.Width - arrow_size * 3F, y = rect_read.Y + rect_read.Height; + return new PointF[] { new PointF(x - arrow_size, y), new PointF(x + arrow_size, y), new PointF(x, y + arrow_size) }; + } + + #endregion + + else + { + //↑上 + float x = rect.Width / 2F, y = rect_read.Y + rect_read.Height; + return new PointF[] { new PointF(x - arrow_size, y), new PointF(x + arrow_size, y), new PointF(x, y + arrow_size) }; + } + } + + #endregion + + #region 角度方向 + + /// + /// 转换大致位置 + /// + /// 方向 + internal static TAlignMini AlignMini(this TAlign align) + { + if (align == TAlign.BL || align == TAlign.Bottom || align == TAlign.BR) + return TAlignMini.Bottom; + else if (align == TAlign.TL || align == TAlign.Top || align == TAlign.TR) + return TAlignMini.Top; + else if (align == TAlign.RT || align == TAlign.Right || align == TAlign.RB) + return TAlignMini.Right; + else if (align == TAlign.LT || align == TAlign.Left || align == TAlign.LB) + return TAlignMini.Left; + return TAlignMini.None; + } + + /// + /// 转换反向大致位置 + /// + /// 方向 + /// 是否竖向 + internal static TAlign AlignMiniReverse(this TAlign align, bool vertical) + { + if (vertical) + { + if (align == TAlign.TL || align == TAlign.BL || align == TAlign.LB || align == TAlign.Left || align == TAlign.LT) return TAlign.Right; + return TAlign.Left; + } + else + { + if (align == TAlign.TL || align == TAlign.Top || align == TAlign.TR || align == TAlign.RT) return TAlign.Bottom; + return TAlign.Top; + } + } + + /// + /// 弹出坐标 + /// + /// 方向 + /// 控件坐标 + /// 控件大小 + /// 提示框宽度 + /// 提示框高度 + internal static Point AlignPoint(this TAlign align, Point point, Size size, int width, int height) + { + switch (align) + { + case TAlign.Top: + return new Point(point.X + (size.Width - width) / 2, point.Y - height); + case TAlign.TL: + return new Point(point.X, point.Y - height); + case TAlign.TR: + return new Point(point.X + size.Width - width, point.Y - height); + case TAlign.Bottom: + return new Point(point.X + (size.Width - width) / 2, point.Y + size.Height); + case TAlign.BL: + return new Point(point.X, point.Y + size.Height); + case TAlign.BR: + return new Point(point.X + size.Width - width, point.Y + size.Height); + case TAlign.Left: + case TAlign.LT: + case TAlign.LB: + return new Point(point.X - width, point.Y + (size.Height - height) / 2); + case TAlign.Right: + case TAlign.RT: + case TAlign.RB: + return new Point(point.X + size.Width, point.Y + (size.Height - height) / 2); + default: + return new Point(point.X + (size.Width - width) / 2, point.Y - height); + } + } + + internal static Point AlignPoint(this TAlign align, Rectangle rect, Rectangle size) + { + return AlignPoint(align, rect.Location, rect.Size, size.Width, size.Height); + } + + internal static Point AlignPoint(this TAlign align, Rectangle rect, int width, int height) + { + return AlignPoint(align, rect.Location, rect.Size, width, height); + } + + #endregion + } +} \ No newline at end of file diff --git a/src/AntdUI/Lib/Helper/Helper.cs b/src/AntdUI/Lib/Helper/Helper.cs new file mode 100644 index 00000000..96536522 --- /dev/null +++ b/src/AntdUI/Lib/Helper/Helper.cs @@ -0,0 +1,232 @@ +// 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.Collections; +using System.Drawing; +using System.Windows.Forms; + +namespace AntdUI +{ + public static partial class Helper + { + public static float Calculate(this float val, float add) + { + return (float)Math.Round(val + add, 3); + } + + /// + /// SizeF转Size(向上取整) + /// + /// SizeF + public static Size Size(this SizeF size) + { + return new Size((int)Math.Ceiling(size.Width), (int)Math.Ceiling(size.Height)); + } + + /// + /// SizeF转Size(向上取整) + /// + /// SizeF + public static Size Size(this SizeF size, float p) + { + return new Size((int)Math.Ceiling(size.Width + p), (int)Math.Ceiling(size.Height + p)); + } + + public static Color ToColor(float alpha, Color color) + { + return ToColor((int)alpha, color); + } + + public static Color ToColorN(float val, Color color) + { + return ToColor((int)(val * color.A), color); + } + + public static Color ToColor(int alpha, Color color) + { + if (alpha > 255) alpha = 255; + else if (alpha < 0) alpha = 0; + return Color.FromArgb(alpha, color); + } + + public static Form? FindPARENT(this Control? control) + { + if (control == null) return null; + if (control is DoubleBufferForm formd) + { + if (control.Tag is Form form) return form; + else if (control.Parent != null) return FindPARENT(control.Parent); + return formd; + } + else if (control is Form form) return form; + else if (control.Parent != null) return FindPARENT(control.Parent); + return null; + } + public static bool SetTopMost(this Control? control, IntPtr hand) + { + var form = control.FindPARENT(); + if (form != null && form.TopMost) + { + SetTopMost(hand); + return true; + } + return false; + } + + public static void SetTopMost(IntPtr hand) + { + Vanara.PInvoke.User32.SetWindowPos(hand, new IntPtr(-1), 0, 0, 0, 0, Vanara.PInvoke.User32.SetWindowPosFlags.SWP_NOACTIVATE); + } + + public static bool Wait(this System.Threading.WaitHandle handle) + { + try + { + handle.WaitOne(); + return false; + } + catch + { + return true; + } + } + + public static bool Wait(this System.Threading.CancellationTokenSource? token) + { + try + { + if (token == null || token.IsCancellationRequested) return true; + return false; + } + catch + { + return true; + } + } + + public static bool Wait(this System.Threading.CancellationTokenSource? token, Control control) + { + try + { + if (token == null || token.IsCancellationRequested || control.IsDisposed) return true; + return false; + } + catch + { + return true; + } + } + + public static bool ListExceed(this IList? list, int index) + { + if (list == null || list.Count <= index || index < 0) return true; + return false; + } + + public static bool DateExceed(DateTime date, DateTime? min, DateTime? max) + { + if (min.HasValue && min.Value >= date) return false; + if (max.HasValue && max.Value <= date) return false; + return true; + } + + public static bool DateExceedRelax(DateTime date, DateTime? min, DateTime? max) + { + if (min.HasValue && min.Value > date) return false; + if (max.HasValue && max.Value < date) return false; + return true; + } + + #region 剪贴板 + + public static string? ClipboardGetText(this Control control) + { + if (control.InvokeRequired) + { + string? r = null; + control.Invoke(new Action(() => + { + r = ClipboardGetText(); + })); + return r; + } + return ClipboardGetText(); + } + public static string? ClipboardGetText() + { + try + { + return Clipboard.GetText(); + } + catch + { + return Win32.GetClipBoardText(); + } + } + public static bool ClipboardSetText(this Control control, string? text) + { + if (control.InvokeRequired) + { + bool r = false; + control.Invoke(new Action(() => + { + r = ClipboardSetText(text); + })); + return r; + } + return ClipboardSetText(text); + } + public static bool ClipboardSetText(string? text) + { + try + { + if (text == null) Clipboard.Clear(); + else Clipboard.SetText(text); + return true; + } + catch + { + if (Win32.SetClipBoardText(text)) return true; + } + return false; + } + + #endregion + } + + internal class AnchorDock + { + public AnchorDock(Control control) + { + Dock = control.Dock; + Anchor = control.Anchor; + control.Dock = DockStyle.None; + control.Anchor = AnchorStyles.Left | AnchorStyles.Top; + } + public DockStyle Dock { get; set; } + public AnchorStyles Anchor { get; set; } + } + + public class RectTextLR + { + public Rectangle text { get; set; } + public Rectangle l { get; set; } + public Rectangle r { get; set; } + } +} \ No newline at end of file diff --git a/src/AntdUI/Lib/Helper/OS.cs b/src/AntdUI/Lib/Helper/OS.cs new file mode 100644 index 00000000..cd130c09 --- /dev/null +++ b/src/AntdUI/Lib/Helper/OS.cs @@ -0,0 +1,76 @@ +// 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; + +namespace AntdUI +{ + public class OS + { + public static Version Version; + public static bool Win11 + { + get + { + var version = Version; + if (version.Major >= 10 && version.Build > 22000) return true; + return false; + } + } + + #region OS版本 + +#if NET40 || NET46 || NET48 + static OS() + { + try + { + var osVersionInfo = new OSVERSIONINFOEX { OSVersionInfoSize = System.Runtime.InteropServices.Marshal.SizeOf(typeof(OSVERSIONINFOEX)) }; + if (RtlGetVersion(ref osVersionInfo) == 0) Version = new Version(osVersionInfo.MajorVersion, osVersionInfo.MinorVersion, osVersionInfo.BuildNumber); + } + catch { } + Version = Environment.OSVersion.Version; + } + + [System.Runtime.InteropServices.DllImport("ntdll.dll", SetLastError = true, CharSet = System.Runtime.InteropServices.CharSet.Unicode)] + internal static extern int RtlGetVersion(ref OSVERSIONINFOEX versionInfo); + + internal struct OSVERSIONINFOEX + { + internal int OSVersionInfoSize; + internal int MajorVersion; + internal int MinorVersion; + internal int BuildNumber; + internal int PlatformId; + [System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValTStr, SizeConst = 128)] + internal string CSDVersion; + internal ushort ServicePackMajor; + internal ushort ServicePackMinor; + internal short SuiteMask; + internal byte ProductType; + internal byte Reserved; + } +#else + static OS() + { + Version = Environment.OSVersion.Version; + } +#endif + #endregion + } +} \ No newline at end of file