Mega Code Archive

 
Categories / Delphi / Graphic
 

Painting on VCL components without canvas

Title: Painting on VCL components without canvas Question: How to paint or write on a visual component which has no canvas Answer: I sometimes need to draw on a panel or a button. If you need it also here is a simple way: Those visual components without canvas property must have a window handle and a device context. By using GetDC (references to exported procedure of USER32.DLL in windows unit) you can get a handle for its device context. Now all you have to do is simply using this handle in painting, drawing or textout calls. The following is a simple example: . . . procedure TForm1.Button2Click(Sender: TObject); begin DrawOnComponent(Panel1, 'Hi there'#13#10'And this is the second line'); end; procedure TForm1.DrawOnComponent(AComponent: TPanel; AText: string); var dc : hdc; APen : hpen; ABrush : hbrush; ARect : TRect; begin dc := getdc(AComponent.handle); //get device context of component ARect := AComponent.ClientRect; //select rectangle to draw on ARect.left := ARect.Left + 10; ARect.top := ARect.Top + 10; ARect.Right:= ARect.Right -10; ARect.Bottom := ARect.Bottom - 10; apen := createpen(PS_SOLID, 3, clRed); //create graphic object to be used abrush := createsolidbrush(clWhite); try SelectObject(dc, ABrush); //fill background fillrect(dc, AComponent.ClientRect, abrush); SelectObject(dc, APen); //draw a rectangle MoveToEx(dc, ARect.left, ARect.Top-5, nil); LineTo(dc, ARect.right, ARect.Top-5); LineTo(dc, ARect.right, ARect.Bottom); LineTo(dc, ARect.left, ARect.Bottom); LineTo(dc, ARect.left, ARect.Top-5); //Rectangle(dc, 0, 0, AComponent.Width-1, AComponent.Height-1); //An existing object can be used for drawing SelectObject(dc, AComponent.font.handle); DrawText( dc, PChar(AText), length(AText), ARect, DT_CENTER or DT_END_ELLIPSIS or DT_VCENTER); finally //free the graphic objects created in this proc. before leaving DeleteObject(APen); DeleteObject(ABrush); end; end; ANOTHER METHOD: 1- Create your (for example) TYourPanel inheriting from TPanel. 2- Add property Canvas to published properties. 3- Override create and destroy methods of TPanel to create an instance of TCanvas for your component and to destroy it. 4- Do not to register your component if you wanto to see it on object panel. 5- The code follows: unit YourPanelUnit; interface uses ExtCtrls, Graphics, Windows, Classes; type TYourPanel = class(TPanel) private FCanvas: TCanvas; procedure SetCanvas(const Value: TCanvas); protected public constructor Create(AOwner: TComponent); override; destructor Destroy;override; published property Canvas : TCanvas read FCanvas write SetCanvas; end; procedure Register; implementation procedure Register; begin RegisterComponents('Custom', [TYourPanel]); end; { TYourPanel } constructor TYourPanel.Create(AOwner: TComponent); begin inherited Create(AOwner); FCanvas := TCanvas.Create; end; destructor TYourPanel.Destroy; begin FCanvas.Free; inherited; end; procedure TYourPanel.SetCanvas(const Value: TCanvas); begin FCanvas := Value; end; end.