现有一种场景,鼠标移动时,假设鼠标坐标为 X , Y , 需实时在 坐标 (X , 0) , (0 , Y) 两处更新内容。
方案一:
增加两个label ,或其它控件,鼠标移动时,实时更新 label 坐标区域 , 及内容。
MouseMove 事件代码:
lblX.Location = new Point(e.X, 0); lblY.Location = new Point(0, e.Y); lblX.Text = e.X.ToString(); lblY.Text = e.Y.ToString();
经过检单测式,鼠标移动时,CPU 升到 10 % - 50% 。
方案二:
GDI Drawing 绘制相关信息.
MouseMove 事件代码 , 记录鼠标位置
//记录当前绘制坐标 curPoint = e.Location; //重绘区包括当前需绘制区域,和需擦除区域 ,使用自身合并函数 if (isFirst) { isFirst = false; } //当前绘制区 Rectangle cur = new Rectangle(0, 0, curPoint.X + 50, curPoint.Y + 25); if (isFirst) { isFirst = false; } else { //将上一次更新区域添加到更新列表 pictureBox1.Invalidate(lstRec); } //更新绘制区域 pictureBox1.Invalidate(cur); lstRec = cur;
Paint 重绘代码
e.Graphics.DrawString(curPoint.X.ToString(), font, brush, curPoint.X, 0); e.Graphics.DrawString(curPoint.Y.ToString(), font, brush, 0, curPoint.Y); Console.WriteLine("{0} , height:{1}", e.ClipRectangle.Width, e.ClipRectangle.Height);
经过简单测式,鼠标移动时,CPU 升到 10 % - 40% 。
由于重绘区域随着X, Y 值增大而增加,Invalidate方法会将重绘区域合并新矩形, 虽然更新很小部份,但重绘面积仍很大。后期,经过优化,重绘面积可不超过全屏四分之一。但CPU 占用仍然很高。
方案三:
采用 gdi32 绘制 , gdi32因绘制区域无合并,重绘机制存在,在局部更新时 默认只更新修改部份。CPU 占用2% - 5%
MouseMove 事件代码:
if (isFirst) { isFirst = false; } else { //擦除背景色 , 区域描述参数为 左,上,右,下。 GDIDrawText.FillRgn(hdc, GDIDrawText.CreateRectRgn(rectX.Left, rectX.Top, rectX.Right, rectX.Bottom), brushWin32); GDIDrawText.FillRgn(hdc, GDIDrawText.CreateRectRgn(rectY.Left, rectY.Top, rectY.Right, rectY.Bottom), brushWin32); } GDIDrawString(rectX = new Rectangle(e.X, 0, 50, 20), e.X.ToString()); GDIDrawString(rectY = new Rectangle(0, e.Y , 50, 20), e.Y.ToString());
绘制方法
private void GDIDrawString(Rectangle rec , string value) { int flags = GDIDrawText.DT_CENTER | GDIDrawText.DT_VCENTER | GDIDrawText.DT_SINGLELINE; Rect bounds = new Rect(rec); GDIDrawText.DrawText(hdc, value , value.Length, ref bounds, flags); }