diff --git a/SunnyUI/Common/UGraphics.cs b/SunnyUI/Common/UGraphics.cs index 9e666e50..3f613b21 100644 --- a/SunnyUI/Common/UGraphics.cs +++ b/SunnyUI/Common/UGraphics.cs @@ -33,6 +33,70 @@ namespace Sunny.UI /// public static class GraphicsEx { + public static string TruncateText(Graphics graphics, string text, Font font, float maxWidth) + { + // If the text is empty or null, return it as-is. + if (string.IsNullOrEmpty(text)) return text; + + // Measure the original string. + SizeF size = graphics.MeasureString(text, font); + + // If the original string fits within the width, return it as-is. + if (size.Width <= maxWidth) return text; + + // Otherwise, truncate the string until it fits. + string truncatedText = text; + for (int i = text.Length; i > 0; i--) + { + truncatedText = text.Left(i) + "..."; + size = graphics.MeasureString(truncatedText, font); + if (size.Width <= maxWidth) + break; + } + + return truncatedText; + } + + public static void DrawTruncateString(this Graphics g, string text, Font font, Color color, Rectangle rect, float maxWidth, HorizontalAlignment alignment) + { + text = TruncateText(g, text, font, maxWidth); + g.DrawString(text, font, color, rect, alignment.ToContentAlignment()); + } + + internal static ContentAlignment ToContentAlignment(this HorizontalAlignment alignment) + { + switch (alignment) + { + case HorizontalAlignment.Left: return ContentAlignment.MiddleLeft; + case HorizontalAlignment.Center: return ContentAlignment.MiddleCenter; + case HorizontalAlignment.Right: return ContentAlignment.MiddleRight; + } + + return ContentAlignment.MiddleLeft; + } + + internal static HorizontalAlignment ToHorizontalAlignment(this ContentAlignment alignment) + { + switch (alignment) + { + case ContentAlignment.TopLeft: + case ContentAlignment.MiddleLeft: + case ContentAlignment.BottomLeft: + return HorizontalAlignment.Left; + case ContentAlignment.TopCenter: + case ContentAlignment.MiddleCenter: + case ContentAlignment.BottomCenter: + return HorizontalAlignment.Center; + case ContentAlignment.TopRight: + case ContentAlignment.MiddleRight: + case ContentAlignment.BottomRight: + return HorizontalAlignment.Right; + } + + return HorizontalAlignment.Left; + } + + public static void DrawString(this Graphics g, string text, Font font, Color color, Rectangle rect, ContentAlignment alignment, int offsetX = 0, int offsetY = 0) { if (text.IsNullOrEmpty()) return; diff --git a/SunnyUI/Controls/UITabControl.cs b/SunnyUI/Controls/UITabControl.cs index 742a6824..e8fad1da 100644 --- a/SunnyUI/Controls/UITabControl.cs +++ b/SunnyUI/Controls/UITabControl.cs @@ -34,6 +34,7 @@ * 2023-11-06: V3.5.2 重构主题 * 2023-12-13: V3.6.2 优化UIPage的Init和Final加载逻辑 * 2024-11-29: V3.8.0 修复了SelectedIndex=-1时的报错 + * 2024-12-12: V3.8.0 修复标签文字越界显示 #IB8571 ******************************************************************************/ using System; @@ -639,6 +640,18 @@ namespace Sunny.UI TabRect = new Rectangle(GetTabRect(index).Location.X - 2, GetTabRect(index).Location.Y + 2, ItemSize.Width, ItemSize.Height); } + Rectangle textRect = new Rectangle(TabRect.Left + 4, TabRect.Top, TabRect.Width - 8, TabRect.Height); + if (ImageList != null) + { + textRect = new Rectangle(textRect.Left + ImageList.ImageSize.Width, textRect.Top, + textRect.Width - ImageList.ImageSize.Width, textRect.Height); + } + + if (ShowCloseButton || ShowActiveCloseButton) + { + textRect = new Rectangle(textRect.Left, textRect.Top, textRect.Width - 24, textRect.Height); + } + Size sf = TextRenderer.MeasureText(TabPages[index].Text, Font); int textLeft = ImageList?.ImageSize.Width ?? 0; if (ImageList != null) textLeft += 4 + 4 + 6; @@ -651,13 +664,17 @@ namespace Sunny.UI e.Graphics.FillRectangle(tabBackColor, TabRect); if (index == SelectedIndex) { - e.Graphics.FillRectangle(TabSelectedColor, TabRect); + var path = TabRect.CreateRoundedRectanglePath(5, UICornerRadiusSides.LeftTop | UICornerRadiusSides.RightTop); + e.Graphics.FillPath(TabSelectedColor, path, true); if (TabSelectedHighColorSize > 0) e.Graphics.FillRectangle(TabSelectedHighColor, TabRect.Left, TabRect.Height - TabSelectedHighColorSize, TabRect.Width, TabSelectedHighColorSize); } - e.Graphics.DrawString(TabPages[index].Text, Font, index == SelectedIndex ? tabSelectedForeColor : TabUnSelectedForeColor, - new Rectangle(TabRect.Left + textLeft, TabRect.Top, TabRect.Width, TabRect.Height), ContentAlignment.MiddleLeft); + //e.Graphics.DrawString(TabPages[index].Text, Font, index == SelectedIndex ? tabSelectedForeColor : TabUnSelectedForeColor, + // new Rectangle(TabRect.Left + textLeft, TabRect.Top, TabRect.Width, TabRect.Height), ContentAlignment.MiddleLeft); + + e.Graphics.DrawTruncateString(TabPages[index].Text, Font, index == SelectedIndex ? tabSelectedForeColor : TabUnSelectedForeColor, + textRect, textRect.Width, TabPageTextAlignment); TabPage tabPage = TabPages[index]; UIPage uiPage = Helper.GetPage(tabPage); @@ -704,6 +721,18 @@ namespace Sunny.UI } } + private HorizontalAlignment _tabPageTextAlignment = HorizontalAlignment.Left; + [DefaultValue(HorizontalAlignment.Left)] + public HorizontalAlignment TabPageTextAlignment + { + get => _tabPageTextAlignment; + set + { + _tabPageTextAlignment = value; + Invalidate(); + } + } + /// /// 重载鼠标移动事件 ///