unit UnitPhoneButton;

interface

uses
  Windows, SysUtils, Controls, Classes, Graphics, Messages;

type
  TPhoneState = (psUnknown, psNoLine, psNoDevice, psHookOff, psHookOn, psRing);


  TPhoneButton = class (TCustomControl)
  private
    FState: TPhoneState;
    FPlaying: Boolean;
    FRecording: Boolean;
    FCallerID: String;
    FDialed: String;
    procedure SetState(value: TPhoneState);
    procedure SetPlaying(value: Boolean);
    procedure SetRecording(value: Boolean);
    procedure SetCallerID(value: String);
  protected
    procedure WndProc(var Msg: TMessage); override;
  public
    constructor Create(id: Integer; panel: TWinControl);
    procedure Paint; override;
    procedure AddDialed(value: String);
    property State: TPhoneState read FState write SetState;
    property Playing: Boolean read FPlaying write SetPlaying;
    property Recording: Boolean read FRecording write SetRecording;
    property CallerID: String read FCallerID write SetCallerID;
    property OnClick;
    property OnMouseUp;
    property OnMouseMove;
    property OnMouseDown;
  end;

var
  PHONE_IMAGES: array[TPhoneState] of TGraphic;


function LoadPNG(resname: String): TGraphic;

implementation

{$R images.res}

uses
  pngimage, Types;

const
  TIMER_RING  = 1;
  TIMER_RING_DURATION  = 2000;
  TIMER_CALLERID  = 2;
  TIMER_CALLERID_DURATION  = 10000;

{ TPhoneButton }

procedure TPhoneButton.AddDialed(value: String);
begin
  FDialed:= FDialed+value;
  Refresh;
end;

constructor TPhoneButton.Create(id: Integer; panel: TWinControl);
begin
  inherited Create(panel);
  Name:= 'PhoneLine'+IntToStr(id);
  Tag:= id;
  Parent:= panel;
  FRecording:= False;
  FPlaying:= False;
  FState:= psUnknown;
  Visible:= true;
  DoubleBuffered:= True;
end;

procedure TPhoneButton.Paint;
var
  points: array of TPoint;
  brect: TRect;
begin
  inherited;
  Canvas.Pen.Color:= clBlue;
  Canvas.Brush.Color:= Color;
  Canvas.Rectangle(ClientRect);
  brect:= ClientRect;
  brect:= Rect(brect.Left+1, brect.Top+1, brect.Right-1, brect.Bottom-Abs(Canvas.Font.Height)*2-2);
  Canvas.StretchDraw(brect, PHONE_IMAGES[FState]);
  if (FPlaying) then
  begin
    Canvas.Brush.Color:= clLime;
    Canvas.Pen.Color:= clLime;
    SetLength(points, 3);
    points[0]:= Point(1, 1);
    points[1]:= Point(15, 10);
    points[2]:= Point(1, 19);
    Canvas.Polygon(points);
  end;
  if (FRecording) then
  begin
    Canvas.Brush.Color:= clRed;
    Canvas.Pen.Color:= clRed;
    Canvas.Ellipse(Rect(1, 20, 15 , 20+15));
  end;
  if (FCallerID<>'') then
  begin
    Canvas.Brush.Style:= bsClear;
    Canvas.Pen.Color:= clBlack;
    Canvas.TextOut(1, brect.Bottom, FCallerID);
  end;
  if (FDialed<>'') then
  begin
    Canvas.Brush.Style:= bsClear;
    Canvas.Pen.Color:= clBlack;
    Canvas.TextOut(1, brect.Bottom+Abs(Canvas.Font.Height), FDialed);
  end;
end;

procedure TPhoneButton.SetCallerID(value: String);
begin
  if (FCallerID<>value) then
  begin
    FCallerID:= value;
    if (value<>'') then
      SetTimer(Handle, TIMER_CALLERID, TIMER_CALLERID_DURATION, nil)
    else
      KillTimer(Handle, TIMER_CALLERID);
    Refresh;
  end
end;

procedure TPhoneButton.SetPlaying(value: Boolean);
begin
  if (FPlaying<>value) then
  begin
    FPlaying:= value;
    Refresh;
  end
end;

procedure TPhoneButton.SetRecording(value: Boolean);
begin
  if (FRecording<>value) then
  begin
    FRecording:= value;
    Refresh;
  end
end;

procedure TPhoneButton.SetState(value: TPhoneState);
begin
  if (FState<>value) then
  begin
    FState:= value;
    FDialed:= '';
    if (value=psRing) then
      SetTimer(Handle, TIMER_RING, TIMER_RING_DURATION, nil)
    else
      KillTimer(Handle, TIMER_RING);
    Refresh;
  end
end;

procedure TPhoneButton.WndProc(var Msg: TMessage);
begin
  if Msg.Msg = WM_TIMER then
  try
    if (Msg.WParam=TIMER_RING) and (FState=psRing) then
      SetState(psHookOn);

    if (Msg.WParam=TIMER_CALLERID) then
      SetCallerID('');

  except
  end
  else
    inherited;
end;

function LoadPNG(resname: String): TGraphic;
var
  stream: TResourceStream;
begin
  Result:= TPNGObject.Create;
  stream:= nil;
  try
    stream:= TResourceStream.Create(HInstance, resname, RT_RCDATA);
    Result.LoadFromStream(stream);
  finally
    stream.Free;
  end;
end;

initialization
  PHONE_IMAGES[psUnknown]:= LoadPNG('IMG_WHAT');
  PHONE_IMAGES[psNoLine]:= LoadPNG('IMG_RJ11');
  PHONE_IMAGES[psNoDevice]:= LoadPNG('IMG_USB');
  PHONE_IMAGES[psHookOn]:= LoadPNG('IMG_HON');
  PHONE_IMAGES[psHookOff]:= LoadPNG('IMG_HOFF');
  PHONE_IMAGES[psRing]:= LoadPNG('IMG_RING');

finalization


end.
