diff --git a/Bin/net40/SunnyUI.dll b/Bin/net40/SunnyUI.dll index 0f099fab..13f569bd 100644 Binary files a/Bin/net40/SunnyUI.dll and b/Bin/net40/SunnyUI.dll differ diff --git a/SunnyUI/Common/UControl.cs b/SunnyUI/Common/UControl.cs index dd4987ba..df0d747f 100644 --- a/SunnyUI/Common/UControl.cs +++ b/SunnyUI/Common/UControl.cs @@ -303,6 +303,57 @@ namespace Sunny.UI return values; } + public static List GetAllControls(this Control control) + { + var list = new List(); + foreach (Control con in control.Controls) + { + list.Add(con); + if (con.Controls.Count > 0) + { + list.AddRange(GetAllControls(con)); + } + } + + return list; + } + + public static float DPIScale(this Control control) + { + return control.CreateGraphics().DpiX / 96.0f; + } + + public static Font DPIScaleFont(this Control control) + { + return new Font(control.Font.FontFamily, control.Font.Size / control.DPIScale(), + control.Font.Style, control.Font.Unit, control.Font.GdiCharSet); + } + + public static void SetDPIScaleFont(this Control control) + { + if (!control.DPIScale().Equals(1)) + { + control.Font = control.DPIScaleFont(); + } + } + + public static List GetAllDPIScaleControls(this Control control) + { + var list = new List(); + foreach (Control con in control.Controls) + { + list.Add(con); + if (con is IToolTip) continue; + + if (con.Controls.Count > 0) + { + list.AddRange(GetAllControls(con)); + } + } + + return list; + } + /// /// 查找包含接口名称的控件列表 /// @@ -401,10 +452,10 @@ namespace Sunny.UI object obj = f1.GetValue(button); PropertyInfo pi = button.GetType().GetProperty("Events", BindingFlags.NonPublic | BindingFlags.Instance); - if (pi != null) + if (pi != null && obj != null) { EventHandlerList list = (EventHandlerList)pi.GetValue(button, null); - list.RemoveHandler(obj, list[obj]); + list?.RemoveHandler(obj, list[obj]); } } diff --git a/SunnyUI/Controls/Color/UIColorWheel.cs b/SunnyUI/Controls/Color/UIColorWheel.cs index 3d4af3fe..4fa2e9f8 100644 --- a/SunnyUI/Controls/Color/UIColorWheel.cs +++ b/SunnyUI/Controls/Color/UIColorWheel.cs @@ -33,6 +33,17 @@ namespace Sunny.UI } } + public bool IsScaled { get; private set; } + + public void SetDPIScale() + { + if (!IsScaled) + { + this.SetDPIScaleFont(); + IsScaled = true; + } + } + public void SetLightness(double lightness) { m_selectedColor.Lightness = lightness; diff --git a/SunnyUI/Controls/Color/UILabelRotate.cs b/SunnyUI/Controls/Color/UILabelRotate.cs index f33db224..33f90874 100644 --- a/SunnyUI/Controls/Color/UILabelRotate.cs +++ b/SunnyUI/Controls/Color/UILabelRotate.cs @@ -11,6 +11,17 @@ namespace Sunny.UI private ContentAlignment m_rotatePointAlignment = ContentAlignment.MiddleCenter; private ContentAlignment m_textAlignment = ContentAlignment.MiddleLeft; + public bool IsScaled { get; private set; } + + public void SetDPIScale() + { + if (!IsScaled) + { + this.SetDPIScaleFont(); + IsScaled = true; + } + } + public new string Text { get { return base.Text; } diff --git a/SunnyUI/Controls/UIComboboxEx.cs b/SunnyUI/Controls/UIComboboxEx.cs index 6ac1b8c3..795d618b 100644 --- a/SunnyUI/Controls/UIComboboxEx.cs +++ b/SunnyUI/Controls/UIComboboxEx.cs @@ -49,6 +49,17 @@ namespace Sunny.UI Width = 150; } + public bool IsScaled { get; private set; } + + public void SetDPIScale() + { + if (!IsScaled) + { + this.SetDPIScaleFont(); + IsScaled = true; + } + } + private UIStyle _style = UIStyle.Blue; protected override void OnBackColorChanged(EventArgs e) diff --git a/SunnyUI/Controls/UIContextMenuStrip.cs b/SunnyUI/Controls/UIContextMenuStrip.cs index 4c3bd2a7..0b3eb74b 100644 --- a/SunnyUI/Controls/UIContextMenuStrip.cs +++ b/SunnyUI/Controls/UIContextMenuStrip.cs @@ -38,6 +38,17 @@ namespace Sunny.UI Version = UIGlobal.Version; } + public bool IsScaled { get; private set; } + + public void SetDPIScale() + { + if (!IsScaled) + { + this.SetDPIScaleFont(); + IsScaled = true; + } + } + /// /// 自定义主题风格 /// diff --git a/SunnyUI/Controls/UIControl.cs b/SunnyUI/Controls/UIControl.cs index 7a29d587..3d3cabf5 100644 --- a/SunnyUI/Controls/UIControl.cs +++ b/SunnyUI/Controls/UIControl.cs @@ -45,6 +45,17 @@ namespace Sunny.UI base.MinimumSize = new Size(1, 1); } + public bool IsScaled { get; private set; } + + public void SetDPIScale() + { + if (!IsScaled) + { + this.SetDPIScaleFont(); + IsScaled = true; + } + } + protected void SetStyleFlags(bool supportTransparent = true, bool selectable = true, bool resizeRedraw = false) { SetStyle(ControlStyles.AllPaintingInWmPaint, true); diff --git a/SunnyUI/Controls/UIDataGridView.cs b/SunnyUI/Controls/UIDataGridView.cs index aeecaba1..6e6c5dcb 100644 --- a/SunnyUI/Controls/UIDataGridView.cs +++ b/SunnyUI/Controls/UIDataGridView.cs @@ -98,6 +98,17 @@ namespace Sunny.UI HorizontalScrollBar.VisibleChanged += HorizontalScrollBar_VisibleChanged; } + public bool IsScaled { get; private set; } + + public void SetDPIScale() + { + if (!IsScaled) + { + this.SetDPIScaleFont(); + IsScaled = true; + } + } + private readonly Dictionary CellStyles = new Dictionary(); public class CellStyle diff --git a/SunnyUI/Controls/UIImageListBox.cs b/SunnyUI/Controls/UIImageListBox.cs index e6adbf44..8f98864a 100644 --- a/SunnyUI/Controls/UIImageListBox.cs +++ b/SunnyUI/Controls/UIImageListBox.cs @@ -33,7 +33,7 @@ using System.Windows.Forms; namespace Sunny.UI { [DefaultEvent("ItemClick")] - public sealed partial class UIImageListBox : UIPanel,IToolTip + public sealed partial class UIImageListBox : UIPanel, IToolTip { private readonly ImageListBox listbox = new ImageListBox(); private readonly UIScrollBar bar = new UIScrollBar(); @@ -136,7 +136,7 @@ namespace Sunny.UI { listbox.SetScrollInfo(); LastCount = Items.Count; - ItemsCountChange?.Invoke(this, null); + ItemsCountChange?.Invoke(this, EventArgs.Empty); } } @@ -368,6 +368,17 @@ namespace Sunny.UI } } + public bool IsScaled { get; private set; } + + public void SetDPIScale() + { + if (!IsScaled) + { + this.SetDPIScaleFont(); + IsScaled = true; + } + } + //protected override void WndProc(ref Message m) //{ // if (IsDisposed || Disposing) return; diff --git a/SunnyUI/Controls/UILabel.cs b/SunnyUI/Controls/UILabel.cs index 268a6eda..d07a4695 100644 --- a/SunnyUI/Controls/UILabel.cs +++ b/SunnyUI/Controls/UILabel.cs @@ -42,6 +42,17 @@ namespace Sunny.UI ForeColorChanged += UILabel_ForeColorChanged; } + public bool IsScaled { get; private set; } + + public void SetDPIScale() + { + if (!IsScaled) + { + this.SetDPIScaleFont(); + IsScaled = true; + } + } + private void UILabel_ForeColorChanged(object sender, EventArgs e) { _style = UIStyle.Custom; @@ -128,6 +139,17 @@ namespace Sunny.UI LinkColor = UIColor.Blue; } + public bool IsScaled { get; private set; } + + public void SetDPIScale() + { + if (!IsScaled) + { + this.SetDPIScaleFont(); + IsScaled = true; + } + } + /// /// Tag字符串 /// diff --git a/SunnyUI/Controls/UIListBox.cs b/SunnyUI/Controls/UIListBox.cs index fd2046fc..39f08359 100644 --- a/SunnyUI/Controls/UIListBox.cs +++ b/SunnyUI/Controls/UIListBox.cs @@ -605,6 +605,17 @@ namespace Sunny.UI [Description("获取或设置包含有关控件的数据的对象字符串"), Category("SunnyUI")] public string TagString { get; set; } + public bool IsScaled { get; private set; } + + public void SetDPIScale() + { + if (!IsScaled) + { + this.SetDPIScaleFont(); + IsScaled = true; + } + } + public UIScrollBar Bar { get => bar; diff --git a/SunnyUI/Controls/UINavBar.cs b/SunnyUI/Controls/UINavBar.cs index 000c6d37..6c50228f 100644 --- a/SunnyUI/Controls/UINavBar.cs +++ b/SunnyUI/Controls/UINavBar.cs @@ -60,6 +60,17 @@ namespace Sunny.UI Version = UIGlobal.Version; } + public bool IsScaled { get; private set; } + + public void SetDPIScale() + { + if (!IsScaled) + { + this.SetDPIScaleFont(); + IsScaled = true; + } + } + private int radius; [DefaultValue(0)] diff --git a/SunnyUI/Controls/UINavMenu.cs b/SunnyUI/Controls/UINavMenu.cs index c4731d17..34f75c3f 100644 --- a/SunnyUI/Controls/UINavMenu.cs +++ b/SunnyUI/Controls/UINavMenu.cs @@ -80,6 +80,17 @@ namespace Sunny.UI SetScrollInfo(); } + public bool IsScaled { get; private set; } + + public void SetDPIScale() + { + if (!IsScaled) + { + this.SetDPIScaleFont(); + IsScaled = true; + } + } + [DefaultValue(false)] [Description("只显示一个打开的节点"), Category("SunnyUI")] public bool ShowOneNode { get; set; } diff --git a/SunnyUI/Controls/UIPanel.cs b/SunnyUI/Controls/UIPanel.cs index 83bb8bc5..1a471a02 100644 --- a/SunnyUI/Controls/UIPanel.cs +++ b/SunnyUI/Controls/UIPanel.cs @@ -52,6 +52,17 @@ namespace Sunny.UI SetStyleFlags(true, false); } + public bool IsScaled { get; private set; } + + public void SetDPIScale() + { + if (!IsScaled) + { + this.SetDPIScaleFont(); + IsScaled = true; + } + } + protected void SetStyleFlags(bool supportTransparent = true, bool selectable = true, bool resizeRedraw = false) { SetStyle(ControlStyles.AllPaintingInWmPaint, true); diff --git a/SunnyUI/Controls/UITabControl.cs b/SunnyUI/Controls/UITabControl.cs index d63a3007..00b9e9ca 100644 --- a/SunnyUI/Controls/UITabControl.cs +++ b/SunnyUI/Controls/UITabControl.cs @@ -62,6 +62,17 @@ namespace Sunny.UI timer.Tick += Timer_Tick; } + public bool IsScaled { get; private set; } + + public void SetDPIScale() + { + if (!IsScaled) + { + this.SetDPIScaleFont(); + IsScaled = true; + } + } + protected override void Dispose(bool disposing) { base.Dispose(disposing); @@ -457,7 +468,7 @@ namespace Sunny.UI Rectangle TabRect = new Rectangle(GetTabRect(index).Location.X - 2, GetTabRect(index).Location.Y - 2, ItemSize.Width, ItemSize.Height); if (Alignment == TabAlignment.Bottom) { - TabRect = new Rectangle(GetTabRect(index).Location.X- 2, GetTabRect(index).Location.Y + 2, ItemSize.Width, ItemSize.Height); + TabRect = new Rectangle(GetTabRect(index).Location.X - 2, GetTabRect(index).Location.Y + 2, ItemSize.Width, ItemSize.Height); } Bitmap bmp = new Bitmap(TabRect.Width, TabRect.Height); Graphics g = Graphics.FromImage(bmp); @@ -479,10 +490,10 @@ namespace Sunny.UI if (TabSelectedHighColorSize > 0) g.FillRectangle(TabSelectedHighColor, 0, bmp.Height - TabSelectedHighColorSize, bmp.Width, TabSelectedHighColorSize); } - + if (Alignment == TabAlignment.Bottom) { - g.DrawString(TabPages[index].Text, Font, index == SelectedIndex ? tabSelectedForeColor : TabUnSelectedForeColor, textLeft, (TabRect.Height - sf.Height - TabSelectedHighColorSize) / 2.0f); + g.DrawString(TabPages[index].Text, Font, index == SelectedIndex ? tabSelectedForeColor : TabUnSelectedForeColor, textLeft, (TabRect.Height - sf.Height - TabSelectedHighColorSize) / 2.0f); } else { diff --git a/SunnyUI/Controls/UITabControlMenu.cs b/SunnyUI/Controls/UITabControlMenu.cs index 40d31d7d..7fd650e6 100644 --- a/SunnyUI/Controls/UITabControlMenu.cs +++ b/SunnyUI/Controls/UITabControlMenu.cs @@ -46,6 +46,17 @@ namespace Sunny.UI Version = UIGlobal.Version; } + public bool IsScaled { get; private set; } + + public void SetDPIScale() + { + if (!IsScaled) + { + this.SetDPIScaleFont(); + IsScaled = true; + } + } + /// /// 自定义主题风格 /// diff --git a/SunnyUI/Controls/UITableLayoutPanel.cs b/SunnyUI/Controls/UITableLayoutPanel.cs index 09240b5e..24bc35ee 100644 --- a/SunnyUI/Controls/UITableLayoutPanel.cs +++ b/SunnyUI/Controls/UITableLayoutPanel.cs @@ -32,6 +32,17 @@ namespace Sunny.UI Version = UIGlobal.Version; } + public bool IsScaled { get; private set; } + + public void SetDPIScale() + { + if (!IsScaled) + { + this.SetDPIScaleFont(); + IsScaled = true; + } + } + protected override void OnControlAdded(ControlEventArgs e) { base.OnControlAdded(e); diff --git a/SunnyUI/Forms/UIForm.cs b/SunnyUI/Forms/UIForm.cs index 73031d80..0312d3c4 100644 --- a/SunnyUI/Forms/UIForm.cs +++ b/SunnyUI/Forms/UIForm.cs @@ -70,6 +70,22 @@ namespace Sunny.UI showTitleIcon = false; } + public bool IsScaled { get; private set; } + + public void SetDPIScale() + { + if (!IsScaled && UIStyles.DPIScale) + { + this.SetDPIScaleFont(); + foreach (Control control in this.GetAllDPIScaleControls()) + { + control.SetDPIScaleFont(); + } + + IsScaled = true; + } + } + [DefaultValue(true)] [Description("是否点击标题栏可以移动窗体"), Category("SunnyUI")] public bool Movable { get; set; } = true; @@ -1183,6 +1199,7 @@ namespace Sunny.UI CalcSystemBoxPos(); SetRadius(); isShow = true; + SetDPIScale(); } /// diff --git a/SunnyUI/Frames/UIPage.cs b/SunnyUI/Frames/UIPage.cs index a21bd039..63b723cc 100644 --- a/SunnyUI/Frames/UIPage.cs +++ b/SunnyUI/Frames/UIPage.cs @@ -65,6 +65,23 @@ namespace Sunny.UI if (!IsDesignMode) base.Dock = DockStyle.Fill; Version = UIGlobal.Version; + SetDPIScale(); + } + + public bool IsScaled { get; private set; } + + public void SetDPIScale() + { + if (!IsScaled) + { + this.SetDPIScaleFont(); + foreach (Control control in this.GetAllDPIScaleControls()) + { + control.SetDPIScaleFont(); + } + + IsScaled = true; + } } public void Render() diff --git a/SunnyUI/Style/UIStyle.cs b/SunnyUI/Style/UIStyle.cs index c1371d20..31e2d80c 100644 --- a/SunnyUI/Style/UIStyle.cs +++ b/SunnyUI/Style/UIStyle.cs @@ -20,6 +20,7 @@ * 2021-07-12: V3.0.5 增加紫色主题 * 2021-07-18: V3.0.5 增加多彩主题,以颜色深色,文字白色为主 * 2021-09-24: V3.0.7 修改默认字体的GdiCharSet + * 2021-10-16: V3.0.8 增加系统DPI缩放自适应 ******************************************************************************/ using System; @@ -56,6 +57,10 @@ namespace Sunny.UI void SetStyleColor(UIBaseStyle uiColor); void SetStyle(UIStyle style); + + bool IsScaled { get; } + + void SetDPIScale(); } /// @@ -189,6 +194,8 @@ namespace Sunny.UI /// public static class UIStyles { + public static bool DPIScale { get; set; } + public static List PopularStyles() { List styles = new List(); @@ -503,6 +510,21 @@ namespace Sunny.UI } } + public static void SetDPIScale() + { + foreach (var form in Forms.Values) + { + if (!form.DPIScale().EqualsFloat(1)) + form.SetDPIScale(); + } + + foreach (var page in Pages.Values) + { + if (!page.DPIScale().EqualsFloat(1)) + page.SetDPIScale(); + } + } + public static void Translate() { foreach (var form in Forms.Values) diff --git a/SunnyUI/Style/UIStyleManager.cs b/SunnyUI/Style/UIStyleManager.cs index eff6f025..22bae52d 100644 --- a/SunnyUI/Style/UIStyleManager.cs +++ b/SunnyUI/Style/UIStyleManager.cs @@ -17,6 +17,7 @@ * 创建日期: 2020-01-01 * * 2020-01-01: V2.2.0 增加文件说明 + * 2021-10-16: V3.0.8 增加系统DPI缩放自适应 ******************************************************************************/ using System.ComponentModel; @@ -67,5 +68,12 @@ namespace Sunny.UI { container.Add(this); } + + [DefaultValue(false), Description("DPI缩放"), Category("SunnyUI")] + public bool DPIScale + { + get => UIStyles.DPIScale; + set => UIStyles.DPIScale = value; + } } } \ No newline at end of file