cxtimeedit.pas

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

PAS
1,149
字号
      if APos > AFirstDifferenceIndex then
      begin
        Result := EqualChars(AChar, ATimeEdit.Text[APos]);
        if Result then
          AChar := ATimeEdit.Text[APos];
      end
      else
      begin
        Result := True;
        if EqualChars(AChar, ATimeSuffix1[APos - ATimeZoneInfo.Start + 1]) then
          ATimeSuffix := ATimeSuffix1
        else if EqualChars(AChar, ATimeSuffix2[APos - ATimeZoneInfo.Start + 1]) then
          ATimeSuffix := ATimeSuffix2
        else
          Result := False;
        if Result then
        begin
          AChar := #0;
          SetEditText(ATimeSuffix, ATimeZoneInfo.Start);
          ATimeEdit.SelStart := ATimeZoneInfo.Start + ATimeZoneInfo.Length;
        end;
      end;
  end;

  function CheckTimeValueItemFirstDigit(ADigit: Char): Boolean;
  var
    AMaxTimeZoneValue, AMinTimeZoneValue: Integer;
  begin
    Result := True;
    GetTimeValueItemValueRange(AMinTimeZoneValue, AMaxTimeZoneValue);
    if ADigit = '0' then
    begin
      SetEditText('0' + ATimeEdit.Text[APos], APos);
      ATimeEdit.SelStart := ATimeEdit.SelStart + 1;
      AChar := #0;
    end
    else
      if ADigit <= IntToStr(AMaxTimeZoneValue)[1]  then
      begin
        SetEditText(ADigit + '0', APos);
        ATimeEdit.SelStart := ATimeEdit.SelStart + 1;
        AChar := #0;
      end
      else
      begin
        SetEditText('0', APos);
        ATimeEdit.SelStart := ATimeEdit.SelStart + 1;
      end
  end;

  function CheckTimeValueItemSecondDigit(ADigit: Char): Boolean;
  begin
    Result := ADigit <> '0';
    if Result then
    begin
      SetEditText('0', APos - 1);
      Result := True;
    end;
  end;

  function CheckTimeValueItem: Boolean;
  var
    AMaxTimeZoneValue, AMinTimeZoneValue: Integer;
    S: string;
  begin
    S := Copy(ATimeEdit.Text, ATimeZoneInfo.Start, ATimeZoneInfo.Length);
    S[APos - ATimeZoneInfo.Start + 1] := AChar;
    GetTimeValueItemValueRange(AMinTimeZoneValue, AMaxTimeZoneValue);
    Result := (StrToInt(S) >= AMinTimeZoneValue) and (StrToInt(S) <= AMaxTimeZoneValue);
    if not Result then
      if APos = ATimeZoneInfo.Start then
        Result := CheckTimeValueItemFirstDigit(AChar)
      else
        Result := CheckTimeValueItemSecondDigit(AChar);
  end;

begin
  if ATimeZoneInfo.Kind = tzTimeSuffix then
    Result := CheckTimeSuffix
  else
    Result := CheckTimeValueItem;
end;

function IsSpace(AChar: Char): Boolean;
begin
  Result :=  AChar = ' ';
end;

procedure PrepareTimeEditMasks;
var
  AMask: string;
  ATimeFormat: TcxTimeEditTimeFormat;
  I: Integer;
  S: string;
begin
  S := FormatDateTime('hh:mm:ss AMPM', 1.5);
  AMask := '';
  for I := 9 to Length(S) do
    if IsSpace(S[I]) then
      AMask := AMask + ' '
    else
      AMask := AMask + 'c';
  AMask := TrimRight(AMask);
  for ATimeFormat := tfHourMinSec to tfHour do
  begin
    S := cxTimeEditFormats[ATimeFormat, False, 1];
    S := Copy(S, 1, (3 - Integer(ATimeFormat)) * 3 - 1);
    S := S + AMask + ';1;0';
    cxTimeEditFormats[ATimeFormat, False, 1] := S;
  end;
end;

{ TcxTimeEditFormatListener }

constructor TcxTimeEditFormatListener.Create(AOwner: TPersistent);
begin
  inherited Create(AOwner);
  cxFormatController.AddListener(Self);
  PrepareTimeEditMasks;
end;

destructor TcxTimeEditFormatListener.Destroy;
begin
  cxFormatController.RemoveListener(Self);
  inherited Destroy;
end;

procedure TcxTimeEditFormatListener.FormatChanged;
begin
  PrepareTimeEditMasks;
end;

{ TcxTimeEditMaskMode }

function TcxTimeEditMaskMode.GetBlank(APos: Integer): Char;
begin
  if TcxCustomTimeEditProperties(Properties).GetEditingPlace(APos) = tzTimeSuffix then
    Result := #0
  else
    Result := '0';
end;

{ TcxCustomTimeEditProperties }

constructor TcxCustomTimeEditProperties.Create(AOwner: TPersistent);
begin
  inherited Create(AOwner);
  FTimeFormat := tfHourMinSec;
  ValueType := vtFloat;
  FAutoCorrectHours := True;
  FUse24HourFormat := True;
  FUseTimeFormatWhenUnfocused := True;
  UpdateEditMask;
  IgnoreMaskBlank := True;
  Increment := 1;
  MinValue := 0;
  MaxValue := 24 * 60 * 60 - 1;
  AlwaysShowBlanksAndLiterals := True;
end;

procedure TcxCustomTimeEditProperties.Assign(Source: TPersistent);
begin
  if Source is TcxCustomTimeEditProperties then
  begin
    BeginUpdate;
    try
      inherited Assign(Source);
      with Source as TcxCustomTimeEditProperties do
      begin
        Self.AutoCorrectHours := AutoCorrectHours; 
        Self.ShowDate := ShowDate;
        Self.TimeFormat := TimeFormat;
        Self.Use24HourFormat := Use24HourFormat;
        Self.UseTimeFormatWhenUnfocused := UseTimeFormatWhenUnfocused;
      end
    finally
      EndUpdate;
    end
  end
  else
    inherited Assign(Source);
end;

class function TcxCustomTimeEditProperties.GetContainerClass: TcxContainerClass;
begin
  Result := TcxTimeEdit;
end;

function TcxCustomTimeEditProperties.IsDisplayValueValid(var DisplayValue: TcxEditValue;
  AEditFocused: Boolean): Boolean;
var
  AText: string;
  ADateTime: TDateTime;
begin
  AText := VarToStr(DisplayValue);
  Result := True;
  try
    ADateTime := StrToDateTime(AText);
    DisplayValue := FormatDateTime(cxTimeEditFormats[TimeFormat, FUse24HourFormat, 0], ADateTime);
    DisplayValue := TrimRight(DisplayValue);
  except
    Result := False;
  end;
end;

function TcxCustomTimeEditProperties.IsEditValueValid(var EditValue: TcxEditValue;
  AEditFocused: Boolean): Boolean;
begin
  if VarIsStr(EditValue) then
    Result := IsDisplayValueValid(EditValue, AEditFocused)
  else
    Result := VarIsNull(EditValue) or VarIsDate(EditValue) or VarIsNumericEx(EditValue);
end;

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

  function InternalFormatDateTime(AValue: TcxEditValue): string;
  begin
    if AEditFocused or FUseTimeFormatWhenUnfocused and
      ((AValue = 0) or not ShowDate or (DateOf(AValue) = 0)) then
        Result := FormatDateTime(cxTimeEditFormats[TimeFormat, Use24HourFormat, 0], AValue)
    else
      if (AValue = 0) or not ShowDate or (DateOf(AValue) = 0) then
        Result := TimeToStr(AValue)
      else
        Result := DateTimeToStr(AValue);
    Result := TrimRight(Result);
  end;

begin
  if VarIsNull(AEditValue) then
    if not AEditFocused then
      DisplayValue := ''
    else
    begin
      DisplayValue := FormatDateTime(cxTimeEditFormats[TimeFormat, FUse24HourFormat, 0], 0);
      DisplayValue := TrimRight(DisplayValue);
    end
  else
    if not VarIsDate(AEditValue) and not VarIsNumericEx(AEditValue) and
        not VarIsStr(AEditValue) then
      raise EConvertError.CreateFmt(cxGetResourceString(@cxSEditTimeConvertError), [])
    else
      try
        if VarIsStr(AEditValue) then
          DisplayValue := InternalFormatDateTime(StrToDateTime(AEditValue))
        else
          DisplayValue := InternalFormatDateTime(AEditValue);
      except
        DisplayValue := InternalFormatDateTime(SysUtils.Now);
      end;
end;

procedure TcxCustomTimeEditProperties.ValidateDisplayValue(
  var ADisplayValue: TcxEditValue; var AErrorText: TCaption;
  var AError: Boolean; AEdit: TcxCustomEdit);
var
  AIsUserErrorDisplayValue: Boolean;
begin
  if AErrorText = '' then
    AErrorText := cxGetResourceString(@cxSEditTimeConvertError);
  DoValidate(ADisplayValue, AErrorText, AError, AEdit, AIsUserErrorDisplayValue);
end;

function TcxCustomTimeEditProperties.GetEditValueSource(AEditFocused: Boolean): TcxDataEditValueSource;
begin
  Result := GetValueEditorEditValueSource(AEditFocused);
end;

function TcxCustomTimeEditProperties.DefaultFocusedDisplayValue: TcxEditValue;
begin
  Result := FormatDateTime(cxTimeEditFormats[TimeFormat, FUse24HourFormat, 0], 0);
  Result := TrimRight(Result);
end;

function TcxCustomTimeEditProperties.ExtendValueUpToBound: Boolean;
begin
  Result := False;
end;

procedure TcxCustomTimeEditProperties.FormatChanged;
begin
  BeginUpdate;
  try
    UpdateEditMask;
  finally
    EndUpdate;
  end;
end;

function TcxCustomTimeEditProperties.GetDisplayFormatOptions: TcxEditDisplayFormatOptions;
begin
  Result := [dfoSupports, dfoNoCurrencyValue];
end;

function TcxCustomTimeEditProperties.GetModeClass(
  AMaskKind: TcxEditMaskKind): TcxMaskEditCustomModeClass;
begin
  Result := TcxTimeEditMaskMode;
end;

procedure TcxCustomTimeEditProperties.GetTimeZoneInfo(APos: Integer;
  out AInfo: TcxTimeEditZoneInfo);
begin
  AInfo.Kind := GetEditingPlace(APos);
  AInfo.Start := GetTimePartPos(AInfo.Kind);
  AInfo.Length := GetTimePartLength(AInfo.Kind);
  AInfo.TimeSuffixKind := GetTimeSuffixKind;
  AInfo.Use24HourFormat := Use24HourFormat;
end;

function TcxCustomTimeEditProperties.GetTimePartLength(AKind: TcxTimeEditZoneKind): Integer;
begin
  Result := 2;
end;

function TcxCustomTimeEditProperties.GetTimePartPos(AKind: TcxTimeEditZoneKind): Integer;
begin
  if AKind = tzTimeSuffix then
    Result := (3 - Integer(TimeFormat)) * 3 + 1
  else
    Result := Integer(AKind) * 3 + 1;
end;

function TcxCustomTimeEditProperties.GetTimeSuffixKind: TcxTimeSuffixKind;
begin
  Result := tskAMPMString;
end;

function TcxCustomTimeEditProperties.IsDisplayValueNumeric: Boolean;
begin
  Result := False;
end;

function TcxCustomTimeEditProperties.IsEditValueNumeric: Boolean;
begin
  Result := False;
end;

function TcxCustomTimeEditProperties.PrepareValue(const AValue: TcxEditValue): Variant;
begin
  Result := 0;
end;

function TcxCustomTimeEditProperties.PreserveSelection: Boolean;
begin
  Result := True;
end;

function TcxCustomTimeEditProperties.GetEditingPlace(
  APos: Integer): TcxTimeEditZoneKind;
var
  ATimeStringLength: Integer;
  ATimeZoneChar: Char;
  S: string;
begin
  ATimeStringLength := (3 - Integer(TimeFormat)) * 3 - 1;
  if (MaxLength > 0) and (APos > MaxLength) then
    APos := MaxLength;
  if (APos > ATimeStringLength) and not Use24HourFormat then
  begin
    Result := tzTimeSuffix;
    Exit;
  end;
  S := UpperCase(cxTimeEditFormats[TimeFormat, Use24HourFormat, 0]);
  if APos > Length(S) then
    APos := Length(S);
  ATimeZoneChar := S[APos];
  if not ((ATimeZoneChar = 'H') or (ATimeZoneChar = 'N') or
    (ATimeZoneChar = 'S')) then
  begin
    Inc(APos);
    if APos > Length(S) then
      APos := Length(S);
    ATimeZoneChar := S[APos];
  end;

  case ATimeZoneChar of
    'H':
      Result := tzHour;
    'N':
      Result := tzMin;

⌨️ 快捷键说明

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