返回
{***************************************************************}
{*** FVision Unit Version1.0 ***}
{*** 蓝蚂蚁工作室 ***}
{***************************************************************}
{*** 计算器单元 ***}
{***************************************************************}
{$O+,F+,X+,I-,S-,N+,E+}
Unit FCalc;
Interface
Uses
FMouse,FEvent,FView,Graph,FGraph,FWrite;
Const
MaxBut=24;
Type
PBut=^TBut;
TBut=object(TView)
R:TRect;
Str:string[2];
Wid,Hig:integer;
KeyCh:Char;
constructor Init(Rr:TRect;S:string;Key:Char);
procedure Paint;virtual;
procedure DrawPush;
procedure MoveTo(X,Y:Integer);virtual;
function Push:Boolean;
procedure HandleEvent(var Event:TEvent);virtual;
end;
PCalc = ^TCalc;
TCalc = object(TView)
Len:Integer;
Size_:TPoint;
Status:Word;
Number:string[30];
Sign:Char;
Operator:Char;
Operand:Extended;
constructor Init(x,y,l:Integer);
procedure CalcKey(Key: Char);
procedure Clear;
procedure Draw;virtual;
procedure Paint;virtual;
procedure MoveTo(x,y:Integer);virtual;
procedure HandleEvent(var Event: TEvent); virtual;
end;
Function CalculatorWindow:PWindow;
Implementation
const
csError = 10;
csFirst = 11;
csValid = 12;
constructor TBut.Init;
begin
Inherited Init;
R:=Rr;
Origin:=R.A;
Str:=S;
Wid:=r.b.x-r.a.x;
Hig:=r.b.y-r.a.y;
KeyCh:=Key;
end;
procedure TBut.Paint;
begin
hidemouse;
drawbroad(r.a.x+1,r.a.y+1,r.b.x-1,r.b.y-1,1);
setcolor(0);
rectangle(r.a.x,r.a.y,r.b.x,r.b.y);
setcolor(4);
settextstyle(0,0,1);
outtextxy(r.a.x+ wid div 2 -length(str)*4,r.a.y+hig div 2-3,str);
showmouse;
end;
procedure tbut.drawpush;
begin
hidemouse;
drawbroad(r.a.x+1,r.a.y+1,r.b.x-1,r.b.y-1,0);
setcolor(0);
rectangle(r.a.x,r.a.y,r.b.x,r.b.y);
setcolor(4);
settextstyle(0,0,1);
outtextxy(r.a.x+ wid div 2 -length(str)*4+1,r.a.y+hig div 2-3+1,str);
showmouse;
end;
procedure tbut.moveto;
begin
Origin.X:=x;
Origin.Y:=y;
r.a.x:=x;r.a.y:=y;
r.b.x:=r.a.x+wid;
r.b.y:=r.a.y+hig;
end;
function tbut.push;
label circle;
var event:tevent;
begin
push:=true;
drawpush;
circle:
repeat
clearevent(event);
getevent(event);
until (event.what=evmouseup)or(event.what=evmousemove);
if event.what=evmouseup then paint
else if isin(event.where,r) then goto circle
else begin paint;push:=false;end;
end;
procedure tbut.handleevent;
begin
case event.what of
evmousedown:if isin(event.where,r) and (event.buttons=mbleftbutton) then
if push then
begin
event.what:=evcommand;
event.command:=cmbuttondown;
event.infochar:=keych;
end;
evkeydown :if upcase(event.charcode)=keych then
begin event.what:=evcommand;
event.command:=cmbuttondown;
event.infochar:=keych;
end;
end;
end;
constructor TCalc.Init;
begin
Inherited Init;
size_.x:=l;
len:=l;
size_.y:=1;
broad.a.x:=(x div 8)*8;
broad.a.y:=y;
broad.b.x:=broad.a.x+8*size_.x;
broad.b.y:=broad.a.y+15;
Origin:=Broad.A;
Clear;
end;
procedure TCalc.CalcKey(Key: Char);
var
R: Extended;
procedure FlushKey;
begin
case key of
'T':key:=#251;
'S':key:='^';
'N':key:='@';
end;
end;
procedure Error;
begin
Status:=csError;
Number := 'Error';
Sign := ' ';
end;
procedure SetDisplay(R: Extended);
var
S: string[63];
begin
Str(R: 0: 10, S);
if S[1] <> '-' then Sign := ' ' else
begin
Delete(S, 1, 1);
Sign := '-';
end;
if Length(S) > len then Error
else
begin
while S[Length(S)] = '0' do Dec(S[0]);
if S[Length(S)] = '.' then Dec(S[0]);
Number := S;
end;
end;
procedure GetDisplay(var R: Extended);
var
E: Integer;
begin
Val(Sign + Number, R, E);
end;
procedure CheckFirst;
begin
if Status = csFirst then
begin
Status := csValid;
Number := '0';
Sign := ' ';
end;
end;
begin
Key := UpCase(Key);
flushkey;
if (Status = csError) and (Key <> 'C') then Key := ' ';
case Key of
'0'..'9':
begin
CheckFirst;
if Number = '0' then Number := '';
if length(Number)<len-1 then
Number := Number + Key;
end;
'.':
begin
CheckFirst;
if Pos('.', Number) = 0 then Number := Number + '.';
end;
#8, #27:
begin
CheckFirst;
if Length(Number) = 1 then Number := '0' else Dec(Number[0]);
end;
'_', #241:
if Sign = ' ' then Sign := '-' else Sign := ' ';
#251:begin Status := csFirst;
GetDisplay(R);
if sign='-' then error
else SetDisplay(sqrt(R));
Operator := Key;
GetDisplay(Operand);
end;
'^': begin Status := csFirst;
getdisplay(r);
setdisplay(r*r);
Operator := Key;
GetDisplay(Operand);
end;
'@': begin Status := csFirst;
getdisplay(r);
if r=0 then error
else setdisplay(1/r);
Operator := Key;
GetDisplay(Operand);
end;
'+', '-', '*', '/', '=', '%', #13:
begin
if Status = csValid then
begin
Status := csFirst;
GetDisplay(R);
if Key = '%' then
case Operator of
'+', '-': R := Operand * R / 100;
'*', '/': R := R / 100;
end;
case Operator of
'+': SetDisplay(Operand + R);
'-': SetDisplay(Operand - R);
'*': SetDisplay(Operand * R);
'/': if R = 0 then Error else SetDisplay(Operand / R);
end;
end;
Operator := Key;
GetDisplay(Operand);
end;
'C':
Clear;
end;
Paint;
end;
procedure TCalc.Clear;
begin
Status := csFirst;
Number := '0';
Sign := ' ';
Operator := '=';
end;
procedure TCalc.MoveTo;
begin
Origin.X:=x;
Origin.Y:=y;
AssignRect(Broad,(x div 8)*8,y,(x div 8)*8+8*Size_.x,y+15);
end;
procedure TCalc.Draw;
var
I,j: Integer;
B: string;
begin
b:='';
I := Size_.X - Length(Number);
for j:=1 to size_.x do b:=b+' ';
b[i]:=Sign;
for j:=i+1 to Size_.x do b[j]:=Number[j-i];
hideMouse;
Writec16(Broad.a.x div 8,Broad.a.y,b,$0f);
ShowMouse;
end;
procedure TCalc.Paint;
begin
HideMouse;
DrawBroadC(Broad.a.x-2,Broad.a.y-2,Broad.b.x+2,Broad.b.y+2,0,0);
Draw;
end;
procedure TCalc.HandleEvent(var Event: TEvent);
const
KeyCan: array[0..30] of Char =
'C'#27'%'#241#251'789/^456*@123-#0.=+&_TSN'#13#8;
var
i:Integer;
begin
case Event.What of
evCommand:
if Event.Command = cmButtonDown then
begin
CalcKey(Event.InfoChar);
ClearEvent(Event);
end;
evKeyDown:
for i:=0 to 30 do
if UpCase(Event.CharCode)=KeyCan[i] then
begin
CalcKey(Event.CharCode);
ClearEvent(Event);
Exit;
end;
end;
end;
{ TCalculator }
Function CalculatorWindow:PWindow;
const
KeyChar: array[0..maxbut] of Char = 'C'#27'%'#241#251'789/^456*@123-#0.=+&';
var
I: Integer;
P: PWindow;
R: TRect;
begin
AssignRect(R, 0, 0, 270, 200);
P:=New(PWindow,Init(R,'Calculator',True));
P^.Option:=P^.Option or opAligen8;
for I := 0 to MaxBut do
begin
R.A.X := 18+(I mod 5) * 40 ;
R.A.Y := 55+(I div 5) * 25 ;
R.B.X := R.A.X + 32;
R.B.Y := R.A.Y + 20;
P^.Insert(New(PBut, Init(R, KeyChar[I], KeyChar[I])));
end;
P^.Insert(New(PCalc, Init(20,30,30)));
P^.Next;
P^.Center;
CalculatorWindow:=P;
end;
end.