本文以一個用戶控件【user control】實現溫度計的小例子,簡述用戶控件的相關知識,以供學習分享使用,如有不足之處,還請指正。
概述
一般而言,用戶控件【user control】,是在visual studio提供的默認控件不能滿足實際的工作需要,才需要在現有控件的基礎之上進行新的擴展,來實現自己的功能。用戶控件有自己特有的屬性,事件,方法來支撐特定的功能。用戶控件封裝實現的細節,可以進行方便的復用。
用戶控件分類
用戶控件主要有以下三種分類,本例采用的是第三種。
- 復合控件(composite controls):將現有的各種控件組合起來,形成一個新的控件,來滿足用戶的需求。
- 擴展控件(extended controls):就是在現有的控件基礎上,派生出一個新的控件,增加新的功能,或者修改原有功能,來滿足用戶需求。
- 自定義控件(custom controls):就是直接從usercontrol類派生,也就是說完全由自己來設計、實現一個全新的控件,這是最靈活、最強大的方法。
涉及知識點
本例中主要涉及以下知識點:
- usercontrol : 提供一個可用來創建其他控件的空控件。用戶創建一個用戶控件,會默認繼承這個類。
- onpaint :控件重繪方法,是protected修飾符,本例中需要重寫此方法。
- graphics : 密封類,不可被繼承,用于繪制圖形(包括矩形,扇形,直線等)。
- tooltip : 表示一個長方形的小彈出窗口,該窗口在用戶將指針懸停在一個控件上時顯示有關該控件用途的簡短說明。
- 鼠標事件函數:onmousehover 鼠標懸停時觸發函數,onmouseleave鼠標離開時觸發函數。
- datagridview:在可自定義的網格中顯示數據。
示例效果圖
本例中示例效果圖如下所示:
關鍵代碼
本例中的關鍵代碼如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
|
using system; using system.collections.generic; using system.componentmodel; using system.drawing; using system.data; using system.linq; using system.text; using system.threading.tasks; using system.windows.forms; namespace demothermometer { public partial class thermometer : usercontrol { #region 屬性與構造函數 private int interval = 10; /// <summary> /// 刻度間隔 /// </summary> public int interval { get { return interval; } set { interval = value; } } private int minvalue = -50; /// <summary> /// 最低溫度 /// </summary> public int minvalue { get { return minvalue; } set { minvalue = value; } } private int maxvalue = 50; /// <summary> /// 最高溫度 /// </summary> public int maxvalue { get { return maxvalue; } set { maxvalue = value; } } private float curvalue = 0; /// <summary> /// 當前溫度 /// </summary> public float curvalue { get { return curvalue; } set { curvalue = value; } } private color thermocolor = color.red; /// <summary> /// 溫度條顏色 /// </summary> public color thermocolor { get { return thermocolor; } set { thermocolor = value; } } private color backgroundcolor = color.skyblue; /// <summary> /// 溫度計背景色 /// </summary> public color backgroundcolor { get { return backgroundcolor; } set { backgroundcolor = value; } } private font thermofont= new font( "宋體" ,10,fontstyle.regular); /// <summary> /// 溫度計上字體 /// </summary> public font thermofont { get { return thermofont; } set { thermofont = value; } } private string thermotitle = "溫度計" ; /// <summary> /// 標題 /// </summary> public string thermotitle { get { return this .thermotitle; } set { this .thermotitle = value; } } private bool showtip = false ; /// <summary> /// 是否顯示提示 /// </summary> public bool showtip { get { return showtip; } set { showtip = value; } } private tooltip tip= new tooltip(); public thermometer() { initializecomponent(); } #endregion protected override void onpaint(painteventargs e) { //base.onpaint(e); //this.backcolor = this.backgroundcolor; int width = this .width; int height = this .height - 50 ; graphics g = e.graphics; int c_x = width / 2; int c_y = height / 2; int padding = this .padding.all; //空白 int r = (width - 2 * padding)/2; //半徑 int d = 2 * r; //直徑 int dis = 2; //兩個半圓之間的間隔 int dis2 = 2 * dis; //填充與邊框之間的距離 int startangle1 = -180; int startangle2 = 0; int sweepangle1 = 180; //首先畫頂端一個半圓 g.drawpie(pens.black, new rectangle(padding, padding, d, d),startangle1, sweepangle1); g.drawpie(pens.black, new rectangle(padding+ dis, padding+ dis, d-2* dis, d-2* dis), startangle1, sweepangle1); //填充背景色 g.fillpie( new solidbrush( this .backgroundcolor), new rectangle(padding + dis2, padding + dis2, d - 2*dis2, d - 2*dis2), startangle1, sweepangle1); //畫底端一個半圓 g.drawpie(pens.black, new rectangle(padding, height-d-padding, d, d), startangle2, sweepangle1); g.drawpie(pens.black, new rectangle(padding + dis, height-d-padding + dis, d - 2*dis, d - 2*dis), startangle2, sweepangle1); g.fillpie( new solidbrush( this .backgroundcolor), new rectangle(padding + dis2, height - d - padding+dis2, d - 2*dis2, d - 2*dis2), startangle2, sweepangle1); //畫一個矩形 g.drawrectangle(pens.black, new rectangle(padding, padding + r, d, height - d - 2 * padding)); g.drawrectangle(pens.black, new rectangle(padding+dis, padding + r+dis, d-2*dis, height - d - 2 * padding-2*dis)); //背景色填充,去掉邊界線 g.fillrectangle( new solidbrush( this .backgroundcolor), new rectangle(padding+3, padding + r-2, 2 * r-6, 6)); g.fillrectangle( new solidbrush( this .backgroundcolor), new rectangle(padding + 3, height-r-padding-4, 2 * r - 6, 8)); //背景色填充中間部分 g.fillrectangle( new solidbrush( this .backgroundcolor), new rectangle(padding + dis2, padding + r + dis2, d - 2*dis2, height -d - 2 * padding - 2*dis2)); //畫刻度 int s_s_x_1 = padding + r - 20; int s_s_x_2 = width-padding - r + 20; int s_s_y = padding + r+4; int total = this .maxvalue - this .minvalue; int scale_width = 5; //刻度寬度 int scale = total / this .interval; int pscale = (height - 2 * r - 2 * padding) / this .interval; //像素間隔 //豎線 g.drawline(pens.black, new point(s_s_x_1, s_s_y ), new point(s_s_x_1, s_s_y + this .interval* pscale)); g.drawline(pens.black, new point(s_s_x_2, s_s_y), new point(s_s_x_2, s_s_y + this .interval * pscale)); for ( int i = 0; i <= this .interval; i++) { //橫線刻度 g.drawline(pens.black, new point(s_s_x_1- scale_width, s_s_y + i * pscale), new point(s_s_x_1, s_s_y + i * pscale)); g.drawline(pens.black, new point(s_s_x_2, s_s_y + i * pscale), new point(s_s_x_2 + scale_width, s_s_y + i * pscale)); //畫刻度數字 g.drawstring(( this .maxvalue - (scale * i)).tostring(), this .thermofont, new solidbrush( this .forecolor), new point(s_s_x_1-35, s_s_y + i * pscale-10)); g.drawstring(( this .maxvalue - (scale * i)).tostring(), this .thermofont, new solidbrush( this .forecolor), new point(s_s_x_2 + 10, s_s_y + i * pscale-10)); } int white_width = 3; //中間白色線寬度 //畫條白色細線 g.fillrectangle(brushes.white, new rectangle(c_x- white_width, r/2, white_width*2, height-r)); //在底部畫一個圓球 g.fillpie( new solidbrush( this .thermocolor), new rectangle(c_x-r/2+5, height - r - padding, r-10, r-10), 0, 360); //根據當前溫度畫紅色線 int red_width = 5; //紅色溫度線寬度 float ii = ( this .curvalue- this .minvalue) / this .interval; g.fillrectangle( new solidbrush( this .thermocolor), new rectanglef(c_x - red_width, height - r - padding- (ii * pscale)-4, 2* red_width, ii * pscale+5)); //此處有一像素的誤差 //畫標志字符單℃位 g.drawstring( "℃" , this .thermofont, new solidbrush( this .forecolor), new point(c_x - 30, r / 2 - 10)); font titlefont = new font( "宋體" , 13, fontstyle.bold); //繪制標題 sizef tsize = g.measurestring( this .thermotitle, titlefont); g.drawstring( this .thermotitle, titlefont, new solidbrush( this .forecolor), new pointf(c_x- (tsize.width/2), height + 5)); string cur = string .format( "當前溫度:{0}℃" , this .curvalue); sizef tsize2 = g.measurestring(cur, this .thermofont); g.drawstring(cur, this .thermofont, new solidbrush( this .thermocolor), new pointf(c_x - (tsize2.width / 2), height + 10+tsize.height)); } /// <summary> /// 當鼠標覆蓋進去時 /// </summary> /// <param name="e"></param> protected override void onmousehover(eventargs e) { this .showtip = true ; //需要顯示的內容 int x = this .width / 2; int y = ( this .height-50) / 2; stringbuilder sbtips = new stringbuilder(); //sbtips.appendline(this.thermotitle); sbtips.appendline( string .format( "當前溫度:{0}" , this .curvalue)); sbtips.appendline( "單位:℃" ); tip.tooltiptitle = this .thermotitle; tip.isballoon = true ; tip.usefading = true ; //t.settooltip(this, sbtips.tostring()); tip.show(sbtips.tostring(), this , x, y); } protected override void onmouseleave(eventargs e) { this .showtip = false ; tip.hide( this ); } } } |
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。
原文鏈接:https://www.cnblogs.com/hsiang/archive/2018/03/18/8595982.html