Link to home
Start Free TrialLog in
Avatar of DMTrump
DMTrumpFlag for United States of America

asked on

How can I prevent TPaintbox graphics from being erased when obscured?

I have a situation where I have a TImage on a work surface.  The Timage may be moverd around on the work surface.  Over the whole work surface is a TPaintBox upon which the user can draw - both over and around the Timage.

It works well, except that if during the work the user passes another window over top, or drags the work surface partly off screen, the portion of the drawing on the TPaintBox that has been obscured is erased.

I know that I could save the contents of the TPaintBox to a Bitmap and restore it, but unless I do that constantly, how can I make sure that it is saved when needed?  

Is there a way to prevent the repaint that is erasing the TPaintBox?
Avatar of Hypo
Hypo
Flag of Sweden image

I don't think that it is the repaint that is erasing the data, it is the actual window that moves over the PaintBox that erases the data, the repaint just tries to restore the default TPaintBox control graphics. You can prohibit repaints fropm happening by adding your own message handler for WMPaint, that does nothing; but the effect you will get then is that the area that has been obscured will become white (undefined) like it does for an application that freezes.

My sugestion is that if you want to keep the contents of the TPaintBox whenever it has been obscured by another window, then you should redirect all the user painting to a Bitmaps canvas, which has the same size as the TPaintBox, and then just draw this Bitmap to the TPaintBox.Canvas, in the TPaintBox.OnPaint event.

procedure TForm1.PaintBox1Paint(Sender: TObject);
begin
  PaintBox1.Canvas.Draw(0, 0, myBitmap);
end;


regards
Hypo
Avatar of DMTrump

ASKER

I created a possible solution myself - but I'll leave the question open in case someone else has a better idea!

I wrote two procedures:

TraceSave is called upon the completion (mouseup, for instance) of any drawing routine.
procedure T_form.TraceSave;
var
  i, j: integer;
begin
  TraceSaved.Height := pbTrace.height;
  TraceSaved.Width := pbTrace.Width;
  BitBlt(TraceSaved.Canvas.Handle, 0, 0, pbTrace.Width, pbTrace.Height,
    pbTrace.Canvas.Handle, 0, 0, SRCCOPY);
end;

TraceBack is called from the the TPaintbox OnPaint event.
procedure T_form.TraceBack;
var
  i, j: integer;
begin
  BitBlt(pbTrace.Canvas.Handle, 0, 0, pbTrace.Width, pbTrace.Height,
    TraceSaved.Canvas.Handle, 0, 0, SRCCOPY);
end;

This seems to work fine - but is there a better way?

Avatar of DMTrump

ASKER

Hypo, Thanks for that suggestion,  I may try that.  (less code than my way, I think) It is important, however that the user be able to observe the drawing as it happens - therefore I think I would have to draw <both> to the BitMap and to the Tpaintbox.  

However, my method would - however unlikely) make it possible for a another application to "pop up" over the drawing area and obscure a drawingoperation in progress.  

If I were to simultaneously draw to both the bitmap and the painbox, that could not happen.  

BTW, in my code, the TraceSaved is a global TBitMap, created and destroyed with the application.
ASKER CERTIFIED SOLUTION
Avatar of Hypo
Hypo
Flag of Sweden image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of DMTrump

ASKER

Thanks for the help