diff --git a/Bin/SunnyUI.dll b/Bin/SunnyUI.dll index 3bac3c51..06d206c2 100644 Binary files a/Bin/SunnyUI.dll and b/Bin/SunnyUI.dll differ diff --git a/Bin/SunnyUI.pdb b/Bin/SunnyUI.pdb index c33cf149..3aa614dc 100644 Binary files a/Bin/SunnyUI.pdb and b/Bin/SunnyUI.pdb differ diff --git a/SunnyUI.Demo/Bin/SunnyUI.Demo.exe b/SunnyUI.Demo/Bin/SunnyUI.Demo.exe index b46845ec..2f86d3cb 100644 Binary files a/SunnyUI.Demo/Bin/SunnyUI.Demo.exe and b/SunnyUI.Demo/Bin/SunnyUI.Demo.exe differ diff --git a/SunnyUI.Demo/Bin/SunnyUI.dll b/SunnyUI.Demo/Bin/SunnyUI.dll index 3bac3c51..06d206c2 100644 Binary files a/SunnyUI.Demo/Bin/SunnyUI.dll and b/SunnyUI.Demo/Bin/SunnyUI.dll differ diff --git a/SunnyUI.Demo/Charts/FBarChart.cs b/SunnyUI.Demo/Charts/FBarChart.cs index 2dad7e64..4942a955 100644 --- a/SunnyUI.Demo/Charts/FBarChart.cs +++ b/SunnyUI.Demo/Charts/FBarChart.cs @@ -24,17 +24,17 @@ var series = new UIBarSeries(); series.Name = "Bar1"; - series.AddData(+11); - series.AddData(+15); - series.AddData(+12); - series.AddData(+14); - series.AddData(+13); + series.AddData(11); + series.AddData(15); + series.AddData(12); + series.AddData(14); + series.AddData(13); option.Series.Add(series); series = new UIBarSeries(); series.Name = "Bar2"; series.AddData(-22); - series.AddData(0); + series.AddData(-28); series.AddData(-25); series.AddData(-23); series.AddData(-24); @@ -47,6 +47,10 @@ option.XAxis.Data.Add("Fri"); option.ToolTip = new UIBarToolTip(); + option.YAxis.Scale = true; + + option.XAxis.Name = "日期"; + option.YAxis.Name = "数值"; BarChart.SetOption(option); } diff --git a/SunnyUI/Charts/UIBarChart.cs b/SunnyUI/Charts/UIBarChart.cs index 017f96f1..79f89c3b 100644 --- a/SunnyUI/Charts/UIBarChart.cs +++ b/SunnyUI/Charts/UIBarChart.cs @@ -37,7 +37,7 @@ namespace Sunny.UI NeedDraw = true; DrawBarWidth = DrawSize.Width * 1.0f / o.XAxis.Data.Count; - double min = Double.MaxValue; + double min = double.MaxValue; double max = double.MinValue; foreach (var series in o.Series) { @@ -45,18 +45,14 @@ namespace Sunny.UI max = Math.Max(max, series.Data.Max()); } - bool minZero = false; - bool maxZero = false; if (min > 0 && max > 0 && !o.YAxis.Scale) { min = 0; - minZero = true; } if (min < 0 && max < 0 && !o.YAxis.Scale) { max = 0; - maxZero = true; } UIChartHelper.CalcDegreeScale(min, max, o.YAxis.SplitNumber, @@ -77,20 +73,21 @@ namespace Sunny.UI for (int j = 0; j < series.Data.Count; j++) { - if (minZero) + if (YAxisStart >= 0) { - float h = Math.Abs((float)(DrawSize.Height * series.Data[j] / (end * interval))); + float h = Math.Abs((float)(DrawSize.Height * (series.Data[j]- start *interval) / ((end -start) * interval))); + Bars[i].Add(new BarInfo() { Rect = new RectangleF( - barX + x1 * (i + 1) + x2 * i, - DrawOrigin.Y - h, - x2, h) + barX + x1 * (i + 1) + x2 * i, + DrawOrigin.Y - h, + x2, h) }); } - else if (maxZero) + else if (YAxisEnd<=0) { - float h = Math.Abs((float)(DrawSize.Height * series.Data[j] / (start * interval))); + float h = Math.Abs((float)(DrawSize.Height * (end * interval-series.Data[j]) / ((end - start) * interval))); Bars[i].Add(new BarInfo() { Rect = new RectangleF( @@ -119,24 +116,24 @@ namespace Sunny.UI if (series.Data[j] >= 0) { - float h = Math.Abs((float)(highH *series.Data[j] /highV )); + float h = Math.Abs((float)(highH * series.Data[j] / highV)); Bars[i].Add(new BarInfo() { Rect = new RectangleF( barX + x1 * (i + 1) + x2 * i, - DrawOrigin.Y - lowH- h, + DrawOrigin.Y - lowH - h, x2, h) }); } else { - float h = Math.Abs((float)(lowH*series.Data[j] /lowV )); + float h = Math.Abs((float)(lowH * series.Data[j] / lowV)); Bars[i].Add(new BarInfo() { Rect = new RectangleF( barX + x1 * (i + 1) + x2 * i, - DrawOrigin.Y - lowH+1, - x2, h-1) + DrawOrigin.Y - lowH + 1, + x2, h - 1) }); } } @@ -210,8 +207,15 @@ namespace Sunny.UI tip.Size = new Size((int)Bars[0][selectIndex].Size.Width + 4, (int)Bars[0][selectIndex].Size.Height + 4); } - tip.Left = e.Location.X + 15; - tip.Top = e.Location.Y + 20; + int x = e.Location.X + 15; + int y = e.Location.Y + 20; + if (e.Location.X + 15 + tip.Width > Width - BarOption.Grid.Right) + x = e.Location.X - tip.Width - 2; + if (e.Location.Y + 20 + tip.Height > Height - BarOption.Grid.Bottom) + y = e.Location.Y - tip.Height - 2; + + tip.Left = x; + tip.Top = y; if (!tip.Visible) tip.Visible = Bars[0][selectIndex].Tips.IsValid(); } } @@ -304,7 +308,9 @@ namespace Sunny.UI private void DrawAxis(Graphics g) { - //g.DrawLine(ChartStyle.ForeColor, DrawOrigin, new Point(DrawOrigin.X + DrawSize.Width, DrawOrigin.Y)); + if (YAxisStart>=0) g.DrawLine(ChartStyle.ForeColor, DrawOrigin, new Point(DrawOrigin.X + DrawSize.Width, DrawOrigin.Y)); + if (YAxisEnd <= 0) g.DrawLine(ChartStyle.ForeColor, new Point(DrawOrigin.X, BarOption.Grid.Top), new Point(DrawOrigin.X + DrawSize.Width, BarOption.Grid.Top)); + g.DrawLine(ChartStyle.ForeColor, DrawOrigin, new Point(DrawOrigin.X, DrawOrigin.Y - DrawSize.Height)); if (BarOption.XAxis.AxisTick.Show) @@ -350,9 +356,12 @@ namespace Sunny.UI foreach (var data in BarOption.XAxis.Data) { SizeF sf = g.MeasureString(data, SubFont); - g.DrawString(data, SubFont, Color.FromArgb(150, ChartStyle.ForeColor), start - sf.Width / 2.0f, DrawOrigin.Y + BarOption.XAxis.AxisTick.Length); + g.DrawString(data, SubFont, ChartStyle.ForeColor, start - sf.Width / 2.0f, DrawOrigin.Y + BarOption.XAxis.AxisTick.Length); start += DrawBarWidth; } + + SizeF sfname = g.MeasureString(BarOption.XAxis.Name, SubFont); + g.DrawString(BarOption.XAxis.Name,SubFont,ChartStyle.ForeColor, DrawOrigin.X +(DrawSize.Width-sfname.Width)/2.0f, DrawOrigin.Y + BarOption.XAxis.AxisTick.Length +sfname.Height); } if (BarOption.YAxis.AxisTick.Show) @@ -393,13 +402,21 @@ namespace Sunny.UI float start = DrawOrigin.Y; float DrawBarHeight = DrawSize.Height * 1.0f / (YAxisEnd - YAxisStart); int idx = 0; + float wmax = 0; for (int i = YAxisStart; i <= YAxisEnd; i++) { string label = BarOption.YAxis.AxisLabel.GetLabel(i * YAxisInterval, idx); SizeF sf = g.MeasureString(label, SubFont); + wmax = Math.Max(wmax, sf.Width); g.DrawString(label, SubFont, ChartStyle.ForeColor, DrawOrigin.X - BarOption.YAxis.AxisTick.Length - sf.Width, start - sf.Height / 2.0f); start -= DrawBarHeight; } + + SizeF sfname = g.MeasureString(BarOption.YAxis.Name, SubFont); + int x = (int)(DrawOrigin.X - BarOption.YAxis.AxisTick.Length - wmax - sfname.Height); + int y = (int) (BarOption.Grid.Top + (DrawSize.Height - sfname.Width) / 2); + g.DrawString(BarOption.YAxis.Name,SubFont,ChartStyle.ForeColor, new Point(x,y), + new StringFormat(){Alignment = StringAlignment.Center}, 270); } } diff --git a/SunnyUI/Charts/UIOption.cs b/SunnyUI/Charts/UIOption.cs index 3ff4cfa5..1174d746 100644 --- a/SunnyUI/Charts/UIOption.cs +++ b/SunnyUI/Charts/UIOption.cs @@ -53,7 +53,7 @@ namespace Sunny.UI public int Left { get; set; } = 60; public int Right { get; set; } = 60; public int Top { get; set; } = 60; - public int Bottom { get; set; } = 40; + public int Bottom { get; set; } = 60; } public enum UIOrient diff --git a/SunnyUI/Controls/UIDataGridView.cs b/SunnyUI/Controls/UIDataGridView.cs index c4d7289b..e230b456 100644 --- a/SunnyUI/Controls/UIDataGridView.cs +++ b/SunnyUI/Controls/UIDataGridView.cs @@ -71,7 +71,7 @@ namespace Sunny.UI SelectionMode = DataGridViewSelectionMode.FullRowSelect; //禁止调整数据行行高 - AllowUserToResizeRows = false; + //AllowUserToResizeRows = false; //允许调整标题行行宽 AllowUserToResizeColumns = true; @@ -80,7 +80,7 @@ namespace Sunny.UI RowHeadersVisible = false; //禁止行多选 - MultiSelect = false; + //MultiSelect = false; //自动生成行 AutoGenerateColumns = true; diff --git a/SunnyUI/Static/UGDI.cs b/SunnyUI/Static/UGDI.cs index d2cdaa7f..1e5cfdad 100644 --- a/SunnyUI/Static/UGDI.cs +++ b/SunnyUI/Static/UGDI.cs @@ -641,5 +641,155 @@ namespace Sunny.UI } } } + + public static void DrawString(this Graphics g, string s, Font font, Color color, + RectangleF layoutRectangle, StringFormat format, float angle) + { + using (Brush br= new SolidBrush(color)) + { + g.DrawString(s,font,br,layoutRectangle,format,angle); + } + } + + public static void DrawString(this Graphics g, string s, Font font, Color color, + PointF point, StringFormat format, float angle) + { + using (Brush br = new SolidBrush(color)) + { + g.DrawString(s,font,br,point,format,angle); + } + } + + /// + /// 绘制根据矩形旋转文本 + /// + /// Graphics + /// 文本 + /// 字体 + /// 填充 + /// 局部矩形 + /// 布局方式 + /// 角度 + public static void DrawString(this Graphics g, string s, Font font, Brush brush, RectangleF layoutRectangle, StringFormat format, float angle) + { + // 求取字符串大小 + SizeF size = g.MeasureString(s, font); + + // 根据旋转角度,求取旋转后字符串大小 + SizeF sizeRotate = ConvertSize(size, angle); + + // 根据旋转后尺寸、布局矩形、布局方式计算文本旋转点 + PointF rotatePt = GetRotatePoint(sizeRotate, layoutRectangle, format); + + // 重设布局方式都为Center + StringFormat newFormat = new StringFormat(format); + newFormat.Alignment = StringAlignment.Center; + newFormat.LineAlignment = StringAlignment.Center; + + // 绘制旋转后文本 + g.DrawString(s, font, brush, rotatePt, newFormat, angle); + } + + /// + /// 绘制根据点旋转文本,一般旋转点给定位文本包围盒中心点 + /// + /// Graphics + /// 文本 + /// 字体 + /// 填充 + /// 旋转点 + /// 布局方式 + /// 角度 + public static void DrawString(this Graphics g, string s, Font font, Brush brush, PointF point, StringFormat format, float angle) + { + // Save the matrix + Matrix mtxSave = g.Transform; + + Matrix mtxRotate = g.Transform; + mtxRotate.RotateAt(angle, point); + g.Transform = mtxRotate; + + g.DrawString(s, font, brush, point, format); + + // Reset the matrix + g.Transform = mtxSave; + } + + private static SizeF ConvertSize(SizeF size, float angle) + { + Matrix matrix = new Matrix(); + matrix.Rotate(angle); + + // 旋转矩形四个顶点 + PointF[] pts = new PointF[4]; + pts[0].X = -size.Width / 2f; + pts[0].Y = -size.Height / 2f; + pts[1].X = -size.Width / 2f; + pts[1].Y = size.Height / 2f; + pts[2].X = size.Width / 2f; + pts[2].Y = size.Height / 2f; + pts[3].X = size.Width / 2f; + pts[3].Y = -size.Height / 2f; + matrix.TransformPoints(pts); + + // 求取四个顶点的包围盒 + float left = float.MaxValue; + float right = float.MinValue; + float top = float.MaxValue; + float bottom = float.MinValue; + + foreach (PointF pt in pts) + { + // 求取并集 + if (pt.X < left) + left = pt.X; + if (pt.X > right) + right = pt.X; + if (pt.Y < top) + top = pt.Y; + if (pt.Y > bottom) + bottom = pt.Y; + } + + SizeF result = new SizeF(right - left, bottom - top); + return result; + } + + private static PointF GetRotatePoint(SizeF size, RectangleF layoutRectangle, StringFormat format) + { + PointF pt = new PointF(); + + switch (format.Alignment) + { + case StringAlignment.Near: + pt.X = layoutRectangle.Left + size.Width / 2f; + break; + + case StringAlignment.Center: + pt.X = (layoutRectangle.Left + layoutRectangle.Right) / 2f; + break; + + case StringAlignment.Far: + pt.X = layoutRectangle.Right - size.Width / 2f; + break; + } + + switch (format.LineAlignment) + { + case StringAlignment.Near: + pt.Y = layoutRectangle.Top + size.Height / 2f; + break; + + case StringAlignment.Center: + pt.Y = (layoutRectangle.Top + layoutRectangle.Bottom) / 2f; + break; + + case StringAlignment.Far: + pt.Y = layoutRectangle.Bottom - size.Height / 2f; + break; + } + + return pt; + } } } \ No newline at end of file