Solved

TPanel.Canvas?

Posted on 2002-03-10
10
3,184 Views
Last Modified: 2012-08-14
I know how to draw on the canvas of a form but is it possible to do the same with a Panel (or Tabsheet)?

if so, give a short example please.
0
Comment
Question by:d32coder
  • 6
  • 3
10 Comments
 

Expert Comment

by:Kelmi
ID: 6854582
You can make and a new panel component which has an OnPaint event and Canvas property. Here is an example:

unit paintpanel;

interface

uses
  ExtCtrls, Classes;

type
  TPaintPanel = class(TPanel)
  private
    FOnPaint: TNotifyEvent;  
  protected
    procedure Paint; override;
  public
    property Canvas;
  published
    property OnPaint: TNotifyEvent read FOnPaint write FOnPaint;
  end;

  procedure Register;

implementation

{ Register component }

procedure Register;
begin
  RegisterComponents('Samples', [TPaintPanel]);
end;

{ TPaintPanel }

procedure TPaintPanel.Paint;
begin
  inherited Paint;
  if Assigned(FOnPaint) then FOnPaint(Self);
end;

end.
0
 
LVL 9

Expert Comment

by:ginsonic
ID: 6854649
listening
0
 

Expert Comment

by:Kelmi
ID: 6854717
I mean: "You can make and INSTALL a new..."


0
What is SQL Server and how does it work?

The purpose of this paper is to provide you background on SQL Server. It’s your self-study guide for learning fundamentals. It includes both the history of SQL and its technical basics. Concepts and definitions will form the solid foundation of your future DBA expertise.

 
LVL 8

Expert Comment

by:TOndrej
ID: 6854811
All TControl descendants have Canvas property which is protected by default, although in some cases the descendant classes do promote its visibility to public.

To access a protected property of a class, you can use an old trick:

type
  THackPanel = class(TPanel);

with THackPanel(Panel1).Canvas do
  ...

in this example, Panel1 is a 'normal' TPanel. The typecast allows you to access its protected properties.

HTH
TOndrej
0
 

Expert Comment

by:Kelmi
ID: 6854842
Useful tip, TOndrej! But if you want to paint on panel's canvas, you should also override its Paint procedure, or...?
0
 

Expert Comment

by:Kelmi
ID: 6854846
Useful tip, TOndrej! But if you want to paint on panel's canvas, you should also override its Paint procedure, or...?
0
 
LVL 8

Accepted Solution

by:
TOndrej earned 50 total points
ID: 6854995
> if you want to paint on panel's canvas, you should also
> override its Paint procedure, or...?

No, strictly speaking, to paint on a canvas you don't need anything else than to use TCanvas methods, or Windows GDI APIs with the DC handle.

A different problem is if you want to do your painting every time the panel repaints itself (ie. you don't want your painting to disappear the next time the control gets invalidated and repaints itself). In that case you need to make sure that your painting is done again _every time_ the control (re)paints itself.

In a TForm descendant, you can simply use the form's OnPaint event which is called for you automatically every time the form is painted.
For controls like TPanel which don't have an OnPaint event, you have two options:

1. Create a descendant and override its Paint method, as you have shown.
This one is useful when the descendant is going to be reused in other projects.

2. Subclass the panel to intercept WM_PAINT messages, for example:

type
  TFormTest = class(TForm)
    Panel1: TPanel;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    FPanelWndProc: TWndMethod;

    procedure PanelWndProc(var Message: TMessage);
  public
  end;


procedure TFormTest.FormCreate(Sender: TObject);

begin
  // remember the panel's original window procedure
  FPanelWndProc := Panel1.WindowProc;
  // subclass the panel
  Panel1.WindowProc := PanelWndProc;
end;

procedure TFormTest.FormDestroy(Sender: TObject);
begin
  // restore the panel's original window procedure
  Panel1.WindowProc := FPanelWndProc;
  FPanelWndProc := nil;
end;

type
  THackPanel = class(TPanel);

procedure TFormTest.PanelWndProc(var Message: TMessage);
const
  GridSize = 8;
var
  X, Y: Integer;
begin
  // call the panel's original window procedure
  FPanelWndProc(Message);
  // do your own painting
  // this example draws a grid on the panel
  if Message.Msg = WM_PAINT then
    with THackPanel(Panel1) do
    begin
      X := 0;
      while X <= ClientWidth do
      begin
        Y := 0;
        while Y <= ClientHeight do
        begin
          Canvas.Pixels[X, Y] := clNavy;

          Inc(Y, GridSize);
        end;

        Inc(X, GridSize);
      end;
    end;
end;

This can come handy when you don't want to create a new descendant for just one very specific case; you want to create the control and set its properties at designtime but not register it into the component palette (because it's very special and will not be used in other projects).

HTH
TOndrej
0
 

Expert Comment

by:Kelmi
ID: 6855077
I can see your point.

Do you know why protected properties become accessible when you define a new type like:

type
 THackPanel = class(TPanel);

If you want those protected properties to stay protected (I mean not accessible), is the only way to redeclare them as protected?
0
 
LVL 8

Expert Comment

by:TOndrej
ID: 6855106
> Do you know why protected properties become accessible
> when you define a new type like:

> type
> THackPanel = class(TPanel);

The statement above declares a new descendant class.

By definition, a protected property is visible to the class in which it is declared and to all descendant classes; plus also to any code within the same unit after the declaration.

> If you want those protected properties to stay protected
> (I mean not accessible), is the only way to redeclare
> them as protected?

No need to do anything, see above.
In the example above, we have not changed visibility of any properties.
Our trick was to typecast Panel (an instance of TPanel) to THackPanel which is technically incorrect (Panel1 is _not_ THackPanel) but safe (because THackPanel does not introduce any changes) which allowed us to access the protected Canvas.
0
 

Expert Comment

by:Kelmi
ID: 6855128
Thanks for the information. That trick is pretty useful.
0

Featured Post

NAS Cloud Backup Strategies

This article explains backup scenarios when using network storage. We review the so-called “3-2-1 strategy” and summarize the methods you can use to send NAS data to the cloud

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Objective: - This article will help user in how to convert their numeric value become words. How to use 1. You can copy this code in your Unit as function 2. than you can perform your function by type this code The Code   (CODE) The Im…
In my programming career I have only very rarely run into situations where operator overloading would be of any use in my work.  Normally those situations involved math with either overly large numbers (hundreds of thousands of digits or accuracy re…
In a recent question (https://www.experts-exchange.com/questions/28997919/Pagination-in-Adobe-Acrobat.html) here at Experts Exchange, a member asked how to add page numbers to a PDF file using Adobe Acrobat XI Pro. This short video Micro Tutorial sh…
This video shows how to quickly and easily add an email signature for all users on Exchange 2016. The resulting signature is applied on a server level by Exchange Online. The email signature template has been downloaded from: www.mail-signatures…

773 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question