我的部分应用程序是绘制图形表单草稿,主要是用户输入表单,包含许多编辑框。我绘制位图并保存为PNG,报告过程的所有部分,因此没有任何内容被绘制到应用程序表单。 我绘制所有控件,编辑框,单选按钮,复选框......
绘图的最长部分当然是绘制编辑框,因为它们数量巨大。我有一个典型的过程,在大约70K表格上绘制1M编辑框。
我画了一个非常简单的编辑框:
我附上了简单编辑控件的屏幕截图,其中包含Zoomed,因此可以看到额外的左侧和顶部线条。
以下是DrawEdit的代码,它绘制了1M Edit框,需要20秒。 无论如何都要加快这个过程吗?
procedure DrawEdit(myCanvas:TCanvas; vLeft, vTop, vWidth, vHeight: integer; const vText: string; vCenterText:boolean=false);
begin
// basic rectangle
pPoint.x := vLeft; pPoint.Y := vTop;
myCanvas.Pen.Width := 1;
myCanvas.PenPos := pPoint;
myCanvas.Pen.Color := $0099A8AC;
myCanvas.LineTo(vLeft + vWidth, vTop);
myCanvas.LineTo(vLeft + vWidth, vTop + 1);
myCanvas.Pen.Color := $00E2EFF1;
myCanvas.LineTo(vLeft + vWidth, vTop + vHeight - 1);
myCanvas.LineTo(vLeft, vTop + vHeight - 1);
myCanvas.Pen.Color := $0099A8AC;
myCanvas.LineTo(vLeft, vTop);
// again top border
pPoint.x := vLeft + 1; pPoint.Y := vTop + 1;
myCanvas.PenPos := ppoint;
myCanvas.Pen.Color := $00646F71;
myCanvas.LineTo(vLeft + vWidth, vTop + 1);
// again left border
ppoint.x := vLeft + 1; ppoint.Y := vTop + 1;
myCanvas.PenPos := ppoint;
myCanvas.Pen.Color := $00646F71;
myCanvas.LineTo(vLeft + 1, vTop + vHeight - 1);
if vText<>'' then
begin
// clear area for text - white background
myCanvas.Font.Color := clblack;
myCanvas.Brush.Color := clWhite;
rRect.Left := vLeft + 2;
rRect.Top := vTop + 2;
rRect.Right := vLeft + myCanvas.TextWidth(vText);
rRect.Bottom := vTop + myCanvas.TextHeight(vText);
myCanvas.FillRect(rRect);
If Not vCenterText Then
Winapi.Windows.TextOut(myCanvas.Handle, vLeft + 4, vTop + 2, PChar(vText), Length(vText))
else
Winapi.Windows.TextOut(myCanvas.Handle, vLeft + (vWidth div 2) - (myCanvas.TextWidth(vText) div 2), vTop + (vHeight div 2) - (myCanvas.TextHeight(vText) div 2), PChar(vText), Length(vText));
end;
end;
这是我使用的测试。测试不理想,因为真正的编辑框大小不同,但这是我测试不同的optimizatino选项的测试。
procedure TForm1.Button3Click(Sender: TObject);
var
i, t1, t2: integer;
myBitmap: TBitmap;
begin
myBitmap := TBitmap.Create;
try
myBitmap.SetSize(500, 500);
myBitmap.PixelFormat := pf24bit;
t1 := GetTickCount;
for i := 1 to 1000000 do
DrawEdit(myBitmap.Canvas, 10, 10, 100, 50, 'Edit box', true);
t2 := GetTickCount;
finally
myBitmap.Free;
end;
button3.Caption := inttostr(t2 - t1);
end;
答案 0 :(得分:5)
GDI对于绘制到设备是有效的,但是,对于内存位图工作,它会带来很大的开销。
您最好避开GDI图层并直接对内存光栅图像执行此操作。我建议使用graphics32库。切换到那应该会产生非常显着的性能提升。
您可能要做的另一件事是将工作分成多个任务并利用多线程。您想要绘制到不同的位图,然后在最后拼接在一起。
答案 1 :(得分:2)
我使用Line
在Graphics32上绘制TBitmap32,结果比在TBitmap上绘图快3倍.Canvas:
procedure DrawEdit32(BM32: TBitmap32; vLeft, vTop, vWidth, vHeight: integer; const vText: string; vCenterText: boolean = false);
begin
// basic rectangle
BM32.Line(vLeft, vTop, vWidth, vTop, $0099A8AC);
BM32.Line(vWidth, vTop, vWidth, vTop + vHeight, $00E2EFF1);
BM32.Line(vWidth, vTop + vHeight, vLeft, vTop + vHeight, $00E2EFF1);
BM32.Line(vLeft, vTop + vHeight, vLeft, vTop, $0099A8AC);
// again top border
BM32.Line(vLeft + 1, vTop + 1, vWidth, vTop + 1, $00646F71);
// again left border
BM32.Line(vLeft + 1, vTop + 1, vLeft + 1, vTop + vHeight, $00646F71);
if vText <> '' then
begin
// clear area for text - white background
BM32.Font.Color := clblack;
rRect.Left := vLeft + 2;
rRect.Top := vTop + 2;
rRect.Right := vLeft + BM32.TextWidth(vText);
rRect.Bottom := vTop + BM32.TextHeight(vText);
BM32.FillRect(rRect.Left,rRect.Top,rRect.Right,rRect.Bottom,clWhite);
if not vCenterText then
Winapi.Windows.TextOut(BM32.Handle, vLeft + 4, vTop + 2, PChar(vText), Length(vText))
else
Winapi.Windows.TextOut(BM32.Handle, vLeft + (vWidth div 2) - (BM32.TextWidth(vText) div 2), vTop + (vHeight div 2) - (BM32.TextHeight(vText) div 2), PChar(vText), Length(vText));
end;
end;