📄 wwcalcedit.pas
字号:
end;
end;
procedure TwwCalcPanel.Paint;
var
bmp: TBitmap;
begin
inherited;
exit;
bmp := TBitmap.Create;
try
bmp.Width := Width;
bmp.Height := Height;
Draw( bmp.Canvas );
Canvas.CopyRect( ClientRect, bmp.Canvas, ClientRect );
finally
bmp.free;
end;
end;
*)
{ TwwCustomCalcEdit }
constructor TwwCustomCalcEdit.Create( aOwner: TComponent );
begin
inherited Create( aOwner );
fResult := 0;
MaxLength := 20;
WantReturns := True;
FCalcOptions := TwwPopupCalcOptions.Create(Self);
end;
procedure TwwCustomCalcEdit.CreateWnd;
begin
inherited;
end;
destructor TwwCustomCalcEdit.Destroy;
begin
FCalcOptions.Free;
if wwCalcHook<>0 then begin
UnhookWindowsHookEx(wwCalcHook);
wwCalcHook:= 0;
end;
inherited Destroy;
end;
function TwwCustomCalcEdit.IsBinaryOperator(Key:Char): boolean;
begin
Result := Key in ['+','-','*','/','%','^','='];
end;
function TwwCustomCalcEdit.IsUnaryOperator(Key:Char): boolean;
begin
Result := Key in ['@','#','r','n','l',';','!'];
end;
function TwwCustomCalcEdit.IsValidOperator(Key:Char): boolean;
begin
Result := IsBinaryOperator(Key) or IsUnaryOperator(Key) or
(Key in ['p']);
end;
procedure TwwCustomCalcEdit.ResetCalculator;
begin
fResult := 0.0;
Text:='';
FLastOperator := char(#0);
FLastOperand := 0;
FLastOperatorEquals:= False;
FClearOnNextKey := False;
FDecimalEntered := False;
end;
procedure TwwCustomCalcEdit.KeyDown(var Key: Word; Shift: TShiftState);
var curvalue:Double;
begin
inherited KeyDown(Key, Shift);
if (key=vk_Delete) or (key=vk_escape) then begin
//Clear the displayed number.
Text := '0';
//Treat vk_Escape as C key like the windows calculator.
//The C key clears the current calculation.
if (FLastOperator = char(#0)) or (key=vk_Escape) then begin
ResetCalculator;
end;
SelectAll;
Key := 0;
end;
//Handle Memory Keys....
if not (ssCtrl in Shift) or (Text = '') then exit;
try
curValue := StrToFloat(Text);
except
curValue := 0;
end;
if (ssCtrl in Shift) and ((key = ord('M')) or (key=ord('m'))) then
FMemoryValue := curValue;
if (ssCtrl in Shift) and ((key = ord('L')) or (key=ord('l'))) then
FMemoryValue := 0.0;
if (ssCtrl in Shift) and ((key = ord('P')) or (key=ord('p'))) then
FMemoryValue := FMemoryValue + CurValue;
if (ssCtrl in Shift) and ((key = ord('R')) or (key=ord('r'))) then
begin
Text := FloatToStr(FMemoryValue);
end;
end;
procedure TwwCustomCalcEdit.KeyPress(var Key: Char);
function IsValidDigit(Key:Char): boolean;
begin
Result := (key in ['0'..'9',',','.'])
or ((ord(key) >= VK_NUMPAD0) and (ord(key) <= VK_NUMPAD9));
end;
function IsValidCalcChar(Key:Char): boolean;
begin
result:= isValidDigit(Key) or (key=#13) or
(key = #8) or (key=#46) or (Key=#27) or
isValidOperator(Key)
end;
begin
inherited KeyPress(Key);
case Key of
'.',',':
if (Key='.') or (Key=',') then begin
if FClearOnNextKey then ResetCalculator;
if not FDecimalEntered then begin
if Text = '' then begin
Text := '0'+decimalseparator;
SelStart := Length(Text);
Key := #0;
end
else Key := DecimalSeparator;
FDecimalEntered := True;
end
else begin
Key := #0;
Beep;
end;
end;
'0'..'9',#96..#105:
begin
if FClearOnNextKey then begin
if FLastOperatorEquals then ResetCalculator
else Text := '';
end;
FClearOnNextKey := false;
end;
{ #27,#47:
begin
//If a vk_Escape (C) or a vk_delete (CE) was pressed the text needs to be reset to zero.
//Clear the displayed number.
Text := '0';
//Treat vk_Escape as C key like the windows calculator.
//The C key clears the current calculation.
if ord(key)=vk_Escape then ResetCalculator;
SelectAll;
Key := #0;
end}
else
begin
if Key=#13 then Key := '=';
if IsValidOperator(Key) then begin
if not isDroppedDown then DropDOwn;
Compute(Key);
if Key='=' then SelectAll;//SelStart := Length(Text);
Key := #0;
end
else Key := #0;
end;
end;
end;
procedure TwwCustomCalcEdit.Compute(OperatorKey:Char);
var
Value : Double;
flag: boolean;
i:integer;
begin
if Text = '' then
begin
Value := 0;
exit;
end;
try
Value := StrToFloat( Text );
except
Value := 0.0;
end;
if isBinaryOperator(OperatorKey) then
begin
if FClearOnNextKey and ((OperatorKey<>'=') and (ord(OperatorKey)<>vk_return))then
begin
FLastOperator := OperatorKey;
FLastOperatorEquals:= False;
end
else //Equals pressed.
begin
if not fLastOperatorEquals then flastoperand := Value;
flag := true;
try
if OperatorKey='%' then fResult := (fResult * flastoperand)/100.0
else begin
case FLastOperator of
'*': fResult := fResult * flastoperand;
'/': begin
if flastoperand <> 0 then
fResult := fResult / flastoperand
else begin Text := 'Error';
flag := False;
end;
end;
'+': fResult := fResult + flastoperand;
'-': fResult := fResult - flastoperand;
'^': fResult := Power(fResult,flastoperand);
else
flag := false;
FLastOperator := '=';
end;
end;
except
ResetCalculator;
Text := 'Error';
exit;
end;
FClearOnNextKey := true;
if flag then
Text := FloatToStr(fResult)
else fResult := Value;
if ((OperatorKey<>'=') and (ord(OperatorKey)<>vk_return)) then FLastOperator := OperatorKey
else FLastOperatorEquals:= True;
end;
end
else begin
case OperatorKey of
^M : FMemoryValue := Value;
'@' : fResult := Sqr(Value);
'r' : fResult := 1 / Value;
'#' : fResult := Power(Value,3);
'n' : fResult := ln(Value);
'l' : fResult := log10(Value);
'!' : begin
fResult := 1;
for i:= 1 to trunc(Value) do
fResult := fResult*i;
end;
';' : fResult := Trunc(Value);
end;
Text := FloatToStr(fResult);
end;
end;
function TwwCustomCalcEdit.GetValue: Double;
begin
Result := StrToFloat( Text );
end;
{procedure TwwCustomCalcEdit.ToggleSign;
begin
if Text[ 1 ] = CH_MINUS then Text := Copy( Text, 2, Length( Text ))
else Text := CH_MINUS + Text;
end;
}
procedure TwwCustomCalcEdit.CreateParams(var Params: TCreateParams);
begin
inherited CreateParams(Params);
Params.Style :=(Params.Style and not (ES_AUTOVSCROLL or ES_WANTRETURN) or
WS_CLIPCHILDREN);
if UseRightToLeftAlignment or LimitEditRect then
Params.Style:= Params.Style or ES_MULTILINE;
end;
function TwwCustomCalcEdit.IsDroppedDown: Boolean;
begin
result := (fDropDownCalc<>nil) and fDropDownCalc.Visible;
end;
procedure TwwCustomCalcEdit.CMCancelMode(var Message: TCMCancelMode);
var
F: THandle;
sb:TSpeedButton;
begin
if (Message.Sender <> Self) and (Message.Sender <> fDropDownCalc) and
(Message.Sender <> Button) and (Message.Sender.Parent <> fDropDownCalc) then
CloseUp(True);
end;
procedure TwwCustomCalcEdit.WMKillFocus(var Message: TWMKillFocus);
{begin
inherited;
if fDropDownCalc.HandleAllocated and
(Message.FocusedWnd <> fDropDownCalc.Handle) then
CloseUp(True);
}
var
F: THandle;
sb:TSpeedButton;
begin
inherited;
CloseUp(True);
exit;
F := GetFocus;
sb:= TwwCustomCalcEdit(self).Button;
if ((fDropDownCalc <> nil) and ( F <> fDropDownCalc.Handle ))
and ( F <> Handle )and
( F <> sb.parent.Handle ) then
CloseUp(True);
end;
//end;
procedure TwwCustomCalcedit.DropDown;
var
P: TPoint;
X, Y: Integer;
WinAttribute: HWnd;
ListBoxWidth, ListBoxHeight: integer;
function GetDeskTopHeight:Integer;
var Rect1:TRect;
begin
if SystemParametersInfo(SPI_GETWORKAREA,0,@Rect1,0) Then
GetDeskTopHeight:=Rect1.Bottom-Rect1.Top
else
GetDeskTopHeight:=Screen.Height;
end;
begin
if (fDropDownCalc <> nil) then exit;
if wwCalcHook=0 then
wwCalcHook := SetWindowsHookEx(WH_MOUSE, @wwCalcHookProc, HINSTANCE, GetCurrentThreadID);
fDropDownCalc := TwwCalcPanel.Create(self);
fDropDownCalc.Visible := False;
fDropDownCalc.Height := 175;
fDropDownCalc.Width := 250;
fDropDownCalc.Parent := Self;
if CalcOptions.background <> nil then begin
fDropDownCalc.BackgroundBitmapDrawStyle := CalcOptions.BackgroundStyle;
fDropDownCalc.BackgroundBitmap.Assign(CalcOptions.Background);
end;
fDropDownCalc.PanelColor := CalcOptions.PanelColor;
fDropDownCalc.Options := CalcOptions.Options;
fDropDownCalc.ButtonMargin := CalcOptions.ButtonMargin;
P := Parent.ClientToScreen(Point(Left, Top));
Y := P.Y + Height - 1;
if BorderStyle = bsNone then y:= y + 1;
{ 11/28/2000 - PYW - Check based on actual work area. }
if Y + fDropDownCalc.Height > GetDeskTopHeight then Y := P.Y - fDropDownCalc.Height;
{ 4/1/97 - Expand list to left since it goes past edge of screen }
X := P.X ;
if P.X + fDropDownCalc.Width >= Screen.Width then X := P.X + Width - 1 - fDropDownCalc.Width;
try
// DoDropDown;
except
exit;
end;
{ 3/13/97 - Always Top so that drop-down is not hidden under taskbar}
WinAttribute:= HWND_TOPMOST;
SetWindowPos(fDropDownCalc.Handle, WinAttribute, X, Y, 0, 0,
SWP_NOSIZE or SWP_NOACTIVATE or SWP_SHOWWINDOW);
fDropDownCalc.visible:= true;
Windows.SetFocus(Handle);
{ if not inAutoDropDown then DoSelectAll;
if Editable then ShowCaret(Handle);
LastShowHint:= ShowHint;
ShowHint:= False;
Invalidate; }
end;
{procedure TwwCustomCalcEdit.SetCalcOptions(Value: TwwPopupCalcOptions);
begin
if FCalcOptions <> Value then
FCalcOptions := Value;
end;}
procedure TwwCustomCalcEdit.CloseUp(Accept: Boolean);
begin
try
if fDropDownCalc = nil then exit
else begin
fDropDownCalc.Visible := False;
SetWindowPos(fDropDownCalc.Handle, 0, 0, 0, 0, 0, SWP_NOZORDER or
SWP_NOMOVE or SWP_NOSIZE or SWP_NOACTIVATE or SWP_HIDEWINDOW);
fDropDownCalc.Free;
fDropDownCalc := nil;
SetFocus;
if wwCalcHook<>0 then
begin
UnhookWindowsHookEx(wwCalcHook);
wwCalcHook:= 0;
end;
end;
SelectAll;
if IsDroppedDown then
begin
// SetWindowPos(fDropDownCalc.Handle, 0, 0, 0, 0, 0, SWP_NOZORDER or
// SWP_NOMOVE or SWP_NOSIZE or SWP_NOACTIVATE or SWP_HIDEWINDOW);
// Invalidate;
if fDropDownCalc.Focused or fDropDownCalc.ResultEdit.Focused then SetFocus;
fDropDownCalc.Visible := False;
fDropDownCalc.Free;
// if Assigned(FOnCloseUp) then FOnCloseUp(self, Accept);
end;
finally
if wwCalcHook<>0 then
begin
UnhookWindowsHookEx(wwCalcHook);
wwCalcHook:= 0;
end;
end;
end;
procedure Register;
begin
RegisterComponents('Samples', [TwwCustomCalcEdit]);
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -