unit U_Doodler1;
{Copyright 2001, Gary Darby, Intellitech Systems Inc., www.DelphiForFun.org

 This program may be used or modified for any non-commercial purpose
 so long as this original notice remains in place.
 All other rights are reserved
 }

{A drawing program - version 1}


interface
uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
     ExtCtrls, StdCtrls, ComCtrls;

type
  TPoints=record {info saved with each segment point}
    px,py:integer;
    color:TColor; {pen color}
    width:integer; {pen width}
    break:boolean; {true ==> this is the end of a segment}
  end;

  TForm1 = class(TForm)
    PaintBox1: TPaintBox;
    ResetBtn: TButton;
    ColorDialog1: TColorDialog;
    WidthUD: TUpDown;
    Edit1: TEdit;
    PenColor: TStaticText;
    Label1: TLabel;
    NumDivsGrp: TRadioGroup;
    procedure FormActivate(Sender: TObject);
    procedure PaintBox1Paint(Sender: TObject);
    procedure PaintBox1MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure PaintBox1MouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure PaintBox1MouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure ResetBtnClick(Sender: TObject);
    procedure PenColorClick(Sender: TObject);
    procedure NumDivsGrpClick(Sender: TObject);
  public
    drawing:boolean;  {mouse button is down}
    points:array of TPoints; {an array of points}
    numpoints:integer; {how many points to draw}
    cx,cy:integer;
    numdivs:integer;
    {penwidth:integer;}
    procedure makecaption(leftSide, Rightside:string);
  end;

var
  Form1: TForm1;

implementation
{$R *.DFM}

{******************* FormActivate **************}
procedure TForm1.FormActivate(Sender: TObject);
begin
  windowstate:=wsmaximized;
  with paintbox1 do
  begin
    cx:=width div 2;
    cy:=height div 2;
  end;
  NumDivsGrpClick(sender);
  numpoints:=-1;
  doublebuffered:=true;
  setlength(points,1000);
  makecaption('Doodler #1',#169+' 2001  G. Darby, www.delphiforfun.org' );
end;

{*************** PaintBox1Paint ************}
procedure TForm1.PaintBox1Paint(Sender: TObject);
{called whenever the drawing needs to be drawn}
var
  i:integer;
  x2,y2:integer;
begin
  with paintbox1, canvas do
  begin
    pen.color:=clblack;
    pen.width:=1;
    ellipse(cx-1,cy-1,cx+1,cy+1);
    if numpoints<=0 then exit;
    pen.width:=points[0].width;
    pen.color:=points[0].color;
    for i:=1 to numpoints do
    with points[i] do
    begin
      if width<>points[i-1].width
      then pen.width:=points[i].width;
      if color<>points[i-1].color
      then pen.color:=points[i].color;
       if not points[i-1].break then
       begin
        moveto(cx+points[i-1].px,cy+points[i-1].py); {first line}
        lineto(cx+points[i].px,cy+points[i].py);
        If numdivs mod 4 =0 then {4 or 8 divisions}
        begin {add 3 more line segments}
          moveto(cx-points[i-1].px,cy+points[i-1].py);
          lineto(cx-points[i].px,cy+points[i].py);
          moveto(cx+points[i-1].px,cy-points[i-1].py);
          lineto(cx+points[i].px,cy-points[i].py);
          moveto(cx-points[i-1].px,cy-points[i-1].py);
          lineto(cx-points[i].px,cy-points[i].py);
        end;
        if numdivs=8 then {add four more lines rotated 45,135,225,315 degrees}
        begin
          x2:=round(0.707*(points[i-1].px-points[i-1].py));
          y2:=round(0.707*(points[i-1].px+points[i-1].py));
          moveto(cx-x2,cy+y2);
          x2:=round(0.707*(points[i].px-points[i].py));
          y2:=round(0.707*(points[i].px+points[i].py));
          lineto(cx-x2,cy+y2);

          x2:=round(0.707*(points[i-1].px-points[i-1].py));
          y2:=round(0.707*(-points[i-1].px-points[i-1].py));
          moveto(cx-x2,cy+y2);
          x2:=round(0.707*(points[i].px-points[i].py));
          y2:=round(0.707*(-points[i].px-points[i].py));
          lineto(cx-x2,cy+y2);

          x2:=round(0.707*(-points[i-1].px+points[i-1].py));
          y2:=round(0.707*(-points[i-1].px-points[i-1].py));
          moveto(cx-x2,cy+y2);
          x2:=round(0.707*(-points[i].px+points[i].py));
          y2:=round(0.707*(-points[i].px-points[i].py));
          lineto(cx-x2,cy+y2);

          x2:=round(0.707*(-points[i-1].px+points[i-1].py));
          y2:=round(0.707*(points[i-1].px+points[i-1].py));
          moveto(cx-x2,cy+y2);
          x2:=round(0.707*(-points[i].px+points[i].py));
          y2:=round(0.707*(points[i].px+points[i].py));
          lineto(cx-x2,cy+y2);
        end;
      end;
    end;
  end;
end;

{******************* PaintBox1MouseDown **************}
procedure TForm1.PaintBox1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin drawing:=true; end;  {tells mouse move to add a point}

{******************* PaintBox1MouseMove **************}
procedure TForm1.PaintBox1MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
  if drawing then
  begin
    inc(numpoints); {make a new point}
    if numpoints>length(points) then setlength(points, length(points)+1000);
    with points[numpoints] do
    begin
      px:=x-cx;
      py:=y-cy;
      color:=pencolor.color;
      width:=widthUD.position;
      break:=false;
    end;
    paintbox1.refresh;
  end;
end;

{*************** PaintBox1MouseUp *************}
procedure TForm1.PaintBox1MouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  drawing:=false;
  points[numpoints].break:=true; {mark end of segment}
end;

{***************** ResetBtnClick ************}
procedure TForm1.ResetBtnClick(Sender: TObject);
{erase drawing info}
begin
  setlength(points,1000);
  numpoints:=-1;
  paintbox1.refresh;
end;

{******************* PenColorClick ************}
procedure TForm1.PenColorClick(Sender: TObject);
{get a new pen color}
begin
  If colordialog1.execute then
  begin pencolor.color:=ColorDialog1.Color; end;
end;

{****************** NumDivsGrpClick ************}
procedure TForm1.NumDivsGrpClick(Sender: TObject);
{set nbr of replications in drawing}
begin
  case NumDivsGrp.itemindex of
    0: numdivs:=1;
    1: numdivs:=4;
    2: numdivs:=8;
  end;
  paintbox1.refresh;
end;

{******************** MakeCaption ***************}
procedure TForm1.makecaption(leftSide, Rightside:string);
{draws a left/righ justified form caption}
var
  Metrics:NonClientMetrics;
  captionarea,spacewidth,nbrspaces:integer;
  b:TBitmap;
begin
  b:=TBitmap.create;  {to get a canvas}
  metrics.cbsize:=sizeof(Metrics);
  if SystemParametersInfo(SPI_GetNonCLientMetrics, sizeof(Metrics),@metrics,0)
  then  with metrics   do
  begin
    b.canvas.font.name:=Pchar(@metrics.LFCaptionFont.LfFaceName);
    with metrics.LFCaptionFont, b.canvas.font do
    begin
      height:=LFHeight;
      if lfweight=700 then style:=[fsbold];
      if lfitalic<>0 then style:=style+[fsitalic];
    end;
    {subtract 3 buttons + Icon + some border space}
    captionarea:=clientwidth-4*iCaptionwidth-4*iBorderWidth;;
    {n = # of spaces to insert}
    spacewidth:=b.canvas.textwidth(' ');
    nbrspaces:=(captionarea-b.canvas.textwidth(Leftside + Rightside)) div spacewidth;
    if nbrspaces>3 then caption:=LeftSide+stringofchar(' ',nbrspaces)+RightSide
    else caption:=LeftSide+' '+RightSide;
  end;
  b.free;
end;

end.