GDI+ 绘制经验

  现有一种场景,鼠标移动时,假设鼠标坐标为 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);
}
原文地址:https://www.cnblogs.com/a_bu/p/5563924.html