c ++在背景图像上高效绘制线条

时间:2016-11-06 16:48:19

标签: c++ canvas vcl

TBitmap* prevImg对象需要一些时间才能生成,因此我生成一次,并希望将其设置为背景

Image1->Picture->Assign(prevImg); //TImage* Image1

现在我想在mousemove上绘制一些线条和数字:

void __fastcall TTriggerSystemForm::Image1MouseMove(TObject *Sender, TShiftState Shift, int X, int Y){
  if(!prevImg)return;
  Image1->Picture->Assign(prevImg); //reset image

  Image1->Canvas->Pen->Color=clRed; //draw a vertical dotted red line
  Image1->Canvas->Pen->Style=psDot;
  Image1->Canvas->MoveTo(X,0);
  Image1->Canvas->LineTo(X,Image1->Picture->Height);
}

现在这已经很好了。但是,由于图像有时会闪烁而且任务的CPU因为这个鼠标移动事件而上升到8%,这可能不是很有效。

我正在使用带有VCL的C ++ Builder XE2。

有没有更好的方法在给定的TImage对象上动态绘制内容而不更改原始图像源?

2 个答案:

答案 0 :(得分:0)

了解双缓冲,诀窍在于您使用不同的缓冲区,一旦您的工作完成,您就可以切换缓冲区。这样可以防止“闪烁”。

要降低CPU使用率,您可以最小化已处理鼠标事件的数量,例如,如果上次处理的事件的时间低于100-200ms,则跳过事件处理

答案 1 :(得分:0)

您可以简单地绘制实际更改的图像部分,而不是绘制整个图像,例如:

int oldX = -1;

void __fastcall TTriggerSystemForm::Image1MouseMove(TObject *Sender, TShiftState Shift, int X, int Y)
{
    if (!prevImg) return;

    if (!Image1->Picture->Graphic)
        Image1->Picture->Assign(prevImg); //reset image

    if (oldX == X) return;

    if (oldX != -1)
    {
        TRect r = Rect(oldX, 0, oldX + Image1->Canvas->Pen->Width, Image1->Height);
        Image1->Canvas->CopyRect(r, prevImg->Canvas, r);
    }

    Image1->Canvas->Pen->Color = clRed; //draw a vertical dotted red line
    Image1->Canvas->Pen->Style = psDot;
    Image1->Canvas->MoveTo(X, 0);
    Image1->Canvas->LineTo(X, Image1->Height);

    oldX = X;
}

话虽如此,我建议使用TPaintBox代替TImage,例如:

int MouseX = -1;

void __fastcall TTriggerSystemForm::PaintBox1MouseMove(TObject *Sender, TShiftState Shift, int X, int Y)
{
    MouseX = X;
    PaintBox1->Invalidate();
}

void __fastcall TTriggerSystemForm::PaintBox1MouseMove(TObject *Sender)
{
    if (!prevImg) return;
    PaintBox1->Canvas->Draw(0, 0, prevImg); //reset image

    if (MouseX != -1)
    {
        PaintBox1->Canvas->Pen->Color = clRed; //draw a vertical dotted red line
        PaintBox1->Canvas->Pen->Style = psDot;
        PaintBox1->Canvas->MoveTo(MouseX, 0);
        PaintBox1->Canvas->LineTo(MouseX, PaintBox1->Height);
    }
}