比赛训练笔记 - WinForm
DataGridView
使用错误容器时的巨坑
使用 List 作为 DataSource。点击单元格时,就算没有单元格点击事件,也会在外层(父窗体 ShowDialog 子窗体的位置)报 IndexOutOfRange 下标越界异常。
解决方法:只要是用于 DGV 显示的列表,一律用BindingList
。
BindingList
用ResetBinding()
(对于整个列表)或ResetItem(i)
(对于特定元素)来手动触发“列表已改变”事件。
用RaiseListChangedEvents
属性控制 BindingList 是否会发出“列表已改变”的事件。
注意:这个属性不仅控制添加和删除元素时是否会自动触发事件,同时也控制ResetBinding() / ResetItem(i)
这类手动触发事件的方法是否会触发事件。
添加向列表大量元素时的标准流程:
list.RaiseListChangedEvents = false;
list.Clear();
foreach(var item in source)
{
list.Add(item);
}
// 一定要先启用事件,然后再手动触发事件。
list.RaiseListChangedEvents = true;
list.ResetBindings();
外观与杂项行为
- 内容多行显示:
DefaultCellStyle
属性集合 →WrapMode
属性设置为 True。
AutoSizeRowsMode 行自动大小模式设置为 AllCells,行大小会自动匹配内容高度。 表头是否可见:
- 左侧行头:
RowHeaderVisible
属性。 - 顶部列头:
ColumnHeaderVisible
属性。
- 左侧行头:
- 是否可多选:
MultiSelect
属性。 - 整行选择:
SelectionMode
设置为 FullRowSelect。整行选择不会影响单元格点击。
在 ContentClick 内容点击事件中,如果用户选择了表头,则e.RowIndex
为 -1。
在 CellFormat 单元格格式化事件中,e.FormatApplied
控制是否还要使用其他格式化器继续格式化内容。如果设置为 true,则不会继续进行格式化。如果只是修改了颜色,就不要设置这个属性。否则如果内容不是文本形式,就会报错。
Timer
Timer 会自动重复。
Start() / Stop()
方法和设置Enabled
属性的功能相等。
Timer 不受 ShowDialog 阻塞线程的影响。但是 Timer.Tick “时间到了”事件始终在UI线程上运行。
Timer会在窗体对象存在时一直运作。在窗体 Close 之后,如果没有Dispose
,Timer 还是会一直在后台运行。
自定义绘制
用控件的CreateGraphics()
方法创建画布。
Graphics g = this.CreateGraphics();
因此,一定要在控件的Paint事件中进行绘制。
绘制图形需要画笔 Pen 对象。
Pen pen = new Pen(color, width);
像素
直接设置 Image 指定位置的像素颜色。
image.SetPixel(x, y, color);
直线(Line)
g.DrawLine(pen, pointStart, pointEnd);
矩形(Rectangle)
g.DrawRectangle(pen, x, y, width, height);
椭圆(Ellipse)
g.DrawEllipse(pen, x, y, width, height);
圆弧(Arc)
角度从右边开始,顺时针。
在矩形中画椭圆(定义的矩形是椭圆的 bounding box),传入的角度会作 cos 和 sin 定位到圆上的点。
从startAngle
开始,顺时针推进advanceAngle
角度作为终点。
g.DrawArc(pen, rect, startAngle, advanceAngle);
扇形(Pie)
使用方法同圆弧,但是圆弧的开头和结尾会与圆心连直线。
g.DrawPie(pen, rect, startAngle, advanceAngle);
贝塞尔曲线(Bezier)
由起点、控制点 1(位于起点处)、控制点 2(位于终点处)、终点组成。
g.DrawBezier(pen, pointStart, pointControl1, pointControl2, pointEnd);
多边形(Polygon)
传入顶点数组,顶点之间依次连接直线,绘制出多边形。
Point[] vertices = {...};
g.DrawPolygon(pen, vertices)
文本(String)
绘制文本需要字体 Font 和画刷 Brush 对象。
Brush 类型通常有:
- SolidBrush:纯色
- LinearGradientBrush:线性渐变色
Font font = new Font(fontName, emSize);
Brush brush = new SolidBrush(color);
g.DrawString(text, font, brush, x, y);
可以提前测量文本的大小:
SizeF size = g.MeasureString(text, font);
图像(Image)
g.DrawImage(image, x, y, width, height);
变换矩阵
可以设置绘制时的变换矩阵。
添加平移(在当前变换矩阵的基础上):
g.TranslateTransform(x, y);
添加旋转(在当前变换矩阵的基础上):
g.RotateTransform(angle);
重置变换矩阵:
g.ResetTransform();
离屏渲染
可以创建使用 Image 作为画布的 Graphics,进行离屏渲染。
最后用控件的 Graphics 来将 Image 画到控件上。
Graphics g = Graphics.FromImage(image);
抗锯齿
可以设置 Graphics 绘制时的渲染质量。
g.SmoothingMode = SmoothingMode.AntiAlias;
默认值为 Default,有以下设置:
- 无抗锯齿:Default / HighSpeed / None
- 有抗锯齿:HighQuality / AntiAlias
评论已关闭