我使用循环原语代码输出测试图像:
procedure TForm1.Button1Click(Sender: TObject);
var
LP1, LP2: TLogPen;
hp1, hp2: THandle;
hdcv: Handle;
i: integer;
begin
LP1.lopnColor:=$FF0000;
LP1.lopnStyle:=0;
LP1.lopnWidth:=Classes.Point(1,0);
LP2.lopnColor:=$FFFFFF;
LP2.lopnStyle:=0;
LP2.lopnWidth:=Classes.Point(1,0);
hp1:=Windows.CreatePenIndirect(Windows.LOGPEN(LP1));
hp2:=Windows.CreatePenIndirect(Windows.LOGPEN(LP2));
hdcv:=Canvas.Handle;
for i:=1 to 1000 do
begin
SelectObject(hdcv, hp1);
Windows.MoveToEx(hdcv, 10+2*i, 10, nil);
Windows.LineTo(hdcv, 50+2*i, 50);
Sleep(100);
Application.ProcessMessages;
SelectObject(hdcv, hp2);
Windows.MoveToEx(hdcv, 10+2*i+1, 10, nil);
Windows.LineTo(hdcv, 50+2*i+1, 50);
Sleep(100);
Application.ProcessMessages;
end;
Windows.DeleteObject(hp1);
Windows.DeleteObject(hp2);
end;
问题是当鼠标放在按钮(Button1)上时,行输出是间歇性的。就好像绘图发生在某种缓冲区中,过了一段时间它就会显示在表单上。我录了一段视频。我用的是Windows 7和Lazarus 1.6.4。有人能解释一下这种图形行为吗?
在休眠期间,窗口重绘消息不能操作。因此,重绘可能只发生在processmessages阶段。
最好的解决方案是使用计时器异步重写。
为了验证这个假设,你可以替换睡眠应用程序。处理更细粒度的解决方案,如
所以不用
sleep(100);
Application.ProcessMessages;
我们用 代替
for y:=1 to 10 do
begin
sleep(10);
Application.ProcessMessages;
end;
稍微好一点的解决方案是这样的(伪代码):
startticks:=gettickcount64; // startticks = int64
while (gettickcount64-startticks)<100 do
begin
sleep(10);
Application.ProcessMessages;
end;
可以更好地说明在Application.Processmessages中花费的时间。