cxdrawtextutils.pas

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

PAS
994
字号
{********************************************************************}
{                                                                    }
{           Developer Express Visual Component Library               }
{           Express Cross Platform Library classes                   }
{                                                                    }
{           Copyright (c) 2000-2008 Developer Express Inc.           }
{           ALL RIGHTS RESERVED                                      }
{                                                                    }
{   The entire contents of this file is protected by U.S. and        }
{   International Copyright Laws. Unauthorized reproduction,         }
{   reverse-engineering, and distribution of all or any portion of   }
{   the code contained in this file is strictly prohibited and may   }
{   result in severe civil and criminal penalties and will be        }
{   prosecuted to the maximum extent possible under the law.         }
{                                                                    }
{   RESTRICTIONS                                                     }
{                                                                    }
{   THIS SOURCE CODE AND ALL RESULTING INTERMEDIATE FILES            }
{   (DCU, OBJ, DLL, ETC.) ARE CONFIDENTIAL AND PROPRIETARY TRADE     }
{   SECRETS OF DEVELOPER EXPRESS INC. THE REGISTERED DEVELOPER IS    }
{   LICENSED TO DISTRIBUTE THE EXPRESSCROSSPLATFORMLIBRARY AND ALL   }
{   ACCOMPANYING VCL CONTROLS AS PART OF AN EXECUTABLE PROGRAM       }
{   ONLY.                                                            }
{                                                                    }
{   THE SOURCE CODE CONTAINED WITHIN THIS FILE AND ALL RELATED       }
{   FILES OR ANY PORTION OF ITS CONTENTS SHALL AT NO TIME BE         }
{   COPIED, TRANSFERRED, SOLD, DISTRIBUTED, OR OTHERWISE MADE        }
{   AVAILABLE TO OTHER INDIVIDUALS WITHOUT EXPRESS WRITTEN CONSENT   }
{   AND PERMISSION FROM DEVELOPER EXPRESS INC.                       }
{                                                                    }
{   CONSULT THE END USER LICENSE AGREEMENT FOR INFORMATION ON        }
{   ADDITIONAL RESTRICTIONS.                                         }
{                                                                    }
{********************************************************************}

unit cxDrawTextUtils;

{$I cxVer.inc}

interface

uses
  Windows, Controls,
{$IFDEF DELPHI6}
  Types,
{$ELSE}
  Classes,
{$ENDIF}
  SysUtils, Graphics;

const
  CXTO_LEFT                    = $00000000;
  CXTO_CENTER_HORIZONTALLY     = $00000001;
  CXTO_RIGHT                   = $00000002;
  CXTO_JUSTIFY_HORIZONTALLY    = $00000003;
  CXTO_DISTRIBUTE_HORIZONTALLY = $00000004;

  CXTO_TOP                     = $00000000;
  CXTO_CENTER_VERTICALLY       = $00000010;
  CXTO_BOTTOM                  = $00000020;
  CXTO_DISTRIBUTE_VERTICALLY   = $00000030;

  CXTO_PREVENT_LEFT_EXCEED     = $00000040;
  CXTO_PREVENT_TOP_EXCEED      = $00000080;

  CXTO_WORDBREAK               = $00000100;
  CXTO_SINGLELINE              = $00000200;
  CXTO_EXPANDTABS              = $00000400;
  CXTO_END_ELLIPSIS            = $00000800;

  CXTO_PATTERNEDTEXT           = $00001000;
  CXTO_EXTERNALLEADING         = $00002000;
  CXTO_EDITCONTROL             = $00004000;
  CXTO_NOCLIP                  = $00008000;

  CXTO_AUTOINDENTS             = $00010000;
  CXTO_CHARBREAK               = $00020000;

  CXTO_CALCRECT                = $00100000;
  CXTO_CALCROWCOUNT            = $00200000;

  CXTO_DEFAULT_FORMAT          = CXTO_LEFT or CXTO_TOP or CXTO_SINGLELINE;

  cxTextSpace = 2;

type
  TCaptionChar = Char;
  TcxCaptionChar = TCaptionChar;
  PcxCaptionChar = PChar;
  TcxTextOutFormat = DWORD;
  TcxTextAlignX = (taLeft, taCenterX, taRight, taJustifyX, taDistributeX);
  TcxTextAlignY = (taTop, taCenterY, taBottom, taDistributeY);

  PcxTextParams = ^TcxTextParams;
  TcxTextParams = packed record
    RowHeight: Integer;
    tmExternalLeading: Integer;
    FullRowHeight: Integer;
    EndEllipsisWidth: Integer;
    BreakChar: TcxCaptionChar;
    TextAlignX: TcxTextAlignX;
    TextAlignY: TcxTextAlignY;
    WordBreak: Boolean;
    SingleLine: Boolean;
    ExpandTabs: Boolean;
    EndEllipsis: Boolean;
    ExternalLeading: Boolean;
    EditControl: Boolean;
    NoClip: Boolean;
    AutoIndents: Boolean;
    PreventLeftExceed: Boolean;
    PreventTopExceed: Boolean;
    CharBreak: Boolean;
    CalcRowCount: Boolean;
    CalcRect: Boolean;
    MaxCharWidth: Integer;
    CharSet: Byte;
  end;

  TcxTextRow = record
    Text: PcxCaptionChar;
    TextLength: Integer;
    TextExtents: TSize;
    BreakCount: Integer;
    TextOriginX: Integer;
    TextOriginY: Integer;
    StartOffset: Integer;
  end;
  TcxTextRows = array of TcxTextRow;

  TCanvasHandle = HDC;

function cxCalcTextParams(AHandle: TCanvasHandle; AFormat: DWORD): TcxTextParams; overload;
function cxCalcTextParams(ACanvas: TCanvas; AFormat: DWORD): TcxTextParams; overload;

function cxCalcTextExtents(AHandle: TCanvasHandle; AText: PcxCaptionChar;
  ATextLength: Integer; AExpandTabs: Boolean): TSize;
function cxGetLongestTextRowWidth(const ATextRows: TcxTextRows; ARowCount: Integer): Integer;

procedure cxCalcTextRowExtents(AHandle: TCanvasHandle; var ATextRow: TcxTextRow;
  const ATextParams: TcxTextParams);

function cxMakeTextRows(AHandle: TCanvasHandle;
  AText: PcxCaptionChar; const R: TRect;
  const ATextParams: TcxTextParams; out ATextRows: TcxTextRows;
  out ACount: Integer; AMaxLineCount: Integer = 0): Boolean; overload;
function cxMakeTextRows(ACanvas: TCanvas;
  AText: PcxCaptionChar; const R: TRect;
  const ATextParams: TcxTextParams; out ATextRows: TcxTextRows;
  out ACount: Integer; AMaxLineCount: Integer = 0): Boolean; overload;

procedure cxPlaceTextRows(AHandle: TCanvasHandle; const R: TRect;
  var ATextParams: TcxTextParams; const ATextRows: TcxTextRows; ARowCount: Integer);

function cxMakeFormat(ATextAlignX: TcxTextAlignX; ATextAlignY: TcxTextAlignY): DWORD;

function cxPrepareRect(const R: TRect; const ATextParams: TcxTextParams;
  ALeftIndent, ARightIndent: Integer): TRect;

function cxTextOut(AHandle: TCanvasHandle; AText: PcxCaptionChar; var R: TRect;
  AFormat: TcxTextOutFormat = CXTO_DEFAULT_FORMAT; AMaxLineCount: Integer = 0;
  ALeftIndent: Integer = 0; ARightIndent: Integer = 0): Integer; overload;

function cxTextOut(AHandle: TCanvasHandle; AText: PcxCaptionChar; var R: TRect;
  AFormat: TcxTextOutFormat; ASelStart, ASelLength: Integer;
  AColor, ATextColor: TColor; AMaxLineCount: Integer = 0;
  ALeftIndent: Integer = 0; ARightIndent: Integer = 0): Integer; overload;

// for TCanvas
function cxTextOut(ACanvas: TCanvas; AText: PcxCaptionChar; var R: TRect;
  AFormat: TcxTextOutFormat = CXTO_DEFAULT_FORMAT; AMaxLineCount: Integer = 0;
  ALeftIndent: Integer = 0; ARightIndent: Integer = 0): Integer; overload;

function cxTextOut(ACanvas: TCanvas; AText: PcxCaptionChar; var R: TRect;
  AFormat: TcxTextOutFormat; ASelStart, ASelLength: Integer;
  AColor, ATextColor: TColor; AMaxLineCount: Integer = 0;
  ALeftIndent: Integer = 0; ARightIndent: Integer = 0): Integer; overload;

procedure cxTextRowsOutHighlight(AHandle: TCanvasHandle; const R: TRect;
  const ATextParams: TcxTextParams; const ATextRows: TcxTextRows; ARowCount,
  ASelStart, ASelLength: Integer; AColor, ATextColor: TColor; AForceEndEllipsis: Boolean);

implementation

uses
  Math,
  cxClasses, cxGraphics;

type
  TCanvasAccess = class(TControlCanvas);

const
  CXTO_VERT_ALIGN_OFFSET = 4;
  CXTO_HORZ_ALIGN_MASK   = CXTO_CENTER_HORIZONTALLY or CXTO_RIGHT or CXTO_JUSTIFY_HORIZONTALLY or CXTO_DISTRIBUTE_HORIZONTALLY;
  CXTO_VERT_ALIGN_MASK   = CXTO_CENTER_VERTICALLY or CXTO_BOTTOM or CXTO_DISTRIBUTE_VERTICALLY;

  Tab: TcxCaptionChar = #9;
  LF: TcxCaptionChar = #10;
  CR: TcxCaptionChar = #13;
  Space: TcxCaptionChar = ' ';

  cxEndEllipsisChars: PcxCaptionChar = '...';

var
  cxEndEllipsisCharsLength: Integer;

function cxMakeFormat(ATextAlignX: TcxTextAlignX; ATextAlignY: TcxTextAlignY): DWORD;
begin
  Result := Byte(ATextAlignX) or (Byte(ATextAlignY) shl CXTO_VERT_ALIGN_OFFSET);
end;

function cxCalcTextExtents(AHandle: TCanvasHandle; AText: PcxCaptionChar;
  ATextLength: Integer; AExpandTabs: Boolean): TSize;
var
  ATextExtent: DWORD;
  R: TRect;
begin
  if AExpandTabs then
  begin
    if ATextLength <= 4096 then
    begin
      ATextExtent := GetTabbedTextExtent(AHandle, AText, ATextLength, 0, Result);
      Result.cx := LoWord(ATextExtent);
      Result.cy := HiWord(ATextExtent);
    end
    else
    begin
      R := cxEmptyRect;
      Result.cy := DrawText(AHandle, AText, ATextLength, R,
        DT_SINGLELINE or DT_NOPREFIX or DT_CALCRECT or DT_EXPANDTABS);
      Result.cx := R.Right - R.Left;
    end;
  end
  else
    GetTextExtentPoint32(AHandle, AText, ATextLength, Result);
end;

function IntersectClipRect(AHandle: TCanvasHandle; const R: TRect): HRGN;
begin
  Result := CreateRectRgn(0, 0, 0, 0);
  if GetClipRgn(AHandle, Result) <> 1 then
  begin
    DeleteObject(Result);
    Result := 0;
  end;
  with R do
    Windows.IntersectClipRect(AHandle, Left, Top, Right, Bottom);
end;

procedure RestoreClipRgn(AHandle: TCanvasHandle; var ARgn: HRGN);
begin
  SelectClipRgn(AHandle, ARgn);
  if ARgn <> 0 then
  begin
    DeleteObject(ARgn);
    ARgn := 0
  end;
end;

procedure cxCalcTextRowExtents(AHandle: TCanvasHandle; var ATextRow: TcxTextRow; const ATextParams: TcxTextParams);
begin
  with ATextRow do
    TextExtents := cxCalcTextExtents(AHandle, Text, TextLength, ATextParams.ExpandTabs);
end;

function cxCalcMinStringLength(AHandle: TCanvasHandle; const ATextParams: TcxTextParams;
  AText: PcxCaptionChar; ATextLength, AWidth: Integer; var ATotalLength: Integer): Integer;
var
  L, H, C: Integer;
begin
  Result := 1;
  H := ATextLength;
  L := H;

  ATotalLength := cxCalcTextExtents(AHandle, AText, L, False).cx;

  if ATotalLength / AWidth > 8 then
  begin
    Result := 1;
    ATotalLength := 0;;
    Exit;
  end
  else
    ATotalLength := cxCalcTextExtents(AHandle, AText, L, ATextParams.ExpandTabs).cx;

  while (L > 1) and (ATotalLength > AWidth) do
  begin
    L := L div 2;
    ATotalLength := cxCalcTextExtents(AHandle, AText, L, ATextParams.ExpandTabs).cx;
  end;
  while L <= H do
  begin
    Result := (L + H) shr 1;
    ATotalLength := cxCalcTextExtents(AHandle, AText, Result, ATextParams.ExpandTabs).cx;
    if L = H then
      C := 0
    else
      C := ATotalLength - AWidth;
    if C < 0 then
      L := Result + 1
    else
    begin
      H := Result - 1;
      if C = 0 then
        Break;
    end;
  end;
  if (ATotalLength > AWidth) and (Result > 1) then
  begin
    Dec(Result);
    ATotalLength := cxCalcTextExtents(AHandle, AText, Result, ATextParams.ExpandTabs).cx;
  end;
end;

procedure cxGetTextRow(AHandle: TCanvasHandle;
  var S: PcxCaptionChar;
  var ALength: Integer; AWidth: Integer; AIsLastRow: Boolean;
  const ATextParams: TcxTextParams; var ATextRow: TcxTextRow);

var
  AMinStrLen, ATotalTextWidth, I, ABreakPos: Integer;
  ASize: TSize;
  ABreakByWords, ABreakByChars, AIsSpecialProcessedRow, ACRExists: Boolean;
  ACharLen: Integer;
  AChar: PChar;
begin
  FillChar(ATextRow, SizeOf(ATextRow), 0);
  if S = nil then Exit;

  ABreakPos := -1;
  AMinStrLen := cxCalcMinStringLength(AHandle, ATextParams, S,
    ALength, Max(AWidth, 1), ATotalTextWidth);

⌨️ 快捷键说明

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