Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

How to draw in layers with Delphi?

1,238 views
Skip to first unread message

Peter Hidas

unread,
Aug 23, 2004, 7:58:58 PM8/23/04
to
Hi

I am working on a traffic simulation package. I want to draw the road
network on the background layer and the (moving) vehicles on the foreground
layer. This would mean that when I move a vehicle (ie. delete it from its
previous location then draw it at the new location) this would not delete
parts of the network on the background.

I thought I can do this by placing 2 TImage objects on top of each other,
draw the network on the first one, and the vehicles on the second one, by
setting Image2.Transparent := True, but it does not work, ie. Image2 does
not become transparent. Then I read in the Delphi Help that "Transparent has
no effect unless the Picture property specifies a TBitmap object." So this
is not the right way.

Is there any other way?

Thanks for any suggestions.

Peter


Nils Haeck

unread,
Aug 23, 2004, 8:28:28 PM8/23/04
to
Hi Peter,

Take a look at DtpDocuments, it will make your life easy for this
application!

What you can do with it:
- Add shapes (e.g. bitmap images of the vehicles) at any position on the
page.
- Rotate them freely (So you can give your vehicles the right heading)
- Move to front/back (vehicles passing under bridges)
- Move shapes simply by setting the position to a new value, no need to care
about how to redraw the background, this is all done automatically
- Assign background bitmap, or add static bitmap shapes
- You can also easily add lines, rectangles, ellipses, etcetera
- Apply effects to your shapes, like shadow
- Semi-transparency
- User-selectable, move shapes around with mouse
- Full persistance (save all shapes with one command)
- Printing, export to raster image

DtpDocuments is based on the very optimized Graphics32 library for fast
rendering of RGBA bitmaps (RGB + alpha channel for transparency).

Just check out this webpage:
http://www.simdesign.nl/dtpdocuments.html

And test the fully functional trial version...

Kind regards,

Nils Haeck
www.simdesign.nl

"Peter Hidas" <phi...@tpg.com.au> wrote in message
news:412a84c4$1...@newsgroups.borland.com...

Peter Hidas

unread,
Aug 24, 2004, 1:13:55 AM8/24/04
to
Hi Nils,

thanks, I will check it out, but first I would like to know if it can be
done by using the native Delphi components, without any extras.

Regards
Peter


"Nils Haeck" <n.ha...@spamchello.nl> wrote in message
news:412a8904$1...@newsgroups.borland.com...

Kiss Miklós

unread,
Aug 24, 2004, 2:32:05 AM8/24/04
to
> thanks, I will check it out, but first I would like to know if it can be
> done by using the native Delphi components, without any extras.

I have two ideas. If You don't have that much objects to draw You can do the
following. Draw Your background image on a temporary bitmap (double
buffering) then draw all Your vechicles to their new position. When drawing
is complete, copy this temporary bitmap to the visible TImage. My second
advice (if You have to draw many objects and not all of them is moving
always) would be to remember the covered area for each object and when it
needs to be moved You simply redraw the covered part, copy the newly covered
part and draw the object to it's new place. You could create a class for
your objects to achive this easily. However, I would not use this because I
think this solution costs many resources and is not so effective.

HTH,
MikKi


RandomAccess

unread,
Aug 24, 2004, 2:39:50 AM8/24/04
to
"Peter Hidas" <phi...@tpg.com.au> wrote in message
news:412a84c4$1...@newsgroups.borland.com...

Then I read in the Delphi Help that "Transparent has


> no effect unless the Picture property specifies a TBitmap object." So this
> is not the right way.
>


hi Peter,

All you need to do is make small bitmaps of your cars and put each in a
timage component. In fact you only need 1 bitmap.

TImage.Loadfromfile(mycar.bmp);

Do this for as many cars as you need.
In order to set transparent to true, make sure the background around the
cars is a solid color that is not used anywhere in the image of the car.


NOTE: Although this should work, I personally don't recommend this approach
to the problem. But on the other hand, it is much easier this way.


Best Regards


Peter Hidas

unread,
Aug 24, 2004, 3:36:36 AM8/24/04
to
Thanks for the suggestions, but it is not that simple...
I may have several thousand cars present at any one time, the cars have
different shapes (passenger car, truck, bus, each may have different
length), and they move in random directions, so they are not simple
rectangles with horizontal/vertical sides.

Therefore I don't use bitmaps, but draw them on the Canvas directly using
filled polygons (after calculating the coordinates of each point). To move
them to a new position, I delete each vehicle from its current position (by
redrawing them with the background color), then draw them at the new
position. This happens at one second intervals during the simulation. This
works well, except that the process deletes some parts of the road network
elements (detectors, stopline, etc...). This is why I wanted to draw them on
separate canvases.

Can anyone answer precisely the following questions:

is it possible in Delphi to have two graphical objects overlaid with the top
one being transparent (so that only what is drawn on the top is covering
what is drawn on the second)?
if yes, what objects should I use, and how to make it transparent?

Thanks
Peter

"RandomAccess" <Ran...@Access.com> wrote in message
news:412ae2b6$1...@newsgroups.borland.com...

David J Taylor

unread,
Aug 24, 2004, 4:12:10 AM8/24/04
to
Peter Hidas wrote:
[]

> Can anyone answer precisely the following questions:
>
> is it possible in Delphi to have two graphical objects overlaid with
> the top one being transparent (so that only what is drawn on the top
> is covering what is drawn on the second)?
> if yes, what objects should I use, and how to make it transparent?
>
> Thanks
> Peter

Peter,

What I have done in my own WXtrack software:

http://www.david-taylor.myby.co.uk/software/wxtrack_at_work.htm

is:

- a base map of the world as a TImage

- the grid overlaid as a TPaintBox

- the satellite paths overlaid as a TPaintBox

- the Sun, Moon and other sprites drawn using TIcon objects

- (in the current version, satellites are also drawn as icons).

So your cars, trucks etc. can be drawn as Icons, provided they are 32 x 32
pixels or less. It may work with larger icons but I haven't checked this.
You can download the software for free if you just want to see what the
screen looks like.

Cheers,
David


Kiss Miklós

unread,
Aug 24, 2004, 5:12:16 AM8/24/04
to
> Can anyone answer precisely the following questions:
>
> is it possible in Delphi to have two graphical objects overlaid with the
top
> one being transparent (so that only what is drawn on the top is covering
> what is drawn on the second)?
> if yes, what objects should I use, and how to make it transparent?

I can still recommend my first suggestion. I think that approach is fast
enough to draw thousands of objects in one second if it is done the way it
should be. So You'll need two more bitmaps which represent the whole map.
One of them stores the unmodified backround image (roads, lamps, etc. -
let's call it BackImg), the other one is used for preparing the image to be
shown (let's call it HelpImg). And You have a third bitmap which is the
TImage.Picture.Bitmap (or anything You use for showing the image).
At the beginning You load the background image (BackImg.LoadFromFile()), and
leave it unmodified for the whole process. In the drawing process first copy
the background image to the invisible bitmap (with HelpImg.Canvas.Draw),
then you draw all Your vechicles on the Canvas (using Polygon or anything).
When finished, copy the ready image to the TImage.Picture (using
Image1.Canvas.Draw) method.
By using this helper bitmap You can avoid flickering during the draw.

HTH,
MikKi


Anders Isaksson

unread,
Aug 24, 2004, 3:50:47 PM8/24/04
to
Peter Hidas wrote:
> is it possible in Delphi to have two graphical objects overlaid with
> the top one being transparent (so that only what is drawn on the top
> is covering what is drawn on the second)?
> if yes, what objects should I use, and how to make it transparent?

Keep your base picture (without any cars) in a bitmap of it's own - bmA.
When drawing, first draw this bitmap on another bitmap - bmB, then draw all
the cars on bmB, then finally draw bmB on a Paintbox.

No need to erase anything.

--
Anders Isaksson, Sweden
BlockCAD: http://w1.161.telia.com/~u16122508/proglego.htm
Gallery: http://w1.161.telia.com/~u16122508/gallery/index.htm


Peter Hidas

unread,
Aug 24, 2004, 6:44:39 PM8/24/04
to
Thanks for all the suggestions. I have never used bitmaps before, but it
seems I'll have to learn using them. Will try and get back if I can't make
it work.

Thanks for all the help.

Peter

"Anders Isaksson" <isaksso...@REMOVEebox.tninet.se> wrote in message
news:412ba35b$1...@newsgroups.borland.com...

Bryan Valencia

unread,
Aug 26, 2004, 4:19:21 PM8/26/04
to
Ok, here's what I did.
I created a form, and put down a 500x500 tImage for the background (made the
background as a bmp).
Then I put another tImage on top of it. It was the same size, and I loaded
a 500x500 solid color (magenta) bmp into that and set "transparent' to true.

Next I put on a tTimer, and this is the code I wrote in the handler.

procedure TForm1.Timer1Timer(Sender: TObject);
var
r:trect;
begin
with Image2.Picture.Bitmap.Canvas do
begin
FillRect(rect(0,0,500,500)); //erases the overlay
r.Top:=trunc(random*400); //creates a rectangle
r.Left:=trunc(random*400);
r.Right:=r.Left+50;
r.Bottom:=r.Top+50;
pen.Width:=5; //pen width
Ellipse(r); //draw the circle.
end;
end;

This draws random circles over the background. I think you can take it from
here.

If you like I can send you the source project.

"Peter Hidas" <phi...@tpg.com.au> wrote in message

news:412bc4dc$1...@newsgroups.borland.com...

Kiss Miklós

unread,
Aug 26, 2004, 7:09:02 PM8/26/04
to
> Ok, here's what I did.
> I created a form, and put down a 500x500 tImage for the background (made
the
> background as a bmp).
> Then I put another tImage on top of it. It was the same size, and I
loaded
> a 500x500 solid color (magenta) bmp into that and set "transparent' to
true.

It has no point to load a bitmap if Your first action is to fill the whole
image with a solid color:

> with Image2.Picture.Bitmap.Canvas do
> begin
> FillRect(rect(0,0,500,500)); //erases the overlay

(...)

The second thing is that You didn't specify the colors to be used. In this
case it is black for the pen and white for the brush. Setting the
TImage.Transparent property to true causes the pixels which have the same
color as the lower left pixel of the image to become transparent. So this
process is very slow because the whole image has to be "checked" from pixel
to pixel (actually this is done with masking).
I would do the following:
Create one TImage, and initialize it's bitmap in the form's OnCreate event
handler, and create two more bitmaps:

type
Form1=class(TForm)
{...}
private
Back,Buffer:TBitmap;
end;

procedure TForm1.OnCreate(Sender: TObject);
begin
//initialize TImage
Image1.Picture.Bitmap:=TBitmap.Create;
Image1.Picture.Bitmap.Width:=300;
Image1.Picture.Bitmap.Height:=300;
//load background image
Back:=TBitmap.Create;
Back.LoadFromFile('background.bmp');
//initialize helper bitmap
Buffer:=TBitmap.Create;
Buffer.Width:=300;
Buffer.Height:=300;
//set colors here once if they are used always (much faster then setting
them all the time)
Buffer.Pen.Color:=clRed;
Buffer.Brush.Color:=clMaroon;
end;

Then in a timer's OnTimer event I would do the actual drawing:

procedure TForm1.Timer1Timer(Sender: TObject);
var
x,y:integer;
begin
//use Buffer to prepare the image to be shown (to avoid flickering)
with Buffer.Canvas do begin
Draw(0,0,Back); //redraw background
//place objects
x:=random(300);
y:=random(300);
Ellipse(x-30,y-30,x+30,y+30);
end;
//show created image
Image1.Picture.Bitmap.Canvas.Draw(0,0,Buffer);
end;

And finally free the allocated memory:

procedure TForm1.OnDestroy(Sender: TObject);
begin
Back.Free;
Buffer.Free;
end;

This code is just a bit more complex then then Bryan's but it is much
faster. Hope this makes my idea clear and You can do what You really want.

Regards,
MikKi


Gordon Whittam

unread,
Aug 26, 2004, 8:41:56 PM8/26/04
to
In article <412af006$1...@newsgroups.borland.com>, Peter Hidas wrote:
> is it possible in Delphi to have two graphical objects overlaid with the top
> one being transparent (so that only what is drawn on the top is covering
> what is drawn on the second)?

Yes.

> if yes, what objects should I use,

TGraphicControl (which TImage is derived from)

>and how to make it transparent?

It just is, its what you draw you draw on it's canvas that determines whether
or not you can see through it.

Have a look at the source for TShape. You can see it in action if you just put
2 TShapes on a form, one set to stCircle and one to stRectangle, put one over
the other, play around with BringToFront.

Gordon
--
MGCSoft Graphical and equation editors
http://www.mgcsoft.com/

geeds

unread,
Aug 27, 2004, 8:35:42 AM8/27/04
to
Peter

I guess I am missing something, is the Sprites_Ex example not exactly
what your talking about?

Geeds

Bryan Valencia

unread,
Aug 27, 2004, 7:51:42 PM8/27/04
to
What, do you think I typed that all in without testing it? Of course it
worked! I guarantee it.


Kiss Miklós

unread,
Aug 28, 2004, 11:29:30 AM8/28/04
to
> What, do you think I typed that all in without testing it? Of course it
> worked! I guarantee it.

Sorry if You have misunderstood me. I didn't tell that Your code doesn't
work. I just told that You relied on default settings which is not always
the best choice. I have tested Your code too and it worked just great! And I
wanted to show another solution which I think is somewhat faster.

MikKi


Bryan Valencia

unread,
Aug 31, 2004, 4:39:44 PM8/31/04
to
Oh, yeah. I knew that... It was just a quickie demo, not an exhaustive
tutorial...


"Kiss Miklós" <kissm...@freemail.hu> wrote in message
news:4130a4ad$1...@newsgroups.borland.com...

0 new messages