Watch, Follow, &
Connect with Us

For forums, blogs and more please visit our
Developer Tools Community.


Welcome, Guest
Guest Settings
Help

Thread: Drawing a selection rectangle on a TImage with PNG


This question is answered.


Permlink Replies: 2 - Last Post: Dec 30, 2015 4:09 PM Last Post By: Nick Reinschmidt
Nick Reinschmidt

Posts: 8
Registered: 7/15/00
Drawing a selection rectangle on a TImage with PNG  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Dec 30, 2015 10:54 AM
My application provides the user a panel where he can create and manipulate several controls, somewhat similar to the Delphi form designer.
For the controls I used some native VCL controls and some custom controls. In any case I always created a derived class that overrides the Paint method, lets the parent do its default drawing and then draws a selection rectangle if the user has previously selected the control.

This works fine for all controls with the exception of TImage when it contains a PNG image. In that case I get
"Can only modify an image if it contains a bitmap"
when I try to use TImage.Canvas to draw the selection rectangle.
I found several suggestions on how to draw on a TPngImage but most of them don't work in my case, f.e.

1) Draw on TPngImage.Canvas:
doesn't work because the selection rectangle can not be removed anymore, also the selection rectangle would scale together with the Png image if the containing TImage is larger than the Png.

2) Convert the Png image to a bitmap and assign it to TImage.Graphic.Bitmap: I didn't try this but it would probably loose transparency information. It is essential that the user can freely move the control around, so the background may change. The TPngImage in the TImage seems to take care of this.

Any ideas how to accomplish this?
thanks,
Nicolas
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: Drawing a selection rectangle on a TImage with PNG
Correct
Click to report abuse...   Click to reply to this thread Reply
  Posted: Dec 30, 2015 11:26 AM   in response to: Nick Reinschmidt in response to: Nick Reinschmidt
Nick wrote:

This works fine for all controls with the exception of TImage
when it contains a PNG image. In that case I get

"Can only modify an image if it contains a bitmap"

when I try to use TImage.Canvas to draw the selection rectangle.

TImage hides the Canvas property it inherits from TGraphicControl and redeclares
its own Canvas property to provide access to the graphic object's own Canvas,
but only when the graphic is a TBitmap:

function TImage.GetCanvas: TCanvas;
var
  Bitmap: TBitmap;
begin
  ...
  if Picture.Graphic is TBitmap then
    Result := TBitmap(Picture.Graphic).Canvas
  else
    raise EInvalidOperation.Create(SImageCanvasNeedsBitmap); // <-- this 
is the exception you are seeing
end;


To do what you are attempting, you need to use the TGraphicControl.Canvas
property, not the TImage.Canvas property. If you look at the implementation
of TImage.Paint(), it uses "inherited Canvas" for all of its drawing. Since
you are deriving from TImage, "inherited Canvas" will refer to TImage.Canvas,
so you will have to use a type-cast to access TGraphicControl.Canvas instead:

type
  TGraphicControlAccess = class(TGraphicControl)
  end;
 
procedure TMyDerivedImage.Paint;
begin
  inherited;
  TGraphicControlAccess(Self).Canvas.DrawFocusRect(ClientRect);
end;


--
Remy Lebeau (TeamB)
Nick Reinschmidt

Posts: 8
Registered: 7/15/00
Re: Drawing a selection rectangle on a TImage with PNG  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Dec 30, 2015 4:09 PM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
Works perfectly! Thanks also for the background information. This "accessing private members" hack is really a gift in certain situations.
Legend
Helpful Answer (5 pts)
Correct Answer (10 pts)

Server Response from: ETNAJIVE02