Delphi : TCanvas Component
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!
...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...):
(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:
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.
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.
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:
Hope this answers your question
______________________________
Don''t ask me, I''m just the code monkey
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
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement
Recommended Tutorials
Advertisement