home *** CD-ROM | disk | FTP | other *** search
- unit Shape;
- {*******************************************************************************
- ShapesDemo
- Written by David Clegg, davidclegg@optusnet.com.au.
-
- This unit contains the base Shape class used to render onto a GDI+ drawing
- surface.
- *******************************************************************************}
-
- interface
-
- uses
- System.Drawing, System.Drawing.Drawing2D, System.Collections;
-
- type
-
- //Forward declaration
- TShape = class;
-
- /// <summary>
- /// Strongly typed collection of TShape objects.
- /// </summary>
- TShapes = class(CollectionBase)
- private
- function GetShape(Index: integer): TShape;
- procedure SetShape(Index: integer; Value: TShape);
- public
- property Shape[Index: integer]: TShape read GetShape write SetShape; default;
- function Add(pShape: TShape): integer;
- function IndexOf(pShape: TShape): integer;
- procedure Remove(pShape: TShape);
- function Contains(pShape: TShape): boolean;
- procedure Insert(pIndex: integer; pShape: TShape);
- end;
-
- /// <summary>
- /// Base class for all shapes to descend from. It implements the logic for
- /// drawing an outline of the shape, and for filling the shape using the
- /// specified brush. It implements the IDisposable interface as the canvas
- /// reference needs to be disposed
- /// Concrete classes need only implement the GetShape method which should
- /// return a GraphicsPath instance representing the bounds of the shape.
- /// As a contrast, some concrete classes may also implement alternative
- /// methods for drawing the outline and filling the shape.
- /// </summary>
- TShape = class
- private
- FOldStartPoint: Point;
- FOldEndPoint: Point;
- FCanvas: Graphics;
- FDisposed: boolean;
- FStartPoint: Point;
- FEndPoint: Point;
- FDrawBrush: Brush;
- procedure DoOutline(pPen: Pen; pStartPoint, pEndPoint: Point);
- function GetRectangle: Rectangle;
- protected
- property Canvas: Graphics read FCanvas;
- function GetShape(pStartPoint, pEndPoint: Point): GraphicsPath; virtual; abstract;
- function DoGetRectangle(pStartPoint, pEndPoint: Point): Rectangle;
- public
- StartPoint: Point;
- EndPoint: Point;
- procedure Dispose;
- procedure Draw(pStartPoint, pEndPoint: Point; pBrush: Brush); overload;
- procedure Draw; overload;
- procedure DrawOutline(pStartPoint, pEndPoint: Point);
- property DrawBrush: Brush read FDrawBrush write FDrawBrush;
- property Rectangle: System.Drawing.Rectangle read GetRectangle;
- constructor Create(pCanvas: Graphics);
- destructor Destroy; override;
- end;
-
- implementation
-
- { TShapes }
- function TShapes.Add(pShape: TShape): integer;
- begin
- Result := List.Add(pShape);
- end;
-
- procedure TShapes.Remove(pShape: TShape);
- begin
- List.Remove(pShape);
- end;
-
- procedure TShapes.Insert(pIndex: integer; pShape: TShape);
- begin
- List.Insert(pIndex, pShape);
- end;
-
- function TShapes.IndexOf(pShape: TShape): integer;
- begin
- Result := List.IndexOf(pShape);
- end;
-
- function TShapes.Contains(pShape: TShape): boolean;
- begin
- Result := List.Contains(pShape);
- end;
-
- function TShapes.GetShape(Index: integer): TShape;
- begin
- Result := List[Index] as TShape;
- end;
-
- procedure TShapes.SetShape(Index: integer; Value: TShape);
- begin
- List[Index] := Value;
- end;
-
- { TShape }
- constructor TShape.Create(pCanvas: Graphics);
- begin
- inherited Create;
- FCanvas := pCanvas;
- FDisposed := False;
- FStartPoint := Point.Create(0, 0);
- FEndPoint := Point.Create(0, 0);
- end;
-
- /// <summary>
- /// Destructor is used to call .Dispose to ensure that fCanvas.Dispose
- /// is called if it hasn't already been done.
- /// </summary>
- destructor TShape.Destroy;
- begin
- Dispose;
- inherited;
- end;
-
- /// <summary>
- /// Implement IDisposable.Dispose to ensure the fCanvas Graphics reference
- /// is explicitly disposed.
- /// </summary>
- procedure TShape.Dispose;
- begin
- if not FDisposed then
- FCanvas.Dispose;
- FDisposed := True;
- end;
-
- /// <summary>
- /// Draws a solid shape based on the startPoint and endPoint
- /// co-ordinates. Concrete classes must implement the GetShape method
- /// to determine the bounds for the shape.
- /// </summary>
- procedure TShape.Draw(pStartPoint, pEndPoint: Point; pBrush: Brush);
- begin
- //Draw the shape
- FCanvas.FillRegion(pBrush, Region.Create(GetShape(pStartPoint, pEndPoint)));
-
- //As the outline has a size of 1, it will still be visible along
- //some points of the shape. Draw another outline which uses a pen
- //the same color as the fill if it uses a SolidBrush, or one that
- //uses the same color as the original outline for other brush types.
- if pBrush is SolidBrush then
- DoOutline(Pen.Create((SolidBrush(pBrush)).Color, 1), pStartPoint, pEndPoint)
- else
- DoOutline(Pen.Create(Color.Black, 1), pStartPoint, pEndPoint);
- end;
-
- /// <summary>
- /// Draws a solid shape based on the StartPoint, EndPoint and Brush properties
- /// </summary>
- procedure TShape.Draw;
- begin
- Draw(StartPoint, EndPoint, FDrawBrush);
- end;
-
- /// <summary>
- /// Draws an outline of a shape based in the startPoint and endPoint
- /// co-ordinates. Concrete classes must implement the GetShape method
- /// to determine the bounds for the shape.
- /// </summary>
- procedure TShape.DrawOutline(pStartPoint, pEndPoint: Point);
- var
- lPen: Pen;
- begin
- //First erase the last outline
- lPen := Pen.Create(Color.White, 1);
- DoOutline(lPen, FOldStartPoint, FOldEndPoint);
-
- //Draw the new outline
- lPen := Pen.Create(Color.Black, 1);
- DoOutline(lPen, pStartPoint, pEndPoint);
-
- //Save the start and end points
- FOldStartPoint := pStartPoint;
- FOldEndPoint := pEndPoint;
- end;
-
- /// <summary>
- /// Return a Rectangle structure to represent the bounds of the shape.
- /// </summary>
- function TShape.DoGetRectangle(pStartPoint, pEndPoint: Point): Rectangle;
- begin
- Result := System.Drawing.Rectangle.FromLTRB(pStartPoint.X, pStartPoint.Y,
- pEndPoint.X, pEndPoint.Y);
- end;
-
- /// <summary>
- /// Return a Rectangle structure, based on FStartPoint and FEndPoint
- /// </summary>
- function TShape.GetRectangle: Rectangle;
- begin
- Result := DoGetRectangle(FStartPoint, FEndPoint);
- end;
-
- /// <summary>
- /// Draws the outline for the shape.
- /// </summary>
- procedure TShape.DoOutline(pPen: Pen; pStartPoint, pEndPoint: Point);
- var
- lGraphicsPath: GraphicsPath;
- begin
- lGraphicsPath := GetShape(pStartPoint, pEndPoint);
- FCanvas.DrawPath(pPen, lGraphicsPath);
- end;
-
- end.
-
-