cxcalc.pas

来自「胜天进销存源码,国产优秀的进销存」· PAS 代码 · 共 1,899 行 · 第 1/4 页

PAS
1,899
字号
end;

procedure TcxCustomCalcEditProperties.SetPrecision(Value: Byte);
begin
  if AssignedValues.Precision and (Value = FPrecision) then
    Exit;

  AssignedValues.FPrecision := True;
  FPrecision := Value;
  Changed;
end;

procedure TcxCustomCalcEditProperties.SetQuickClose(Value: Boolean);
begin
  if Value <> FQuickClose then
  begin
    FQuickClose := Value;
    Changed;
  end;
end;

procedure TcxCustomCalcEditProperties.SetScientificFormat(Value: Boolean);
begin
  if Value <> FScientificFormat then
  begin
    FScientificFormat := Value;
    Changed;
  end;
end;

procedure TcxCustomCalcEditProperties.SetUseThousandSeparator(Value: Boolean);
begin
  if Value <> FUseThousandSeparator then
  begin
    FUseThousandSeparator := Value;
    Changed;
  end;
end;

function TcxCustomCalcEditProperties.GetAlwaysPostEditValue: Boolean;
begin
  Result := True;
end;

class function TcxCustomCalcEditProperties.GetAssignedValuesClass: TcxCustomEditPropertiesValuesClass;
begin
  Result := TcxCalcEditPropertiesValues;
end;

function TcxCustomCalcEditProperties.HasDigitGrouping(
  AIsDisplayValueSynchronizing: Boolean): Boolean;
begin
  Result := not ScientificFormat and UseThousandSeparator;
end;

function TcxCustomCalcEditProperties.PopupWindowAcceptsAnySize: Boolean;
begin
  Result := False;
end;

function TcxCustomCalcEditProperties.StrToFloatEx(S: string;
  var Value: Extended): Boolean;
var
  E: Extended;
  I: Integer;
begin
  // Ignore Thousand Separators
  for I := Length(S) downto 1 do
    if S[I] = ThousandSeparator then
      Delete(S, I, 1);
  if not TextToFloat(PChar(S), E, fvExtended) or
    ((E <> 0) and ((Abs(E) < MinDouble) or (Abs(E) > MaxDouble))) then
  begin
    Value := 0;
    Result := False;
  end
  else
    begin
      Value := E;
      Result := True;
    end;
end;

procedure TcxCustomCalcEditProperties.Assign(Source: TPersistent);
begin
  if Source is TcxCustomCalcEditProperties then
  begin
    BeginUpdate;
    try
      inherited Assign(Source);
      with TcxCustomCalcEditProperties(Source) do
      begin
        Self.BeepOnError := BeepOnError;

        Self.AssignedValues.Precision := False;
        if AssignedValues.Precision then
          Self.Precision := Precision;

        Self.QuickClose := QuickClose;
        Self.ScientificFormat := ScientificFormat;
        Self.UseThousandSeparator := UseThousandSeparator;
      end;
    finally
      EndUpdate
    end
  end  
  else
    inherited Assign(Source);
end;

class function TcxCustomCalcEditProperties.GetContainerClass: TcxContainerClass;
begin
  Result := TcxCalcEdit;
end;

function TcxCustomCalcEditProperties.GetEditValueSource(AEditFocused: Boolean): TcxDataEditValueSource;
begin
  if not AEditFocused and not AssignedValues.DisplayFormat and
    (IDefaultValuesProvider <> nil) and
    IDefaultValuesProvider.IsDisplayFormatDefined(True) then
      Result := evsText
  else
    Result := evsValue;
end;

function TcxCustomCalcEditProperties.IsDisplayValueValid(
  var DisplayValue: TcxEditValue; AEditFocused: Boolean): Boolean;
begin
//  if AEditFocused

  Result := True;
end;

function TcxCustomCalcEditProperties.IsEditValueValid(var EditValue: TcxEditValue;
  AEditFocused: Boolean): Boolean;
var
  AValue: Extended;
begin
  Result := VarIsNumericEx(EditValue) or VarIsSoftNull(EditValue);
  if not Result then
    Result := VarIsStr(EditValue) and
      TextToFloat(PChar(VarToStr(EditValue)), AValue, fvExtended);
end;

procedure TcxCustomCalcEditProperties.PrepareDisplayValue(
  const AEditValue: TcxEditValue; var DisplayValue: TcxEditValue;
  AEditFocused: Boolean);

  procedure RemoveInsignificantZeros(var S: string);
  var
    AExponentialPart: string;
    I: Integer;
  begin
    if Pos(DecimalSeparator, S) = 0 then
      Exit;
    AExponentialPart := RemoveExponentialPart(S);
    I := Length(S);
    while S[I] = '0' do
      Dec(I);
    Delete(S, I + 1, Length(S) - I);
    if S[Length(S)] = DecimalSeparator then
      Delete(S, Length(S), 1);
    S := S + AExponentialPart;
  end;

var
  AFormat: TFloatFormat;
  APrecision: Byte;
  S: string;
begin
  if VarIsSoftNull(AEditValue) then
    S := ''
  else
    if not AEditFocused and AssignedValues.DisplayFormat then
      S := FormatFloat(DisplayFormat, AEditValue)
    else
    begin
      if ScientificFormat then
        AFormat := ffExponent
      else
        AFormat := ffGeneral;
      APrecision := Precision;
      if APrecision = 0 then
        APrecision := cxDefCalcPrecision;
        
      S := FloatToStrF(AEditValue, AFormat, APrecision, 0);
      if UseThousandSeparator and not ScientificFormat then
        InsertThousandSeparator(S);
      if ScientificFormat then
        RemoveInsignificantZeros(S);
    end;
  DisplayValue := S;
end;

procedure TcxCustomCalcEditProperties.ValidateDisplayValue(
  var ADisplayValue: TcxEditValue; var AErrorText: TCaption;
  var Error: Boolean; AEdit: TcxCustomEdit);
begin
  Error := False;
  inherited ValidateDisplayValue(ADisplayValue, AErrorText, Error, AEdit);
end;

{ TcxCustomCalcEdit }

destructor TcxCustomCalcEdit.Destroy;
begin
  FreeAndNil(FCalculator);
  inherited Destroy;
end;

function TcxCustomCalcEdit.GetProperties: TcxCustomCalcEditProperties;
begin
  Result := TcxCustomCalcEditProperties(FProperties);
end;

function TcxCustomCalcEdit.GetActiveProperties: TcxCustomCalcEditProperties;
begin
  Result := TcxCustomCalcEditProperties(InternalGetActiveProperties);
end;

function TcxCustomCalcEdit.GetValue: Extended;
begin
  if VarIsNull(EditValue) or (VarIsStr(EditValue) and (EditValue = '')) then
    Result := 0
  else
    Result := EditValue;
end;

procedure TcxCustomCalcEdit.SetProperties(Value: TcxCustomCalcEditProperties);
begin
  FProperties.Assign(Value);
end;

procedure TcxCustomCalcEdit.SetValue(const Value: Extended);
begin
  InternalEditValue := Value;
end;

procedure TcxCustomCalcEdit.FormatChanged;
begin
  DataBinding.UpdateDisplayValue;
end;

function TcxCustomCalcEdit.CanDropDown: Boolean;
begin
  Result := (not ActiveProperties.ReadOnly) and DataBinding.IsDataAvailable;
end;

procedure TcxCustomCalcEdit.CreatePopupWindow;
begin
  inherited CreatePopupWindow;
  PopupWindow.ModalMode := False;
end;

procedure TcxCustomCalcEdit.DoEnter;
begin
  SynchronizeDisplayValue;
  inherited;
end;

procedure TcxCustomCalcEdit.DoExit;
begin
  inherited;
  DataBinding.UpdateDisplayValue;
end;

procedure TcxCustomCalcEdit.DoInitPopup;
begin
  inherited DoInitPopup;
  ActiveProperties.PopupControl := FCalculator;
end;

procedure TcxCustomCalcEdit.Initialize;
begin
  inherited Initialize;
  Value := 0;
  FCalculator := TcxPopupCalculator.Create(Self);
  FCalculator.Parent := PopupWindow;
  FCalculator.Edit := Self;
  FCalculator.AutoFontSize := False;
  FCalculator.OnHidePopup := HidePopup;
  ActiveProperties.PopupControl := FCalculator;
end;

procedure TcxCustomCalcEdit.InitializePopupWindow;
begin
  inherited InitializePopupWindow;
  with Calculator do
  begin
    HandleNeeded;
    Font.Assign(Self.ActiveStyle.GetVisibleFont);
    FontChanged;
    Resize;
  end;
end;

function TcxCustomCalcEdit.InternalGetEditingValue: TcxEditValue;
begin
  PrepareEditValue(Text, Result, True);
end;

function TcxCustomCalcEdit.IsValidChar(Key: Char): Boolean;

  function NumDigits(const S: string): Byte;
  var
    I: Integer;
  begin
    Result := 0;
    for I := 1 to Length(S) do
      if (S[I] = 'e') or (S[I] = 'E') then
        Break
      else
        if S[I] in ['0'..'9'] then
          Inc(Result);
  end;

var
  S: string;
  V: Extended;
  StartPos, StopPos: Integer;
begin
  Result := False;
  if not IsNumericChar(Key, ntExponent) then
    Exit;
  S := Text;
  StartPos := SelStart;
  StopPos := SelStart + SelLength;
  Delete(S, SelStart + 1, StopPos - StartPos);
  if (Key = '-') and (S = '') then
  begin
    Result := True;
    Exit;
  end;
  Insert(Key, S, StartPos + 1);
  Result := ActiveProperties.StrToFloatEx(S, V);
end;

procedure TcxCustomCalcEdit.KeyPress(var Key: Char);
begin
  if (Key = '.') or (Key = ',') then
    Key := DecimalSeparator;
  if IsTextChar(Key) and not IsValidChar(Key) then
  begin
    Key := #0;
    if ActiveProperties.BeepOnError then Beep;
  end;
  inherited KeyPress(Key);
end;

procedure TcxCustomCalcEdit.PopupWindowClosed(Sender: TObject);
begin
  if Text = cxGetResourceString(@scxSCalcError) then InternalEditValue := 0;
  if ActiveProperties.AutoSelect then SelectAll else SelStart := Length(Text);
  inherited PopupWindowClosed(Sender);
end;

procedure TcxCustomCalcEdit.PopupWindowShowed(Sender: TObject);
begin
  inherited PopupWindowShowed(Sender);
  FCalculator.Init;
end;

procedure TcxCustomCalcEdit.PropertiesChanged(Sender: TObject);
begin
  if (Sender <> nil) and ActiveProperties.FormatChanging then
    Exit;
  inherited PropertiesChanged(Sender);
  if not PropertiesChangeLocked then
  begin
    FCalculator.BeepOnError := ActiveProperties.BeepOnError;
    FCalculator.Precision := ActiveProperties.Precision;
    ActiveProperties.FChangedLocked := True;
    ActiveProperties.PopupControl := FCalculator;
    ActiveProperties.FChangedLocked := False;
  end;
end;

function TcxCustomCalcEdit.InternalPrepareEditValue(const ADisplayValue: string;
  out EditValue: TcxEditValue): Boolean;
var
  AValue: Extended;
  S: string;
begin
  Result := True;
  S := VarToStr(ADisplayValue);
  if not ActiveProperties.ScientificFormat and ActiveProperties.UseThousandSeparator then
    RemoveThousandSeparator(S);
  if Trim(S) = '' then
    EditValue := Null
  else
  begin
    Result := TextToFloat(PChar(S), AValue, fvExtended);
    if Result then
      EditValue := AValue
    else
      EditValue := Null;
  end;
end;

class function TcxCustomCalcEdit.GetPropertiesClass: TcxCustomEditPropertiesClass;
begin
  Result := TcxCustomCalcEditProperties;
end;

procedure TcxCustomCalcEdit.PasteFromClipboard;
begin
  if DoEditing then
    Calculator.PasteFromClipboard;
end;

procedure TcxCustomCalcEdit.PrepareEditValue(
  const ADisplayValue: TcxEditValue; out EditValue: TcxEditValue;
  AEditFocused: Boolean);
begin
  InternalPrepareEditValue(ADisplayValue, EditValue);
end;

{ TcxCalcEdit }

class function TcxCalcEdit.GetPropertiesClass: TcxCustomEditPropertiesClass;
begin
  Result := TcxCalcEditProperties;
end;

function TcxCalcEdit.GetActiveProperties: TcxCalcEditProperties;
begin
  Result := TcxCalcEditProperties(InternalGetActiveProperties);
end;

function TcxCalcEdit.GetProperties: TcxCalcEditProperties;
begin
  Result := TcxCalcEditProperties(FProperties);
end;

procedure TcxCalcEdit.SetProperties(Value: TcxCalcEditProperties);
begin
  FProperties.Assign(Value);
end;

{ TcxFilterCalcEditHelper }

class function TcxFilterCalcEditHelper.GetFilterEditClass: TcxCustomEditClass;
begin
  Result := TcxCalcEdit;
end;

class function TcxFilterCalcEditHelper.GetSupportedFilterOperators(
  AProperties: TcxCustomEditProperties;
  AValueTypeClass: TcxValueTypeClass;
  AExtendedSet: Boolean = False): TcxFilterControlOperators;
begin
  Result := [fcoEqual, fcoNotEqual, fcoLess, fcoLessEqual, fcoGreater,
    fcoGreaterEqual, fcoBlanks, fcoNonBlanks];
  if AExtendedSet then
    Result := Result + [fcoBetween, fcoNotBetween, fcoInList, fcoNotInList];
end;

class procedure TcxFilterCalcEditHelper.InitializeProperties(AProperties,
  AEditProperties: TcxCustomEditProperties; AHasButtons: Boolean);
begin
  inherited InitializeProperties(AProperties, AEditProperties, AHasButtons);
  with TcxCustomCalcEditProperties(AProperties) do
    QuickClose := True;
end;

initialization
  GetRegisteredEditProperties.Register(TcxCalcEditProperties, scxSEditRepositoryCalcItem);
  FilterEditsController.Register(TcxCalcEditProperties, TcxFilterCalcEditHelper);

finalization
  FilterEditsController.Unregister(TcxCalcEditProperties, TcxFilterCalcEditHelper);

end.

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?