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 + -
显示快捷键?