Advertisement

Delphi : TCanvas Component

Started by September 09, 2002 04:52 PM
2 comments, last by sanguineraven 22 years, 3 months ago
After hours of help files, and trying to solve my problem I am resorting to asking for help here. Basically, I feel I have an ok grasp of the delphi environment so I downloaded the source codefor some games (Tetris, Breakout, Pacman) and they all involve basic shapes such as rectangles drawn and moved around on the TCanvas object. I have searched and searched, read all sorts of tutorials but cannot find how to create and use and instance of TCanvas. After searching many help files I am stuck as to how I will progress. If anyone can help, it is greatly appreciated. What about me? What about Raven?
The (rather unwanted) answer is that "usually, you don''t create TCanvas objects." Oops!

TCanvas provides a (*very*) nice wrapper around ''Device Contexts'' from the Windows GDI. This lets you do drawing very easily. You can create them (I''ll explain how in a little while) but first you have to know about some other things...

First of all, many objects contain a TCanvas as a property (called "Canvas"). For example, your form has a Canvas property, which you can then use to draw your lovely stuff. If you want double buffering for it then you can set the canvas'' DoubleBuffered property to true, which will reduce flickering during the OnPaint method.

However, the Canvas isn''t limited to just your forms. For example, you can dump down a TPaintBox object (from the System tab, IIRC). This contains a canvas for you and clips out any objects outside. In effect, it''s an easy way to get a canvas - dump down a TPaintBox, write code for the OnPaint handler, and you''re flying!

PaintBox1.Canvas.TextOut(0, 0, ''Some text''); 


...bung that in your Paintbox''s OnPaint and you''ll see what I mean.

There''s a better way to do this, though - you can create TBitmaps and use their associated Canvas property. You do all your drawing onto the bitmap and copy the results to the screen using another canvas''s Draw method (meaning you''re doing double-buffering, which is a very good idea...):


  procedure DisplayYourBmp(const Filename: String; x,y: Integer);var  Bmp: TBitmap;begin  if not FileExists(Filename) then Exit;  Bmp := TBitmap.Create;  try    Bmp.LoadFromFile(Filename);    // draw onto the bitmap''s canvas here     Bmp.Canvas.Textout(20, 30, ''Some text'');    Paintbox1.Canvas.Draw(x,y, Bmp); // draw the bmp onto some canvas  finally    Bmp.Free;  end;end;// write a handler for your paintbox, for example...procedure TForm1.Paintbox1Paint(Sender: TObject);begin  DisplayYourBmp(''somefile.bmp'', 10, 20); // draw stuffend;  


(Normally you''d create the bitmap once when your program starts and free it at the end, perhaps using FormCreate and FormDestroy. This would be more efficient.)

Note that the bitmap has a canvas for you to play around - as can be seen with the "Bmp.Canvas.Textout(...)" line.

This means that whenever you want a TCanvas, you usually *use one that''s sitting as a property elsewhere*. For example, your form, a paintbox, a TImage component, a TBitmap...

If you *really* want to create a TCanvas then you have to be aware of a wrinkle - it needs to be associated with a handle. Each object in Windows (hiding away at a level below the VCL) has a "handle", which is a way to identify the object. You pass this into most Windows API functions so that it knows what object to change.

Now, you can use GetDC() and ReleaseDC() to get and release device contexts for a window, which lets you draw onto them. This is what TCanvas wraps up nicely.

After all that, here''s some code:


  procedure Funky;var  Canv: TCanvas;begin  Canv := TCanvas.Create;  try    Canv.Handle := GetDC(0); // associate with the desktop handle(!)    try      Canv.TextOut(20, 40, ''SomeText''); // look closely at your screen ;)    finally      ReleaseDC(0, Canv.Handle);    end;  finally    Canv.Free;  end;end;  


That example is actually slightly perverse - you''re drawing *to the screen(!)* rather than your app. It depends entirely on the handle you pass in to GetDC. Most of your components have a "Handle" property, so you could, for example, say "Canv.Handle := GetDC(Button1.Handle);"

In most cases, though, it''s pointless - a canvas is already exposes, so you could just use that instead.

Also, note that you have to assign the handle for the canvas before using it, because if you don''t then it doesn''t know where to draw! This will result in an exception being thrown when you first use it.
Advertisement
Hi

A Delphi form (TForm component) has a canvas property which is an instance of TCanvas, you can use directly, no need to create a new instance, eg

form1.Canvas.LineTo(x,y)

Here''s an example of how to draw a bitmap to the canvas, from the Delphi Help files:


  procedure TForm1.Button1Click(Sender: TObject);var  Bitmap : TBitMap;begin  Bitmap := TBitmap.Create;  try    with Bitmap do begin      LoadFromFile(''C:\Program Files\Common Files\Borland Shared\Images\Splash\256color\factory.bmp'');      Transparent := True;      TransParentColor := BitMap.canvas.pixels[50,50];      Form1.Canvas.Draw(0,0,BitMap);      TransparentMode := tmAuto;      Form1.Canvas.Draw(50,50,BitMap);    end;  finally    Bitmap.Free;  end;end;  


Hope this answers your question

______________________________

Don''t ask me, I''m just the code monkey
______________________________DGDev - The Delphi Games Development Community
Yeah, thx to both of you, it''s enough to build on.

What about me? What about Raven?

This topic is closed to new replies.

Advertisement