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