Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to draw on a TPanel

I need to draw on a TPanel, ideally directly so I don't have another component on top of it getting in the way of mousevent-event trapping (I want to draw a little "size-grip" on it). How should I go about doing this?

like image 680
Jamo Avatar asked May 01 '09 23:05

Jamo


4 Answers

To really do it right, you should probably write a descendant class. Override the Paint method to draw the sizing grip, and override the MouseDown, MouseUp, and MouseMove methods to add resizing functionality to the control.

I think that's a better solution than trying to draw onto a TPanel in your application code for a couple of reasons:

  1. The Canvas property is protected in TPanel, so you have no access to it from outside the class. You can get around that with type-casting, but that's cheating.
  2. The "resizability" sounds more like a feature of the panel than a feature of the application, so put it in code for the panel control, not in your application's main code.

Here's something to get you started:

type
  TSizablePanel = class(TPanel)
  private
    FDragOrigin: TPoint;
    FSizeRect: TRect;
  protected
    procedure Paint; override;
    procedure MouseDown(Button: TMouseButton; Shift: TShiftState;
      X, Y: Integer); override;
    procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
    procedure MouseUp(Button: TMouseButton; Shift: TShiftState;
      X, Y: Integer); override;
  end;

procedure TSizeablePanel.Paint;
begin
  inherited;
  // Draw a sizing grip on the Canvas property
  // There's a size-grip glyph in the Marlett font,
  // so try the Canvas.TextOut method in combination
  // with the Canvas.Font property.
end;

procedure TSizeablePanel.MouseDown;
begin
  if (Button = mbLeft) and (Shift = []) 
      and PtInRect(FSizeRect, Point(X, Y)) then begin
    FDragOrigin := Point(X, Y);
    // Need to capture mouse events even if the mouse
    // leaves the control. See also: ReleaseCapture.
    SetCapture(Handle);
  end else inherited;
end;
like image 135
Rob Kennedy Avatar answered Sep 27 '22 18:09

Rob Kennedy


This is one of the many many ways that Raize Components can make your life easier. I just go into Delphi, drop on a TRzPanel, and type:

RzPanel1.Canvas.Rectangle...

I'm sure there are other solutions - but I don't have to look for them with Raize.

(just a satisfied customer for about 10 years...)

EDIT: Given your goal, and your statement that you have Raize Components already, I should also point out that TRzSizePanel handles resizing of the panel and useful events like OnCanResize (to determine whether you want to allow resizing to a particular new width or height).

like image 42
Argalatyr Avatar answered Sep 27 '22 18:09

Argalatyr


The simplest way to do it is to just put a TImage on the panel. But if you really don't want to do that, type TCanvas into the code editor, hit F1, and have fun learning about how it works under the hood. (Don't say I didn't warn you...)

like image 39
Mason Wheeler Avatar answered Sep 27 '22 19:09

Mason Wheeler


How to Add Size Handles to Controls being Resized at Run-Time: http://delphi.about.com/library/weekly/aa110105a.htm

TAdvPanel: http://www.tmssoftware.com/site/advpanel.asp

like image 42
Bob S Avatar answered Sep 27 '22 19:09

Bob S