⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wwcalcedit.pas

📁 一套及时通讯的原码
💻 PAS
📖 第 1 页 / 共 2 页
字号:
  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 + -