cxtextedit.pas

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

PAS
1,593
字号
      if ALineCount > 0 then
      begin
        if ARowCount > ALineCount then
          ARowCount := ALineCount;
      end
      else
        if (AEditSizeProperties.MaxLineCount > 0) and (ARowCount > AEditSizeProperties.MaxLineCount) then
          ARowCount := AEditSizeProperties.MaxLineCount;
      if ARowCount = 0 then
        Result.cx := 0
      else
        Result.cx := cxGetLongestTextRowWidth(ATextRows, ARowCount);
      ATextRows := nil;
      Result.cy := ACanvas.TextHeight('Zg');
      if ALineCount > 0 then
        Result.cy := Result.cy * ALineCount;
    end;
    if AAlignment <> nil then
      Result.cx := Result.cx + 1;
    if ACorrectWidth then
      Result.cx := Result.cx + ASizeCorrection.cx;
    if Result.cy > 0 then
      Result.cy := Result.cy + ASizeCorrection.cy;
  end;

begin
  if AEditSizeProperties.Width >= 0 then
    Result := GetAutoHeightSize
  else
    Result := GetBestFitSize;
end;

function GetTextEditDrawTextOffset(AViewData: TcxCustomEditViewData): TRect;
begin
  Result := AViewData.EditContentParams.Offsets;
  if not AViewData.IsInplace and (AViewData is TcxCustomTextEditViewData) then
    with AViewData as TcxCustomTextEditViewData do
      if TcxCustomTextEditProperties(Properties).EditingStyle in [esFixedList, esNoEdit] then
      begin
        if AViewData.VertAlignment = taTopJustify then
        begin
          Inc(Result.Top);
          Dec(Result.Bottom);
        end;
        if AViewData.HorzAlignment = taRightJustify then
          Inc(Result.Right)
        else
          Inc(Result.Left);
      end;
end;

function GetTextEditDrawTextOffset(AAlignment: TAlignment; AIsInplace: Boolean): TRect; // deprecated
begin
  Result := EditContentDefaultOffsets[AIsInplace];
end;

procedure PrepareTextRows(ACanvas: TCanvas; var TextOutData: TcxTextOutData;
  AText: PcxCaptionChar; var R: TRect; AFormat: TcxTextOutFormat; ASelStart,
  ASelLength: Integer; ASelBackgroundColor, ASelTextColor: TColor;
  AMaxLineCount: Integer = 0; ALeftIndent: Integer = 0; ARightIndent: Integer = 0);

  procedure InternalPrepareTextRows;
  var
    ATextLength: Integer;
  begin
    TextOutData.RowCount := 0;
    TextOutData.TextRows := nil;
    ATextLength := StrLen(AText);
    if ATextLength = 0 then
      Exit;
    TextOutData.TextParams := cxCalcTextParams(ACanvas.Handle, AFormat);
    TextOutData.TextRect := cxPrepareRect(R, TextOutData.TextParams, ALeftIndent,
      ARightIndent);

    if not IsRectEmpty(TextOutData.TextRect) then
    begin
      TextOutData.ForceEndEllipsis := not cxMakeTextRows(ACanvas.Handle, (AText), TextOutData.TextRect, TextOutData.TextParams, TextOutData.TextRows, TextOutData.RowCount, AMaxLineCount);
      if TextOutData.RowCount <> 0 then
      begin
        if (AMaxLineCount > 0) and (TextOutData.RowCount >= AMaxLineCount) then
        begin
          TextOutData.RowCount := AMaxLineCount;
          with TextOutData.TextParams do
            TextOutData.ForceEndEllipsis := TextOutData.ForceEndEllipsis and EndEllipsis and EditControl and not SingleLine;
        end
        else
          TextOutData.ForceEndEllipsis := False;

        cxPlaceTextRows(ACanvas.Handle, TextOutData.TextRect, TextOutData.TextParams, TextOutData.TextRows, TextOutData.RowCount);
        if (ASelStart < 0) or (ASelStart >= ATextLength) then
          ASelLength := 0
        else
          if (ASelLength + ASelStart) > ATextLength then
            ASelLength := ATextLength - ASelStart;

        TextOutData.SelStart := ASelStart;
        TextOutData.SelLength := ASelLength;
        TextOutData.SelBackgroundColor := ASelBackgroundColor;
        TextOutData.SelTextColor := ASelTextColor;
      end;
    end;
  end;

begin
  TextOutData.Initialized := True;
  InternalPrepareTextRows;
end;

procedure InternalTextOut(ACanvas: TCanvas; AViewInfo: TcxCustomTextEditViewInfo;
  AText: PcxCaptionChar; var R: TRect; AFormat: TcxTextOutFormat; ASelStart,
  ASelLength: Integer; ASelBackgroundColor, ASelTextColor: TColor;
  AMaxLineCount: Integer = 0; ALeftIndent: Integer = 0; ARightIndent: Integer = 0);
begin
  if not AViewInfo.TextOutData.Initialized then
    PrepareTextRows(ACanvas, AViewInfo.TextOutData, AText, R, AFormat, ASelStart,
    ASelLength, ASelBackgroundColor, ASelTextColor, AMaxLineCount, ALeftIndent,
    ARightIndent);
  TCanvasAccess(ACanvas).RequiredState([csFontValid]);
  with AViewInfo.TextOutData do
    cxTextRowsOutHighlight(ACanvas.Handle, TextRect, TextParams, TextRows,
    RowCount, SelStart, SelLength, SelBackgroundColor, SelTextColor, ForceEndEllipsis);
end;

procedure PrepareTextEditDrawTextFlags(ACanvas: TcxCanvas; AViewData: TcxCustomTextEditViewData;
  AViewInfo: TcxCustomTextEditViewInfo);
var
  ADrawTextOffset: TRect;
  AFlags: DWORD;
  R: TRect;
  ATextHeight: Integer;
  ATextParams: TcxTextParams;
  ATextRows: TcxTextRows;
  ARowCount: Integer;
begin
  if AViewData.Style.GetVisibleFont = nil then
    Exit;
  ACanvas.Font := AViewData.Style.GetVisibleFont;
  with AViewInfo do
  begin
    DrawTextFlags := AViewData.GetDrawTextFlags;
    AFlags := DrawTextFlags and not CXTO_SINGLELINE or
      CXTO_WORDBREAK or CXTO_EDITCONTROL or CXTO_CALCROWCOUNT;
    R := Rect(0, 0, TextRect.Right - TextRect.Left, MaxInt);
    ADrawTextOffset := AViewData.GetDrawTextOffset;
    Inc(R.Right, ADrawTextOffset.Left + ADrawTextOffset.Right);
    Dec(R.Right, AViewData.GetEditContentSizeCorrection.cx);
    Dec(R.Right, AViewData.ContentOffset.Left + AViewData.ContentOffset.Right);
    if TcxCustomTextEditProperties(AViewData.Properties).Alignment.Horz = taRightJustify then
      Inc(R.Right);
    ATextParams := cxCalcTextParams(ACanvas.Canvas, AFlags);
// TODO optimize
    cxMakeTextRows(ACanvas.Canvas, PcxCaptionChar(Text), R, ATextParams, ATextRows, ARowCount);
    ATextHeight := ARowCount * ATextParams.RowHeight;
    if ARowCount > 1 then
    begin
      DrawTextFlags := DrawTextFlags and not CXTO_SINGLELINE or
        CXTO_WORDBREAK or CXTO_EDITCONTROL;
      if ATextHeight > TextRect.Bottom - TextRect.Top then
        DrawTextFlags := DrawTextFlags and not CXTO_BOTTOM
          and not CXTO_CENTER_VERTICALLY or CXTO_TOP;
    end;
    ATextRows := nil;
  end;
end;

procedure InsertThousandSeparator(var S: string);

  function IsDigitChar(C: Char): Boolean;
  begin
    Result := C in ['0'..'9'];
  end;

var
  I, J: Integer;
  ACaption: string;
  APrefix, ASuffix: string;
begin
  APrefix := TrimRight(S);
  ASuffix := Copy(S, Length(APrefix) + 1, Length(S) - Length(APrefix));
  APrefix := TrimLeft(S);
  APrefix := Copy(S, 1, Length(S) - Length(APrefix));
  S := Trim(S);
  ACaption := RemoveExponentialPart(S);
  RemoveThousandSeparator(S);
  I := Pos(DecimalSeparator, S);
  if I = 0 then
    I := Length(S)
  else
    Dec(I);
  J := 0;
  while (I > 1) and IsDigitChar(S[I - 1]) do
  begin
    Inc(J);
    if J = 3 then
    begin
      Insert(ThousandSeparator, S, I);
      J := 0;
    end;
    Dec(I);
  end;
  S := APrefix + S + ACaption + ASuffix;
end;

function RemoveExponentialPart(var S: string): string;
var
  APos: Integer;
begin
  APos := Pos('E', UpperCase(S));
  if APos > 0 then
  begin
    Result := Copy(S, APos, Length(S) - APos + 1);
    Delete(S, APos, Length(S) - APos + 1);
  end
  else
    Result := '';
end;

procedure RemoveThousandSeparator(var S: string);
var
  APos: Integer;
begin
  repeat
    APos := Pos(ThousandSeparator, S);
    if APos <> 0 then
      Delete(S, APos, 1);
  until APos = 0;
end;

procedure SaveTextEditState(ATextEdit: IcxInnerTextEdit;
  ASaveText: Boolean;
  var APrevState: TcxCustomInnerTextEditPrevState);
begin
  with APrevState do
  begin
    IsPrevTextSaved := ASaveText;
    if ASaveText then
      PrevText := ATextEdit.EditValue;
    PrevSelStart := ATextEdit.SelStart;
    PrevSelLength := ATextEdit.SelLength;
  end;
end;

procedure SeparateDigitGroups(AEdit: TcxCustomTextEdit);

  function IsValidNumber(S: string): Boolean;
  var
    AValue: Extended;
  begin
    RemoveThousandSeparator(S);
    Result := (S <> '') and TextToFloat(PChar(S), AValue, fvExtended);
  end;

  function GetRealCaretPos: Integer;
  var
    I: Integer;
  begin
    Result := 0;
    for I := 1 to AEdit.SelStart do
      if AEdit.Text[I] <> ThousandSeparator then
        Inc(Result);
  end;

  procedure SetRealCaretPos(APrevCaretPos: Integer);
  var
    I: Integer;
    S: string;
  begin
    S := AEdit.Text;
    for I := 1 to Length(S) do
    begin
      if S[I] <> ThousandSeparator then
        Dec(APrevCaretPos);
      if APrevCaretPos = 0 then
      begin
        AEdit.SelStart := I;
        Break;
      end;
    end;
  end;

var
  ACaretPos: Integer;
  S: string;
begin
  S := AEdit.Text;
  InsertThousandSeparator(S);
  if IsValidNumber(S) then
  begin
    ACaretPos := GetRealCaretPos;
    AEdit.SetInternalDisplayValue(S);
    SetRealCaretPos(ACaretPos);
  end;
end;

{ TcxCustomInnerTextEditHelper }

constructor TcxCustomInnerTextEditHelper.Create(AEdit: TcxCustomInnerTextEdit);
begin
  inherited Create(nil);
  FEdit := AEdit;
  FAlignmentLock := False;
end;

// IcxContainerInnerControl
function TcxCustomInnerTextEditHelper.GetControlContainer: TcxContainer;
begin
  Result := Edit.Container;
end;

function TcxCustomInnerTextEditHelper.GetControl: TWinControl;
begin
  Result := Edit;
end;

// IcxCustomInnerEdit
function TcxCustomInnerTextEditHelper.CallDefWndProc(AMsg: UINT; WParam: WPARAM;
  LParam: LPARAM): LRESULT;

⌨️ 快捷键说明

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