(七十四)c#Winform自定义控件-金字塔图表
程序员文章站
2023-11-25 23:58:46
前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章。 GitHub:https://github.com/kwwwvagaa/NetWinformControl 码云:https://gitee.com/kwwwvagaa/net_winform_custom_contr ......
前提
入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章。
github:https://github.com/kwwwvagaa/netwinformcontrol
码云:
如果觉得写的还行,请点个 star 支持一下吧
欢迎前来交流探讨: 企鹅群568015492
麻烦博客下方点个【推荐】,谢谢
nuget
install-package hzh_controls
目录
用处及效果
准备工作
依然使用gdi+画图,不懂的先百度了解下
开始
添加一些枚举
1 public enum funelchartalignment 2 { 3 /// <summary> 4 /// the left 5 /// </summary> 6 left, 7 /// <summary> 8 /// the center 9 /// </summary> 10 center, 11 /// <summary> 12 /// the right 13 /// </summary> 14 right 15 } 16 17 public enum funelchartdirection 18 { 19 /// <summary> 20 /// up 21 /// </summary> 22 up, 23 /// <summary> 24 /// down 25 /// </summary> 26 down 27 }
添加一个项实体
1 public class funelchartitem 2 { 3 /// <summary> 4 /// gets or sets the text. 5 /// </summary> 6 /// <value>the text.</value> 7 public string text { get; set; } 8 /// <summary> 9 /// gets or sets the value. 10 /// </summary> 11 /// <value>the value.</value> 12 public float value { get; set; } 13 /// <summary> 14 /// gets or sets the color of the value. 15 /// </summary> 16 /// <value>the color of the value.</value> 17 public system.drawing.color? valuecolor { get; set; } 18 /// <summary> 19 /// gets or sets the color of the text fore. 20 /// </summary> 21 /// <value>the color of the text fore.</value> 22 public system.drawing.color? textforecolor { get; set; } 23 }
添加一个类ucfunnelchart ,继承usercontrol
添加一些控制属性
1 /// <summary> 2 /// the title 3 /// </summary> 4 private string title; 5 /// <summary> 6 /// gets or sets the title. 7 /// </summary> 8 /// <value>the title.</value> 9 [browsable(true)] 10 [category("自定义")] 11 [description("获取或设置标题")] 12 public string title 13 { 14 get { return title; } 15 set 16 { 17 title = value; 18 resettitlesize(); 19 invalidate(); 20 } 21 } 22 23 /// <summary> 24 /// the title font 25 /// </summary> 26 private font titlefont = new font("微软雅黑", 12); 27 /// <summary> 28 /// gets or sets the title font. 29 /// </summary> 30 /// <value>the title font.</value> 31 [browsable(true)] 32 [category("自定义")] 33 [description("获取或设置标题字体")] 34 public font titlefont 35 { 36 get { return titlefont; } 37 set 38 { 39 titlefont = value; 40 resettitlesize(); 41 invalidate(); 42 } 43 } 44 45 /// <summary> 46 /// the title fore color 47 /// </summary> 48 private color titleforecolor = color.black; 49 /// <summary> 50 /// gets or sets the color of the title fore. 51 /// </summary> 52 /// <value>the color of the title fore.</value> 53 [browsable(true)] 54 [category("自定义")] 55 [description("获取或设置标题文字颜色")] 56 public color titleforecolor 57 { 58 get { return titleforecolor; } 59 set 60 { 61 titleforecolor = value; 62 invalidate(); 63 } 64 } 65 /// <summary> 66 /// the items 67 /// </summary> 68 private funelchartitem[] items; 69 /// <summary> 70 /// gets or sets the items. 71 /// </summary> 72 /// <value>the items.</value> 73 [browsable(true)] 74 [category("自定义")] 75 [description("获取或设置项目")] 76 public funelchartitem[] items 77 { 78 get { return items; } 79 set 80 { 81 items = value; 82 invalidate(); 83 } 84 } 85 86 /// <summary> 87 /// the direction 88 /// </summary> 89 private funelchartdirection direction = funelchartdirection.up; 90 /// <summary> 91 /// gets or sets the direction. 92 /// </summary> 93 /// <value>the direction.</value> 94 [browsable(true)] 95 [category("自定义")] 96 [description("获取或设置方向")] 97 public funelchartdirection direction 98 { 99 get { return direction; } 100 set 101 { 102 direction = value; 103 invalidate(); 104 } 105 } 106 107 /// <summary> 108 /// the alignment 109 /// </summary> 110 private funelchartalignment alignment = funelchartalignment.center; 111 /// <summary> 112 /// gets or sets the alignment. 113 /// </summary> 114 /// <value>the alignment.</value> 115 [browsable(true)] 116 [category("自定义")] 117 [description("获取或设置对齐方式")] 118 public funelchartalignment alignment 119 { 120 get { return alignment; } 121 set 122 { 123 alignment = value; 124 invalidate(); 125 } 126 } 127 128 /// <summary> 129 /// the item text align 130 /// </summary> 131 private funelchartalignment itemtextalign = funelchartalignment.center; 132 /// <summary> 133 /// gets or sets the item text align. 134 /// </summary> 135 /// <value>the item text align.</value> 136 [browsable(true)] 137 [category("自定义")] 138 [description("获取或设置文字位置")] 139 public funelchartalignment itemtextalign 140 { 141 get { return itemtextalign; } 142 set 143 { 144 itemtextalign = value; 145 resetworkingrect(); 146 invalidate(); 147 } 148 } 149 /// <summary> 150 /// the show value 151 /// </summary> 152 private bool showvalue = false; 153 /// <summary> 154 /// gets or sets a value indicating whether [show value]. 155 /// </summary> 156 /// <value><c>true</c> if [show value]; otherwise, <c>false</c>.</value> 157 [browsable(true)] 158 [category("自定义")] 159 [description("获取或设置是否显示值")] 160 public bool showvalue 161 { 162 get { return showvalue; } 163 set 164 { 165 showvalue = value; 166 invalidate(); 167 } 168 } 169 170 171 /// <summary> 172 /// the value format 173 /// </summary> 174 private string valueformat = "0.##"; 175 /// <summary> 176 /// gets or sets the value format. 177 /// </summary> 178 /// <value>the value format.</value> 179 [browsable(true)] 180 [category("自定义")] 181 [description("获取或设置值格式化")] 182 public string valueformat 183 { 184 get { return valueformat; } 185 set 186 { 187 valueformat = value; 188 invalidate(); 189 } 190 } 191 192 /// <summary> 193 /// the m rect working 194 /// </summary> 195 rectanglef m_rectworking; 196 /// <summary> 197 /// the m title size 198 /// </summary> 199 sizef m_titlesize = sizef.empty; 200 /// <summary> 201 /// the int split width 202 /// </summary> 203 int intsplitwidth = 1;
构造函数初始化
1 public ucfunnelchart() 2 { 3 this.setstyle(controlstyles.allpaintinginwmpaint, true); 4 this.setstyle(controlstyles.doublebuffer, true); 5 this.setstyle(controlstyles.resizeredraw, true); 6 this.setstyle(controlstyles.selectable, true); 7 this.setstyle(controlstyles.supportstransparentbackcolor, true); 8 this.setstyle(controlstyles.userpaint, true); 9 this.fontchanged += ucfunnelchart_fontchanged; 10 font = new font("微软雅黑", 8); 11 12 this.autoscalemode = system.windows.forms.autoscalemode.none; 13 this.sizechanged += ucfunnelchart_sizechanged; 14 size = new system.drawing.size(150, 150); 15 items = new funelchartitem[0]; 16 if (controlhelper.isdesignmode()) 17 { 18 items = new funelchartitem[5]; 19 for (int i = 0; i < 5; i++) 20 { 21 items[i] = new funelchartitem() 22 { 23 text = "item" + i, 24 value = 10 * (i + 1) 25 }; 26 } 27 } 28 }
当大小及状态改变时 重新计算工作区域
1 void ucfunnelchart_fontchanged(object sender, eventargs e) 2 { 3 resetworkingrect(); 4 } 5 6 /// <summary> 7 /// handles the sizechanged event of the ucfunnelchart control. 8 /// </summary> 9 /// <param name="sender">the source of the event.</param> 10 /// <param name="e">the <see cref="eventargs"/> instance containing the event data.</param> 11 void ucfunnelchart_sizechanged(object sender, eventargs e) 12 { 13 resetworkingrect(); 14 } 15 16 /// <summary> 17 /// resets the working rect. 18 /// </summary> 19 private void resetworkingrect() 20 { 21 if (itemtextalign == funelchartalignment.center) 22 { 23 m_rectworking = new rectanglef(0, m_titlesize.height == 0 ? 0 : (m_titlesize.height + 10), this.width, this.height - (m_titlesize.height == 0 ? 0 : (m_titlesize.height + 10))); 24 } 25 else if (itemtextalign == funelchartalignment.left) 26 { 27 float fltmax = 0; 28 if (items != null && items.length > 0) 29 { 30 using (graphics g = this.creategraphics()) 31 { 32 fltmax = items.max(p => g.measurestring(p.text, font).width); 33 } 34 } 35 m_rectworking = new rectanglef(fltmax, m_titlesize.height == 0 ? 0 : (m_titlesize.height + 10), this.width - fltmax, this.height - (m_titlesize.height == 0 ? 0 : (m_titlesize.height + 10))); 36 } 37 else 38 { 39 float fltmax = 0; 40 if (items != null && items.length > 0) 41 { 42 using (graphics g = this.creategraphics()) 43 { 44 fltmax = items.max(p => g.measurestring(p.text, font).width); 45 } 46 } 47 m_rectworking = new rectanglef(0, m_titlesize.height == 0 ? 0 : (m_titlesize.height + 10), this.width - fltmax, this.height - (m_titlesize.height == 0 ? 0 : (m_titlesize.height + 10))); 48 } 49 } 50 51 /// <summary> 52 /// resets the size of the title. 53 /// </summary> 54 private void resettitlesize() 55 { 56 if (string.isnullorempty(title)) 57 { 58 m_titlesize = sizef.empty; 59 } 60 else 61 { 62 using (graphics g = this.creategraphics()) 63 { 64 m_titlesize = g.measurestring(title, titlefont); 65 m_titlesize.height += 20; 66 } 67 } 68 resetworkingrect(); 69 }
重绘
1 protected override void onpaint(painteventargs e) 2 { 3 base.onpaint(e); 4 var g = e.graphics; 5 g.setgdihigh(); 6 7 if (!string.isnullorempty(title)) 8 { 9 g.drawstring(title, titlefont, new solidbrush(titleforecolor), new rectanglef(0, 0, this.width, m_titlesize.height), new stringformat() { alignment = stringalignment.center, linealignment = stringalignment.center }); 10 } 11 12 if (items == null || items.length <= 0) 13 { 14 g.drawstring("没有数据", font, new solidbrush(color.black), this.m_rectworking, new stringformat() { alignment = stringalignment.center, linealignment = stringalignment.center }); 15 return; 16 } 17 18 list<funelchartitem> lstitems; 19 if (direction == funelchartdirection.up) 20 { 21 lstitems = items.orderby(p => p.value).tolist(); 22 } 23 else 24 { 25 lstitems = items.orderbydescending(p => p.value).tolist(); 26 } 27 28 list<rectanglef> lstrects = new list<rectanglef>(); 29 list<graphicspath> lstpaths = new list<graphicspath>(); 30 float maxvalue = lstitems.max(p => p.value); 31 float dblsplitheight = m_rectworking.height / lstitems.count; 32 for (int i = 0; i < lstitems.count; i++) 33 { 34 funelchartitem item = lstitems[i]; 35 if (item.valuecolor == null || item.valuecolor == color.empty || item.valuecolor == color.transparent) 36 item.valuecolor = controlhelper.colors[i]; 37 38 switch (alignment) 39 { 40 case funelchartalignment.left: 41 lstrects.add(new rectanglef(m_rectworking.left, m_rectworking.top + dblsplitheight * i, item.value / maxvalue * m_rectworking.width, dblsplitheight)); 42 break; 43 case funelchartalignment.center: 44 lstrects.add(new rectanglef(m_rectworking.left + (m_rectworking.width - (item.value / maxvalue * m_rectworking.width)) / 2, m_rectworking.top + dblsplitheight * i, item.value / maxvalue * m_rectworking.width, dblsplitheight)); 45 break; 46 case funelchartalignment.right: 47 lstrects.add(new rectanglef(m_rectworking.right - (item.value / maxvalue * m_rectworking.width), m_rectworking.top + dblsplitheight * i, item.value / maxvalue * m_rectworking.width, dblsplitheight)); 48 break; 49 } 50 } 51 52 for (int i = 0; i < lstrects.count; i++) 53 { 54 var rect = lstrects[i]; 55 graphicspath path = new graphicspath(); 56 list<pointf> lstpoints = new list<pointf>(); 57 if (direction == funelchartdirection.up) 58 { 59 switch (alignment) 60 { 61 case funelchartalignment.left: 62 lstpoints.add(new pointf(rect.left, rect.top)); 63 if (i != 0) 64 { 65 lstpoints.add(new pointf(lstrects[i - 1].right, rect.top)); 66 } 67 break; 68 case funelchartalignment.center: 69 if (i == 0) 70 { 71 lstpoints.add(new pointf(rect.left + rect.width / 2, rect.top)); 72 } 73 else 74 { 75 lstpoints.add(new pointf(lstrects[i - 1].left, rect.top)); 76 lstpoints.add(new pointf(lstrects[i - 1].right, rect.top)); 77 } 78 break; 79 case funelchartalignment.right: 80 if (i == 0) 81 { 82 lstpoints.add(new pointf(rect.right, rect.top)); 83 } 84 else 85 { 86 lstpoints.add(new pointf(rect.right - lstrects[i - 1].width, rect.top)); 87 lstpoints.add(new pointf(rect.right, rect.top)); 88 } 89 break; 90 } 91 lstpoints.add(new pointf(rect.right, rect.bottom - intsplitwidth)); 92 lstpoints.add(new pointf(rect.left, rect.bottom - intsplitwidth)); 93 } 94 else 95 { 96 lstpoints.add(new pointf(rect.left, rect.top + intsplitwidth)); 97 lstpoints.add(new pointf(rect.right, rect.top + intsplitwidth)); 98 switch (alignment) 99 { 100 case funelchartalignment.left: 101 if (i == lstrects.count - 1) 102 { 103 lstpoints.add(new pointf(rect.left, rect.bottom)); 104 } 105 else 106 { 107 lstpoints.add(new pointf(lstrects[i + 1].right, rect.bottom)); 108 lstpoints.add(new pointf(rect.left, rect.bottom)); 109 } 110 break; 111 case funelchartalignment.center: 112 if (i == lstrects.count - 1) 113 { 114 lstpoints.add(new pointf(rect.left + rect.width / 2, rect.bottom)); 115 } 116 else 117 { 118 lstpoints.add(new pointf(lstrects[i + 1].right, rect.bottom)); 119 lstpoints.add(new pointf(lstrects[i + 1].left, rect.bottom)); 120 } 121 break; 122 case funelchartalignment.right: 123 if (i == lstrects.count - 1) 124 { 125 lstpoints.add(new pointf(rect.right, rect.bottom)); 126 } 127 else 128 { 129 lstpoints.add(new pointf(rect.right, rect.bottom)); 130 lstpoints.add(new pointf(lstrects[i + 1].left, rect.bottom)); 131 } 132 break; 133 } 134 } 135 path.addlines(lstpoints.toarray()); 136 path.closeallfigures(); 137 // g.drawpath(new pen(new solidbrush(lstitems[i].valuecolor.value)), path); 138 g.fillpath(new solidbrush(lstitems[i].valuecolor.value), path); 139 140 //写字 141 if (itemtextalign == funelchartalignment.center) 142 { 143 g.drawstring(lstitems[i].text + (showvalue ? lstitems[i].value.tostring("\n" + valueformat) : ""), font, new solidbrush((lstitems[i].textforecolor == null || lstitems[i].textforecolor == color.empty || lstitems[i].textforecolor == color.transparent) ? color.white : lstitems[i].textforecolor.value), rect, new stringformat() { alignment = stringalignment.center, linealignment = stringalignment.center }); 144 } 145 else if (itemtextalign == funelchartalignment.left) 146 { 147 g.drawstring(lstitems[i].text + (showvalue ? lstitems[i].value.tostring("\n" + valueformat) : ""), font, new solidbrush((lstitems[i].textforecolor == null || lstitems[i].textforecolor == color.empty || lstitems[i].textforecolor == color.transparent) ? lstitems[i].valuecolor.value : lstitems[i].textforecolor.value), new rectanglef(0, rect.top, rect.left, rect.height), new stringformat() { alignment = stringalignment.far, linealignment = stringalignment.center }); 148 g.drawline(new pen(new solidbrush((lstitems[i].textforecolor == null || lstitems[i].textforecolor == color.empty || lstitems[i].textforecolor == color.transparent) ? lstitems[i].valuecolor.value : lstitems[i].textforecolor.value)), rect.left, rect.top + rect.height / 2, rect.left + rect.width / 2, rect.top + rect.height / 2); 149 } 150 else 151 { 152 g.drawstring(lstitems[i].text + (showvalue ? lstitems[i].value.tostring("\n" + valueformat) : ""), font, new solidbrush((lstitems[i].textforecolor == null || lstitems[i].textforecolor == color.empty || lstitems[i].textforecolor == color.transparent) ? lstitems[i].valuecolor.value : lstitems[i].textforecolor.value), new rectanglef(rect.right, rect.top, this.width - rect.right, rect.height), new stringformat() { alignment = stringalignment.near, linealignment = stringalignment.center }); 153 g.drawline(new pen(new solidbrush((lstitems[i].textforecolor == null || lstitems[i].textforecolor == color.empty || lstitems[i].textforecolor == color.transparent) ? lstitems[i].valuecolor.value : lstitems[i].textforecolor.value)), rect.left + rect.width / 2, rect.top + rect.height / 2, rect.right, rect.top + rect.height / 2); 154 } 155 } 156 }
完整代码
1 // *********************************************************************** 2 // assembly : hzh_controls 3 // created : 2019-09-26 4 // 5 // *********************************************************************** 6 // <copyright file="ucfunnelchart.cs"> 7 // copyright by huang zhenghui(黄正辉) all, qq group:568015492 qq:623128629 email:623128629@qq.com 8 // </copyright> 9 // 10 // blog: https://www.cnblogs.com/bfyx 11 // github:https://github.com/kwwwvagaa/netwinformcontrol 12 // gitee:https://gitee.com/kwwwvagaa/net_winform_custom_control.git 13 // 14 // if you use this code, please keep this note. 15 // *********************************************************************** 16 using system; 17 using system.collections.generic; 18 using system.linq; 19 using system.text; 20 using system.windows.forms; 21 using system.drawing; 22 using system.drawing.drawing2d; 23 using system.componentmodel; 24 25 namespace hzh_controls.controls 26 { 27 /// <summary> 28 /// class ucfunnelchart. 29 /// implements the <see cref="system.windows.forms.usercontrol" /> 30 /// </summary> 31 /// <seealso cref="system.windows.forms.usercontrol" /> 32 public class ucfunnelchart : usercontrol 33 { 34 /// <summary> 35 /// the title 36 /// </summary> 37 private string title; 38 /// <summary> 39 /// gets or sets the title. 40 /// </summary> 41 /// <value>the title.</value> 42 [browsable(true)] 43 [category("自定义")] 44 [description("获取或设置标题")] 45 public string title 46 { 47 get { return title; } 48 set 49 { 50 title = value; 51 resettitlesize(); 52 invalidate(); 53 } 54 } 55 56 /// <summary> 57 /// the title font 58 /// </summary> 59 private font titlefont = new font("微软雅黑", 12); 60 /// <summary> 61 /// gets or sets the title font. 62 /// </summary> 63 /// <value>the title font.</value> 64 [browsable(true)] 65 [category("自定义")] 66 [description("获取或设置标题字体")] 67 public font titlefont 68 { 69 get { return titlefont; } 70 set 71 { 72 titlefont = value; 73 resettitlesize(); 74 invalidate(); 75 } 76 } 77 78 /// <summary> 79 /// the title fore color 80 /// </summary> 81 private color titleforecolor = color.black; 82 /// <summary> 83 /// gets or sets the color of the title fore. 84 /// </summary> 85 /// <value>the color of the title fore.</value> 86 [browsable(true)] 87 [category("自定义")] 88 [description("获取或设置标题文字颜色")] 89 public color titleforecolor 90 { 91 get { return titleforecolor; } 92 set 93 { 94 titleforecolor = value; 95 invalidate(); 96 } 97 } 98 /// <summary> 99 /// the items 100 /// </summary> 101 private funelchartitem[] items; 102 /// <summary> 103 /// gets or sets the items. 104 /// </summary> 105 /// <value>the items.</value> 106 [browsable(true)] 107 [category("自定义")] 108 [description("获取或设置项目")] 109 public funelchartitem[] items 110 { 111 get { return items; } 112 set 113 { 114 items = value; 115 invalidate(); 116 } 117 } 118 119 /// <summary> 120 /// the direction 121 /// </summary> 122 private funelchartdirection direction = funelchartdirection.up; 123 /// <summary> 124 /// gets or sets the direction. 125 /// </summary> 126 /// <value>the direction.</value> 127 [browsable(true)] 128 [category("自定义")] 129 [description("获取或设置方向")] 130 public funelchartdirection direction 131 { 132 get { return direction; } 133 set 134 { 135 direction = value; 136 invalidate(); 137 } 138 } 139 140 /// <summary> 141 /// the alignment 142 /// </summary> 143 private funelchartalignment alignment = funelchartalignment.center; 144 /// <summary> 145 /// gets or sets the alignment. 146 /// </summary> 147 /// <value>the alignment.</value> 148 [browsable(true)] 149 [category("自定义")] 150 [description("获取或设置对齐方式")] 151 public funelchartalignment alignment 152 { 153 get { return alignment; } 154 set 155 { 156 alignment = value; 157 invalidate(); 158 } 159 } 160 161 /// <summary> 162 /// the item text align 163 /// </summary> 164 private funelchartalignment itemtextalign = funelchartalignment.center; 165 /// <summary> 166 /// gets or sets the item text align. 167 /// </summary> 168 /// <value>the item text align.</value> 169 [browsable(true)] 170 [category("自定义")] 171 [description("获取或设置文字位置")] 172 public funelchartalignment itemtextalign 173 { 174 get { return itemtextalign; } 175 set 176 { 177 itemtextalign = value; 178 resetworkingrect(); 179 invalidate(); 180 } 181 } 182 /// <summary> 183 /// the show value 184 /// </summary> 185 private bool showvalue = false; 186 /// <summary> 187 /// gets or sets a value indicating whether [show value]. 188 /// </summary> 189 /// <value><c>true</c> if [show value]; otherwise, <c>false</c>.</value> 190 [browsable(true)] 191 [category("自定义")] 192 [description("获取或设置是否显示值")] 193 public bool showvalue 194 { 195 get { return showvalue; } 196 set 197 { 198 showvalue = value; 199 invalidate(); 200 } 201 } 202 203 204 /// <summary> 205 /// the value format 206 /// </summary> 207 private string valueformat = "0.##"; 208 /// <summary> 209 /// gets or sets the value format. 210 /// </summary> 211 /// <value>the value format.</value> 212 [browsable(true)] 213 [category("自定义")] 214 [description("获取或设置值格式化")] 215 public string valueformat 216 { 217 get { return valueformat; } 218 set 219 { 220 valueformat = value; 221 invalidate(); 222 } 223 } 224 225 /// <summary> 226 /// the m rect working 227 /// </summary> 228 rectanglef m_rectworking; 229 /// <summary> 230 /// the m title size 231 /// </summary> 232 sizef m_titlesize = sizef.empty; 233 /// <summary> 234 /// the int split width 235 /// </summary> 236 int intsplitwidth = 1; 237 238 /// <summary> 239 /// initializes a new instance of the <see cref="ucfunnelchart"/> class. 240 /// </summary> 241 public ucfunnelchart() 242 { 243 this.setstyle(controlstyles.allpaintinginwmpaint, true); 244 this.setstyle(controlstyles.doublebuffer, true); 245 this.setstyle(controlstyles.resizeredraw, true); 246 this.setstyle(controlstyles.selectable, true); 247 this.setstyle(controlstyles.supportstransparentbackcolor, true); 248 this.setstyle(controlstyles.userpaint, true); 249 this.fontchanged += ucfunnelchart_fontchanged; 250 font = new font("微软雅黑", 8); 251 252 this.autoscalemode = system.windows.forms.autoscalemode.none; 253 this.sizechanged += ucfunnelchart_sizechanged; 254 size = new system.drawing.size(150, 150); 255 items = new funelchartitem[0]; 256 if (controlhelper.isdesignmode()) 257 { 258 items = new funelchartitem[5]; 259 for (int i = 0; i < 5; i++) 260 { 261 items[i] = new funelchartitem() 262 { 263 text = "item" + i, 264 value = 10 * (i + 1) 265 }; 266 } 267 } 268 } 269 270 /// <summary> 271 /// handles the fontchanged event of the ucfunnelchart control. 272 /// </summary> 273 /// <param name="sender">the source of the event.</param> 274 /// <param name="e">the <see cref="eventargs"/> instance containing the event data.</param> 275 void ucfunnelchart_fontchanged(object sender, eventargs e) 276 { 277 resetworkingrect(); 278 } 279 280 /// <summary> 281 /// handles the sizechanged event of the ucfunnelchart control. 282 /// </summary> 283 /// <param name="sender">the source of the event.</param> 284 /// <param name="e">the <see cref="eventargs"/> instance containing the event data.</param> 285 void ucfunnelchart_sizechanged(object sender, eventargs e) 286 { 287 resetworkingrect(); 288 } 289 290 /// <summary> 291 /// resets the working rect. 292 /// </summary> 293 private void resetworkingrect() 294 { 295 if (itemtextalign == funelchartalignment.center) 296 { 297 m_rectworking = new rectanglef(0, m_titlesize.height == 0 ? 0 : (m_titlesize.height + 10), this.width, this.height - (m_titlesize.height == 0 ? 0 : (m_titlesize.height + 10))); 298 } 299 else if (itemtextalign == funelchartalignment.left) 300 { 301 float fltmax = 0; 302 if (items != null && items.length > 0) 303 { 304 using (graphics g = this.creategraphics()) 305 { 306 fltmax = items.max(p => g.measurestring(p.text, font).width); 307 } 308 } 309 m_rectworking = new rectanglef(fltmax, m_titlesize.height == 0 ? 0 : (m_titlesize.height + 10), this.width - fltmax, this.height - (m_titlesize.height == 0 ? 0 : (m_titlesize.height + 10))); 310 } 311 else 312 { 313 float fltmax = 0; 314 if (items != null && items.length > 0) 315 { 316 using (graphics g = this.creategraphics()) 317 { 318 fltmax = items.max(p => g.measurestring(p.text, font).width); 319 } 320 } 321 m_rectworking = new rectanglef(0, m_titlesize.height == 0 ? 0 : (m_titlesize.height + 10), this.width - fltmax, this.height - (m_titlesize.height == 0 ? 0 : (m_titlesize.height + 10))); 322 } 323 } 324 325 /// <summary> 326 /// resets the size of the title. 327 /// </summary> 328 private void resettitlesize() 329 { 330 if (string.isnullorempty(title)) 331 { 332 m_titlesize = sizef.empty; 333 } 334 else 335 { 336 using (graphics g = this.creategraphics()) 337 { 338 m_titlesize = g.measurestring(title, titlefont); 339 m_titlesize.height += 20; 340 } 341 } 342 resetworkingrect(); 343 } 344 345 /// <summary> 346 /// 引发 <see cref="e:system.windows.forms.control.paint" /> 事件。 347 /// </summary> 348 /// <param name="e">包含事件数据的 <see cref="t:system.windows.forms.painteventargs" />。</param> 349 protected override void onpaint(painteventargs e) 350 { 351 base.onpaint(e); 352 var g = e.graphics; 353 g.setgdihigh(); 354 355 if (!string.isnullorempty(title)) 356 { 357 g.drawstring(title, titlefont, new solidbrush(titleforecolor), new rectanglef(0, 0, this.width, m_titlesize.height), new stringformat() { alignment = stringalignment.center, linealignment = stringalignment.center }); 358 } 359 360 if (items == null || items.length <= 0) 361 { 362 g.drawstring("没有数据", font, new solidbrush(color.black), this.m_rectworking, new stringformat() { alignment = stringalignment.center, linealignment = stringalignment.center }); 363 return; 364 } 365 366 list<funelchartitem> lstitems; 367 if (direction == funelchartdirection.up) 368 { 369 lstitems = items.orderby(p => p.value).tolist(); 370 } 371 else 372 { 373 lstitems = items.orderbydescending(p => p.value).tolist(); 374 } 375 376 list<rectanglef> lstrects = new list<rectanglef>(); 377 list<graphicspath> lstpaths = new list<graphicspath>(); 378 float maxvalue = lstitems.max(p => p.value); 379 float dblsplitheight = m_rectworking.height / lstitems.count; 380 for (int i = 0; i < lstitems.count; i++) 381 { 382 funelchartitem item = lstitems[i]; 383 if (item.valuecolor == null || item.valuecolor == color.empty || item.valuecolor == color.transparent) 384 item.valuecolor = controlhelper.colors[i]; 385 386 switch (alignment) 387 { 388 case funelchartalignment.left: 389 lstrects.add(new rectanglef(m_rectworking.left, m_rectworking.top + dblsplitheight * i, item.value / maxvalue * m_rectworking.width, dblsplitheight)); 390 break; 391 case funelchartalignment.center: 392 lstrects.add(new rectanglef(m_rectworking.left + (m_rectworking.width - (item.value / maxvalue * m_rectworking.width)) / 2, m_rectworking.top + dblsplitheight * i, item.value / maxvalue * m_rectworking.width, dblsplitheight)); 393 break; 394 case funelchartalignment.right: 395 lstrects.add(new rectanglef(m_rectworking.right - (item.value / maxvalue * m_rectworking.width), m_rectworking.top + dblsplitheight * i, item.value / maxvalue * m_rectworking.width, dblsplitheight)); 396 break; 397 } 398 } 399 400 for (int i = 0; i < lstrects.count; i++) 401 { 402 var rect = lstrects[i]; 403 graphicspath path = new graphicspath(); 404 list<pointf> lstpoints = new list<pointf>(); 405 if (direction == funelchartdirection.up) 406 { 407 switch (alignment) 408 { 409 case funelchartalignment.left: 410 lstpoints.add(new pointf(rect.left, rect.top)); 411 if (i != 0) 412 { 413 lstpoints.add(new pointf(lstrects[i - 1].right, rect.top)); 414 } 415 break; 416 case funelchartalignment.center: 417 if (i == 0) 418 { 419 lstpoints.add(new pointf(rect.left + rect.width / 2, rect.top)); 420 } 421 else 422 { 423 lstpoints.add(new pointf(lstrects[i - 1].left, rect.top)); 424 lstpoints.add(new pointf(lstrects[i - 1].right, rect.top)); 425 } 426 break; 427 case funelchartalignment.right: 428 if (i == 0) 429 { 430 lstpoints.add(new pointf(rect.right, rect.top)); 431 } 432 else 433 { 434 lstpoints.add(new pointf(rect.right - lstrects[i - 1].width, rect.top)); 435 lstpoints.add(new pointf(rect.right, rect.top)); 436 } 437 break; 438 } 439 lstpoints.add(new pointf(rect.right, rect.bottom - intsplitwidth)); 440 lstpoints.add(new pointf(rect.left, rect.bottom - intsplitwidth)); 441 } 442 else 443 { 444 lstpoints.add(new pointf(rect.left, rect.top + intsplitwidth)); 445 lstpoints.add(new pointf(rect.right, rect.top + intsplitwidth)); 446 switch (alignment) 447 { 448 case funelchartalignment.left: 449 if (i == lstrects.count - 1) 450 { 451 lstpoints.add(new pointf(rect.left, rect.bottom)); 452 } 453 else 454 { 455 lstpoints.add(new pointf(lstrects[i + 1].right, rect.bottom)); 456 lstpoints.add(new pointf(rect.left, rect.bottom)); 457 } 458 break; 459 case funelchartalignment.center: 460 if (i == lstrects.count - 1) 461 { 462 lstpoints.add(new pointf(rect.left + rect.width / 2, rect.bottom)); 463 } 464 else 465 { 466 lstpoints.add(new pointf(lstrects[i + 1].right, rect.bottom)); 467 lstpoints.add(new pointf(lstrects[i + 1].left, rect.bottom)); 468 } 469 break; 470 case funelchartalignment.right: 471 if (i == lstrects.count - 1) 472 { 473 lstpoints.add(new pointf(rect.right, rect.bottom)); 474 } 475 else 476 { 477 lstpoints.add(new pointf(rect.right, rect.bottom)); 478 lstpoints.add(new pointf(lstrects[i + 1].left, rect.bottom)); 479 } 480 break; 481 } 482 } 483 path.addlines(lstpoints.toarray()); 484 path.closeallfigures(); 485 // g.drawpath(new pen(new solidbrush(lstitems[i].valuecolor.value)), path); 486 g.fillpath(new solidbrush(lstitems[i].valuecolor.value), path); 487 488 //写字 489 if (itemtextalign == funelchartalignment.center) 490 { 491 g.drawstring(lstitems[i].text + (showvalue ? lstitems[i].value.tostring("\n" + valueformat) : ""), font, new solidbrush((lstitems[i].textforecolor == null || lstitems[i].textforecolor == color.empty || lstitems[i].textforecolor == color.transparent) ? color.white : lstitems[i].textforecolor.value), rect, new stringformat() { alignment = stringalignment.center, linealignment = stringalignment.center }); 492 } 493 else if (itemtextalign == funelchartalignment.left) 494 { 495 g.drawstring(lstitems[i].text + (showvalue ? lstitems[i].value.tostring("\n" + valueformat) : ""), font, new solidbrush((lstitems[i].textforecolor == null || lstitems[i].textforecolor == color.empty || lstitems[i].textforecolor == color.transparent) ? lstitems[i].valuecolor.value : lstitems[i].textforecolor.value), new rectanglef(0, rect.top, rect.left, rect.height), new stringformat() { alignment = stringalignment.far, linealignment = stringalignment.center }); 496 g.drawline(new pen(new solidbrush((lstitems[i].textforecolor == null || lstitems[i].textforecolor == color.empty || lstitems[i].textforecolor == color.transparent) ? lstitems[i].valuecolor.value : lstitems[i].textforecolor.value)), rect.left, rect.top + rect.height / 2, rect.left + rect.width / 2, rect.top + rect.height / 2); 497 } 498 else 499 { 500 g.drawstring(lstitems[i].text + (showvalue ? lstitems[i].value.tostring("\n" + valueformat) : ""), font, new solidbrush((lstitems[i].textforecolor == null || lstitems[i].textforecolor == color.empty || lstitems[i].textforecolor == color.transparent) ? lstitems[i].valuecolor.value : lstitems[i].textforecolor.value), new rectanglef(rect.right, rect.top, this.width - rect.right, rect.height), new stringformat() { alignment = stringalignment.near, linealignment = stringalignment.center }); 501 g.drawline(new pen(new solidbrush((lstitems[i].textforecolor == null || lstitems[i].textforecolor == color.empty || lstitems[i].textforecolor == color.transparent) ? lstitems[i].valuecolor.value : lstitems[i].textforecolor.value)), rect.left + rect.width / 2, rect.top + rect.height / 2, rect.right, rect.top + rect.height / 2); 502 } 503 } 504 } 505 } 506 }
最后的话
如果你喜欢的话,请到 点个星星吧