Reputation:
I am trying to simple thing. But i couldn' t :(
I have an TImage, which name is overview. I want to draw a rectangle which is on the overview but independent from overview. So i added a TImage front of the overview and drawed a rectangle. Rectangle works but i just can see the TImage or overview. I tried to giving a transparency to rectImg but rectImg completely disappear.
with rectImg.Canvas do
begin
Pen.Color:= clRed;
Rectangle(0, 0, rectImg.Width, rectImg.Height);
end;
I draw on a paint, what i want to make.
That rect can be resizable indepented from img.
Thanks in advice.
Upvotes: 2
Views: 1293
Reputation: 4808
If I understand your question correctly, you effectively want to visually frame the image without drawing the frame on the original graphic itself, i.e. rectImg.Picture
should not return a framed graphic. Two ways immediately come to mind:
a) Dump TImage
and use TPaintBox
, manually maintaining the core graphic and doing any stretching or whatever via method calls rather than property settings on the component.
b) Extend TImage
to have an OnPaint
event that gets raised after TImage
has done its standard painting.
With respect to (b), you can do it either as an interposer class or a custom component. As an interposer class you could do this:
1) Re-declare TImage
immediately above your form class:
type
TPaintEvent = procedure (Sender: TObject; Canvas: TCanvas) of object;
TImage = class(Vcl.ExtCtrls.TImage) //use class(ExtCtrls.TImage) if pre-XE2
strict private
FOnPaint: TPaintEvent;
protected
procedure Paint; override;
published
property OnPaint: TPaintEvent read FOnPaint write FOnPaint;
end;
TMyForm = class(TForm)
//...
2) Implement the Paint
override as so (slightly fiddly as TImage
redefines the Canvas
property of the base class):
type
TGraphicControlAccess = class(TGraphicControl);
procedure TImage.Paint;
begin
inherited;
if Assigned(FOnPaint) then
FOnPaint(Self, TGraphicControlAccess(Self).Canvas);
end;
3) Declare a suitable event handler in the form class:
procedure rectImgPaint(Sender: TObject; Canvas: TCanvas);
4) Implement the handler like so - note you need to set Brush.Style
to bsClear
to not create a filled rectangle:
procedure TMyForm.rectImgPaint(Sender: TObject; Canvas: TCanvas);
begin
Canvas.Brush.Style := bsClear;
Canvas.Pen.Color := clRed;
Canvas.Rectangle(0, 0, rectImg.Width, rectImg.Height);
end;
5) Assign the event handler in the form's OnCreate
event:
procedure TMyForm.ImagePaint.FormCreate(Sender: TObject);
begin
rectImg.OnPaint := rectImgPaint;
end;
I leave converting the interposer class to a custom component as an exercise for the reader...
Postscript
Two other thoughts now I think of them:
TImage
provides a OnPaint
event as standard.TImage
with a TShape
, setting the shape's Brush.Style
property to bsClear
as we did in the coding solution. In that situation, set the shape's Enabled
property to False
if you have any OnClick
or OnMouseXXX
handlers assigned to the image.Upvotes: 2