git-svn-id: https://192.168.0.254/svn/Componentes.Terceros.DevExpressVCL@63 05c56307-c608-d34a-929d-697000501d7a
1021 lines
32 KiB
ObjectPascal
1021 lines
32 KiB
ObjectPascal
{*******************************************************************}
|
|
{ }
|
|
{ Developer Express Visual Component Library }
|
|
{ ExpressPrinting System(tm) COMPONENT SUITE }
|
|
{ }
|
|
{ Copyright (C) 1998-2009 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 EXPRESSPRINTINGSYSTEM 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 dxPSRELnk;
|
|
|
|
interface
|
|
|
|
{$I cxVer.inc}
|
|
|
|
uses
|
|
Classes, Windows, Graphics, Controls, ComCtrls, RichEdit, dxPSCore, dxPSGlbl,
|
|
dxPrnPg, dxPSContainerLnk, cxDrawTextUtils;
|
|
|
|
const
|
|
dxDefaultRichEditVersion = {$IFDEF DELPHI12} 2 {$ELSE} 1 {$ENDIF};
|
|
|
|
type
|
|
TAbstractdxRichEditReportLink = class;
|
|
|
|
TdxPSCustomRichEditProducer = class(TdxPSContainerCustomWinControlProducer)
|
|
protected
|
|
function CreateImage: TGraphic; virtual;
|
|
procedure InitializeItem(AnItem: TdxReportVisualItem); override;
|
|
function ItemClass: TdxReportVisualItemClass; override;
|
|
public
|
|
function Control: TCustomRichEdit; reintroduce; overload;
|
|
class function ControlClass: TControlClass; override;
|
|
|
|
function ProducingObjectFriendlyName: string; override;
|
|
end;
|
|
|
|
TdxPSREPageRenderInfo = class(TdxPSPageRenderInfo)
|
|
public
|
|
FirstChar: Integer;
|
|
LastChar: Integer;
|
|
DetailsTwipsRect: TRect;
|
|
procedure AdjustTwipsRect; virtual;
|
|
procedure Calculate; override;
|
|
procedure CalculateBounds; override;
|
|
end;
|
|
|
|
TdxPSREReportLinkRenderInfo = class(TdxPSReportRenderInfo)
|
|
private
|
|
FDetailsTwipsRect: TRect;
|
|
FFormatRange: TFormatRange;
|
|
FPageSize: TPoint;
|
|
FPageTwipsRect: TRect;
|
|
function GetPageRenderInfo(Index: Integer): TdxPSREPageRenderInfo;
|
|
function GetREHandle: {$IFDEF BCB}Integer {$ELSE}HWND {$ENDIF};
|
|
function GetReportLink: TAbstractdxRichEditReportLink;
|
|
|
|
procedure DoFormatRichEdit;
|
|
procedure FormatRichEdit;
|
|
procedure PrepareFormatRange;
|
|
procedure SetupFormatRangeForNonSelection;
|
|
procedure UnprepareFormatRange;
|
|
protected
|
|
FirstChar: Integer;
|
|
LastChar: Integer;
|
|
|
|
procedure CalculatePageRenderInfos; override;
|
|
procedure DoCalculate; override;
|
|
procedure Refresh; override;
|
|
|
|
function GetPageRenderInfoClass: TdxPSPageRenderInfoClass; override;
|
|
function GetPageColCount: Integer; override;
|
|
function GetPageRowCount: Integer; override;
|
|
function GetPageSize: TPoint; override;
|
|
function GetUnitsPerInch: Integer; override;
|
|
function GetWindowScalePair: TdxWindowScalePair; override;
|
|
|
|
function LoMetricValueToInternalUnits(Value: Integer): Integer; override;
|
|
|
|
property PageRenderInfos[Index: Integer]: TdxPSREPageRenderInfo read GetPageRenderInfo;
|
|
property REHandle: {$IFDEF BCB}Integer {$ELSE}HWND {$ENDIF} read GetREHandle;
|
|
property ReportLink: TAbstractdxRichEditReportLink read GetReportLink;
|
|
end;
|
|
|
|
TdxPSREReportRenderer = class(TdxPSReportRenderer)
|
|
private
|
|
function GetREHandle: {$IFDEF BCB}Integer {$ELSE}HWND {$ENDIF};
|
|
function GetPageRenderInfo: TdxPSREPageRenderInfo;
|
|
function GetRenderInfo: TdxPSREReportLinkRenderInfo;
|
|
function GetReportLink: TAbstractdxRichEditReportLink;
|
|
protected
|
|
function GetUnitsPerInch: Integer; override;
|
|
procedure PrepareRects;
|
|
procedure PrepareRenderPage; override;
|
|
procedure RenderPageContent; override;
|
|
procedure UnprepareRects;
|
|
procedure UnprepareRenderPage; override;
|
|
|
|
property REHandle: {$IFDEF BCB}Integer {$ELSE}HWND {$ENDIF} read GetREHandle;
|
|
property PageRenderInfo: TdxPSREPageRenderInfo read GetPageRenderInfo;
|
|
property RenderInfo: TdxPSREReportLinkRenderInfo read GetRenderInfo;
|
|
property ReportLink: TAbstractdxRichEditReportLink read GetReportLink;
|
|
end;
|
|
|
|
TdxRichEditVersion = 1..2;
|
|
|
|
TAbstractdxRichEditReportLink = class(TBasedxReportLink, IdxPSNativeWin32ControlHandleSupport)
|
|
private
|
|
FOnlySelected: Boolean;
|
|
FRichEditVersion: TdxRichEditVersion;
|
|
function GetHasText: Boolean;
|
|
procedure SetOnlySelected(Value: Boolean);
|
|
procedure SetRichEditVersion(Value: TdxRichEditVersion);
|
|
procedure GetCharRange(var ASelStart, ASelLength: Integer);
|
|
protected
|
|
procedure ConstructReport(AReportCells: TdxReportCells); override;
|
|
procedure DoCustomDrawPageHeaderOrFooter(AHFObject: TCustomdxPageObject;
|
|
ACanvas: TCanvas; APageIndex: Integer; R: TRect;
|
|
var ADefaultDrawText, ADefaultDrawBackground: Boolean); override;
|
|
procedure DoCustomDrawPageTitle(ACanvas: TCanvas; R: TRect;
|
|
var ATextAlignX: TcxTextAlignX; var ATextAlignY: TcxTextAlignY;
|
|
var AColor: TColor; AFont: TFont; var ADone: Boolean); override;
|
|
function GetRealScaleFactor: Integer; override;
|
|
function GetRendererClass: TdxPSReportRendererClass; override;
|
|
function GetRenderInfoClass: TdxPSReportRenderInfoClass; override;
|
|
procedure InternalRestoreDefaults; override;
|
|
|
|
{ IdxPSNativeWin32ControlHandleSupport }
|
|
function GetNativeHandle: {$IFDEF BCB}Integer {$ELSE}HWND {$ENDIF};
|
|
procedure SetNativeHandle(Value: {$IFDEF BCB}Integer {$ELSE}HWND {$ENDIF});
|
|
|
|
function GetRichEditHandle: {$IFDEF BCB}Integer {$ELSE}HWND {$ENDIF}; virtual; abstract;
|
|
function TryLoadRichEditDLL(AVersion: Integer): Boolean;
|
|
|
|
property HasText: Boolean read GetHasText;
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
|
|
class function Aggregable: Boolean; override;
|
|
class function CanBeUsedAsStub: Boolean; override;
|
|
class function Serializable: Boolean; override;
|
|
function SupportsScaling: Boolean; override;
|
|
|
|
property REHandle: {$IFDEF BCB}Integer {$ELSE}HWND {$ENDIF} read GetRichEditHandle;
|
|
published
|
|
property OnlySelected: Boolean read FOnlySelected write SetOnlySelected default False;
|
|
property RichEditVersion: TdxRichEditVersion read FRichEditVersion write SetRichEditVersion default dxDefaultRichEditVersion;
|
|
end;
|
|
|
|
TCustomdxRichEditReportLink = class(TAbstractdxRichEditReportLink)
|
|
protected
|
|
function GetCustomRichEdit: TCustomRichEdit; virtual;
|
|
function GetRichEditHandle: {$IFDEF BCB}Integer {$ELSE}HWND {$ENDIF}; override;
|
|
|
|
property CustomRichEdit: TCustomRichEdit read GetCustomRichEdit;
|
|
end;
|
|
|
|
TdxRichEditReportLink = class(TCustomdxRichEditReportLink)
|
|
private
|
|
function GetRichEdit: TRichEdit;
|
|
public
|
|
property RichEdit: TRichEdit read GetRichEdit;
|
|
end;
|
|
|
|
function GetRichEditAsGraphic(AWnd: {$IFDEF BCB}Integer {$ELSE}HWND {$ENDIF};
|
|
ABkColor: TColor; const AMargins: TRect; AGraphicClass: TGraphicClass = nil; {TMetafile}
|
|
AWidth: Integer = -1; AHeight: Integer = -1; AMaxHeight: Integer = -1; ARefDC: HDC = 0): TGraphic; overload;
|
|
|
|
implementation
|
|
|
|
uses
|
|
{$IFDEF DELPHI6}
|
|
Types,
|
|
{$ENDIF}
|
|
SysUtils, Messages, Forms, dxPSUtl;
|
|
|
|
const
|
|
TextOffset = 2;
|
|
|
|
{ Helpers }
|
|
|
|
function GetTextLengthEx(AHandle: HWND; const ATextLengthEx: TGetTextLengthEx): Integer;
|
|
begin
|
|
Result := SendMessage(AHandle, EM_GETTEXTLENGTHEX, WPARAM(@ATextLengthEx), 0);
|
|
End;
|
|
|
|
{ Utilities }
|
|
|
|
function GetRichEditAsGraphic(AWnd: {$IFDEF BCB}Integer {$ELSE}HWND {$ENDIF};
|
|
ABkColor: TColor; const AMargins: TRect; AGraphicClass: TGraphicClass = nil; {TMetafile}
|
|
AWidth: Integer = -1; AHeight: Integer = -1; AMaxHeight: Integer = -1; ARefDC: HDC = 0): TGraphic;
|
|
const
|
|
TwipsPerInch = 1440;
|
|
|
|
function CalculateRichEditHeight(DC: HDC; const APPI: TPoint; AWidth: Integer;
|
|
out AMaxChars: Integer): Integer;
|
|
|
|
function CalculateCharCount: Integer;
|
|
//var
|
|
// ClsName: array[0..1023] of Char;
|
|
begin
|
|
//GetClassName(AWnd, @ClsName, 1023);
|
|
Result := SendMessage(AWnd, WM_GETTEXTLENGTH, 0, 0);
|
|
end;
|
|
|
|
function CalculateMaxHeight: Integer;
|
|
begin
|
|
Result := AMaxHeight;
|
|
if Result <> -1 then
|
|
Result := MulDiv(Result, TwipsPerInch, APPI.Y);
|
|
end;
|
|
|
|
var
|
|
CharCount, MaxHeight: Integer;
|
|
FormatRange: TFormatRange;
|
|
begin
|
|
CharCount := CalculateCharCount;
|
|
if CharCount = 0 then
|
|
begin
|
|
Result := 0;
|
|
Exit;
|
|
end;
|
|
|
|
MaxHeight := CalculateMaxHeight;
|
|
|
|
FillChar(FormatRange, SizeOf(FormatRange), 0);
|
|
if MaxHeight = -1 then
|
|
begin
|
|
Result := 0;
|
|
repeat
|
|
FormatRange.hdc := DC;
|
|
FormatRange.hdcTarget := DC;
|
|
FormatRange.rc.Right := MulDiv(AWidth - (AMargins.Left + AMargins.Right), TwipsPerInch, APPI.X);
|
|
FormatRange.rc.Bottom := TwipsPerInch;
|
|
FormatRange.rcPage := FormatRange.rc;
|
|
FormatRange.chrg.cpMax := -1;
|
|
|
|
FormatRange.chrg.cpMin := SendMessage(AWnd, EM_FORMATRANGE, 0, Longint(@FormatRange));
|
|
Inc(Result, FormatRange.rc.Bottom - FormatRange.rc.Top);
|
|
until (FormatRange.chrg.cpMin >= CharCount) or (FormatRange.chrg.cpMin = -1);
|
|
AMaxChars := -1;
|
|
end
|
|
else
|
|
begin
|
|
FormatRange.hdc := DC;
|
|
FormatRange.hdcTarget := DC;
|
|
FormatRange.rc.Right := MulDiv(AWidth - 2 * TextOffset, TwipsPerInch, APPI.X);
|
|
FormatRange.rc.Bottom := MaxHeight;
|
|
FormatRange.rcPage := FormatRange.rc;
|
|
FormatRange.chrg.cpMax := -1;
|
|
AMaxChars := SendMessage(AWnd, EM_FORMATRANGE, 0, Longint(@FormatRange));
|
|
if AMaxChars = 0 then
|
|
AMaxChars := -1;
|
|
Result := FormatRange.rc.Bottom - FormatRange.rc.Top;
|
|
end;
|
|
SendMessage(AWnd, EM_FORMATRANGE, 0, 0);
|
|
Result := MulDiv(Result, APPI.Y, TwipsPerInch) + AMargins.Top + AMargins.Bottom;
|
|
end;
|
|
|
|
function PrepareFormatRange(DC: HDC; const APPI: TPoint;
|
|
AWidth, AHeight: Integer{In Twips}; AMaxChars: Integer): TFormatRange;
|
|
|
|
function CalculateRenderBounds(const R: TRect): TRect;
|
|
begin
|
|
Result := R;
|
|
with Result do
|
|
begin
|
|
Inc(Left, MulDiv(AMargins.Left, TwipsPerInch, APPI.X));
|
|
Inc(Top, MulDiv(AMargins.Top, TwipsPerInch, APPI.Y));
|
|
Dec(Right, MulDiv(AMargins.Right, TwipsPerInch, APPI.X));
|
|
Dec(Bottom, MulDiv(AMargins.Bottom, TwipsPerInch, APPI.Y));
|
|
end;
|
|
end;
|
|
|
|
begin
|
|
FillChar(Result, SizeOf(Result), 0);
|
|
with Result do
|
|
begin
|
|
Result.hdc := DC;
|
|
Result.hdcTarget := DC;
|
|
Result.rcPage.Right := AWidth;
|
|
Result.rcPage.Bottom := AHeight;
|
|
Result.rc := CalculateRenderBounds(rcPage);
|
|
Result.chrg.cpMin := 0;
|
|
Result.chrg.cpMax := AMaxChars;
|
|
end;
|
|
end;
|
|
|
|
procedure RenderRichEdit(DC: HDC; const AFormatRange: TFormatRange);
|
|
begin
|
|
SetMapMode(DC, MM_TEXT);
|
|
SendMessage(AWnd, EM_FORMATRANGE, 0, 0);
|
|
try
|
|
SendMessage(AWnd, EM_FORMATRANGE, 1, Longint(@AFormatRange));
|
|
finally
|
|
SendMessage(AWnd, EM_FORMATRANGE, 0, 0);
|
|
end;
|
|
end;
|
|
|
|
function GetRichEditAsMetafile(DC: HDC; const APPI: TPoint; AWidth, AHeight: Integer;
|
|
AMaxChars: Integer): TMetafile;
|
|
const
|
|
HundredsMMPerInch = 2540;
|
|
var
|
|
MetaCanvas: TMetafileCanvas;
|
|
FormatRange: TFormatRange;
|
|
begin
|
|
Result := TMetafile.Create;
|
|
try
|
|
Result.MMWidth := MulDiv(AWidth, HundredsMMPerInch, APPI.X);
|
|
Result.MMHeight := MulDiv(AHeight, HundredsMMPerInch, APPI.Y);
|
|
MetaCanvas := TMetafileCanvas.Create(Result, DC);
|
|
try
|
|
MetaCanvas.Brush.Color := ABkColor;
|
|
MetaCanvas.FillRect(MakeRect(0, 0, AWidth + 1, AHeight + 1));
|
|
|
|
AWidth := MulDiv(Result.MMWidth, TwipsPerInch, HundredsMMPerInch);
|
|
AHeight := MulDiv(Result.MMHeight, TwipsPerInch, HundredsMMPerInch);
|
|
FormatRange := PrepareFormatRange(MetaCanvas.Handle, APPI, AWidth, AHeight, AMaxChars);
|
|
RenderRichEdit(MetaCanvas.Handle, FormatRange);
|
|
finally
|
|
MetaCanvas.Free;
|
|
end;
|
|
except
|
|
FreeAndNil(Result);
|
|
raise;
|
|
end;
|
|
end;
|
|
|
|
function GetRichEditAsBitmap(DC: HDC; const APPI: TPoint; AWidth, AHeight: Integer;
|
|
AMaxChars: Integer): TBitmap;
|
|
var
|
|
FormatRange: TFormatRange;
|
|
begin
|
|
Result := TBitmap.Create;
|
|
try
|
|
Result.Width := AWidth;
|
|
Result.Height := AHeight;
|
|
|
|
Result.Canvas.Brush.Color := ABkColor;
|
|
Result.Canvas.FillRect(MakeRect(0, 0, AWidth, AHeight));
|
|
|
|
AWidth := MulDiv(AWidth, TwipsPerInch, APPI.X);
|
|
AHeight := MulDiv(AHeight, TwipsPerInch, APPI.Y);
|
|
FormatRange := PrepareFormatRange(Result.Canvas.Handle, APPI, AWidth, AHeight, AMaxChars);
|
|
Result.Canvas.Handle := CreateCompatibleDC(DC);
|
|
RenderRichEdit(Result.Canvas.Handle, FormatRange);
|
|
Result.HandleType := bmDIB;
|
|
except
|
|
FreeAndNil(Result);
|
|
raise;
|
|
end;
|
|
end;
|
|
|
|
var
|
|
DC: HDC;
|
|
PPI: TPoint;
|
|
R: TRect;
|
|
W, H, MaxChars: Integer;
|
|
Bitmap: TBitmap;
|
|
begin
|
|
DC := ARefDC;
|
|
if DC = 0 then DC := GetDC(0);
|
|
try
|
|
PPI.X := GetDeviceCaps(DC, LOGPIXELSX);
|
|
PPI.Y := GetDeviceCaps(DC, LOGPIXELSY);
|
|
|
|
W := AWidth;
|
|
H := AHeight;
|
|
if (W = -1) or (H = -1) then
|
|
begin
|
|
GetWindowRect(AWnd, R);
|
|
with R do
|
|
begin
|
|
if W = -1 then W := Right - Left;
|
|
if H = -1 then H := CalculateRichEditHeight(DC, PPI, W, MaxChars);
|
|
end;
|
|
end;
|
|
|
|
if (H = 0) or (W = 0) then
|
|
begin
|
|
Result := nil;
|
|
Exit;
|
|
end;
|
|
|
|
if AGraphicClass = nil then AGraphicClass := TMetafile;
|
|
if not AGraphicClass.InheritsFrom(TMetafile) then
|
|
begin
|
|
Bitmap := GetRichEditAsBitmap(DC, PPI, W, H, MaxChars);
|
|
try
|
|
if AGraphicClass <> TBitmap then
|
|
begin
|
|
Result := dxPSUtl.CreateGraphic(AGraphicClass);
|
|
try
|
|
Result.Assign(Bitmap);
|
|
except
|
|
FreeAndNil(Bitmap);
|
|
FreeAndNil(Result);
|
|
raise;
|
|
end;
|
|
end
|
|
else
|
|
Result := Bitmap;
|
|
finally
|
|
if AGraphicClass <> TBitmap then Bitmap.Free;
|
|
end;
|
|
end
|
|
else
|
|
Result := GetRichEditAsMetafile(DC, PPI, W, H, MaxChars);
|
|
|
|
finally
|
|
if ARefDC = 0 then ReleaseDC(0, DC);
|
|
end;
|
|
end;
|
|
|
|
{ TdxPSCustomRichEditProducer }
|
|
|
|
function TdxPSCustomRichEditProducer.Control: TCustomRichEdit;
|
|
begin
|
|
Result := inherited Control as TCustomRichEdit;
|
|
end;
|
|
|
|
class function TdxPSCustomRichEditProducer.ControlClass: TControlClass;
|
|
begin
|
|
Result := TCustomRichEdit;
|
|
end;
|
|
|
|
function TdxPSCustomRichEditProducer.ProducingObjectFriendlyName: string;
|
|
begin
|
|
Result := '';
|
|
if not IsDesigning and (RichEdit_GetLines(Control).Count <> 0) then
|
|
Result := dxPSContainerLnk.dxPSMakeFriendlyNameFromStrings(RichEdit_GetLines(Control));
|
|
if Result = '' then
|
|
Result := inherited ProducingObjectFriendlyName;
|
|
end;
|
|
|
|
function TdxPSCustomRichEditProducer.CreateImage: TGraphic;
|
|
|
|
function GetMargins: TRect;
|
|
begin
|
|
Result := MakeRect(dxTextSpace, dxTextSpace, dxTextSpace, dxTextSpace);
|
|
end;
|
|
|
|
function GetMaxHeight: Integer;
|
|
begin
|
|
if Definition.OptionsPlace.ExpandHeight then
|
|
Result := -1
|
|
else
|
|
Result := Control.Height;
|
|
end;
|
|
|
|
begin
|
|
Result := GetRichEditAsGraphic(Control.Handle, Control_GetColor(Control),
|
|
GetMargins, TMetafile, Control.Width, -1, GetMaxHeight, DC);
|
|
end;
|
|
|
|
procedure TdxPSCustomRichEditProducer.InitializeItem(AnItem: TdxReportVisualItem);
|
|
var
|
|
Graphic: TGraphic;
|
|
begin
|
|
inherited;
|
|
with TdxReportCellGraphic(AnItem) do
|
|
begin
|
|
CellSides := BorderStyleMap[RichEdit_GetBorderStyle(Control)];
|
|
Color := Control_GetColor(Control);
|
|
Graphic := Self.CreateImage;
|
|
try
|
|
Image := Graphic;
|
|
finally
|
|
Graphic.Free;
|
|
end;
|
|
Transparent := False;
|
|
end;
|
|
end;
|
|
|
|
function TdxPSCustomRichEditProducer.ItemClass: TdxReportVisualItemClass;
|
|
begin
|
|
Result := TdxReportCellGraphic;
|
|
end;
|
|
|
|
{ TdxPSREPageRenderInfo }
|
|
|
|
procedure TdxPSREPageRenderInfo.AdjustTwipsRect;
|
|
begin
|
|
if HasTitle then
|
|
Inc(DetailsTwipsRect.Top, MulDiv(TitleHeight, 1440, RenderInfo.UnitsPerInch));
|
|
end;
|
|
|
|
procedure TdxPSREPageRenderInfo.Calculate;
|
|
begin
|
|
CalculateBounds;
|
|
CalculateOffsets;
|
|
end;
|
|
|
|
procedure TdxPSREPageRenderInfo.CalculateBounds;
|
|
begin
|
|
DetailBounds := PrinterPage.PaintRectPixels;
|
|
end;
|
|
|
|
{ TdxPSREReportLinkRenderInfo }
|
|
|
|
procedure TdxPSREReportLinkRenderInfo.CalculatePageRenderInfos;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
FormatRichEdit;
|
|
for I := 0 to VirtualPageCount - 1 do
|
|
PageRenderInfos[I].Calculate;
|
|
end;
|
|
|
|
procedure TdxPSREReportLinkRenderInfo.DoCalculate;
|
|
begin
|
|
FPageSize := inherited GetPageSize;
|
|
CalculateTitleBounds;
|
|
CalculateHeaderAndFooterBounds;
|
|
CalculatePageHeaderAndFooterBounds;
|
|
CalculatePageRenderInfos;
|
|
end;
|
|
|
|
procedure TdxPSREReportLinkRenderInfo.Refresh;
|
|
begin
|
|
inherited;
|
|
FillChar(FFormatRange, SizeOf(TFormatRange), 0);
|
|
FirstChar := 0;
|
|
LastChar := 0;
|
|
FDetailsTwipsRect := dxPSGlbl.NullRect;
|
|
FPageTwipsRect := dxPSGlbl.NullRect;
|
|
end;
|
|
|
|
function TdxPSREReportLinkRenderInfo.GetPageRenderInfoClass: TdxPSPageRenderInfoClass;
|
|
begin
|
|
Result := TdxPSREPageRenderInfo;
|
|
end;
|
|
|
|
function TdxPSREReportLinkRenderInfo.GetPageColCount: Integer;
|
|
begin
|
|
Result := 1;
|
|
end;
|
|
|
|
function TdxPSREReportLinkRenderInfo.GetPageRowCount: Integer;
|
|
begin
|
|
Result := VirtualPageCount;
|
|
end;
|
|
|
|
function TdxPSREReportLinkRenderInfo.GetPageSize: TPoint;
|
|
begin
|
|
Result := FPageSize;
|
|
end;
|
|
|
|
function TdxPSREReportLinkRenderInfo.GetUnitsPerInch: Integer;
|
|
begin
|
|
Result := Screen.PixelsPerInch;
|
|
end;
|
|
|
|
function TdxPSREReportLinkRenderInfo.GetWindowScalePair: TdxWindowScalePair;
|
|
begin
|
|
Result.Numerator := 100;
|
|
Result.Denominator := 100;
|
|
end;
|
|
|
|
function TdxPSREReportLinkRenderInfo.LoMetricValueToInternalUnits(Value: Integer): Integer;
|
|
begin
|
|
// We don't have to take into account the ScaleFactor
|
|
Result := MulDiv(Value, UnitsPerInch, 254);
|
|
end;
|
|
|
|
function TdxPSREReportLinkRenderInfo.GetPageRenderInfo(Index: Integer): TdxPSREPageRenderInfo;
|
|
begin
|
|
Result := inherited PageRenderInfos[Index] as TdxPSREPageRenderInfo;
|
|
end;
|
|
|
|
function TdxPSREReportLinkRenderInfo.GetREHandle: {$IFDEF BCB}Integer {$ELSE}HWND {$ENDIF};
|
|
begin
|
|
Result := ReportLink.REHandle;
|
|
end;
|
|
|
|
function TdxPSREReportLinkRenderInfo.GetReportLink: TAbstractdxRichEditReportLink;
|
|
begin
|
|
Result := inherited ReportLink as TAbstractdxRichEditReportLink;
|
|
end;
|
|
|
|
procedure TdxPSREReportLinkRenderInfo.DoFormatRichEdit;
|
|
var
|
|
PageRenderInfo: TdxPSREPageRenderInfo;
|
|
begin
|
|
VirtualPageCount := 0;
|
|
repeat
|
|
PageRenderInfo := CreatePageRenderInfo(VirtualPageCount) as TdxPSREPageRenderInfo;
|
|
if VirtualPageCount = 0 then
|
|
PageRenderInfo.FirstChar := FirstChar
|
|
else
|
|
PageRenderInfo.FirstChar := PageRenderInfos[VirtualPageCount - 1].LastChar;
|
|
|
|
FFormatRange.chrg.cpMin := PageRenderInfo.FirstChar;
|
|
FFormatRange.rcPage := FPageTwipsRect;
|
|
|
|
PageRenderInfo.DetailsTwipsRect := FDetailsTwipsRect;
|
|
PageRenderInfo.AdjustTwipsRect;
|
|
FFormatRange.rc := PageRenderInfo.DetailsTwipsRect;
|
|
|
|
PageRenderInfo.LastChar := SendMessage(REHandle, EM_FORMATRANGE, 0, Longint(@FFormatRange));
|
|
if PageRenderInfo.LastChar > LastChar then
|
|
PageRenderInfo.LastChar := LastChar;
|
|
Inc(VirtualPageCount);
|
|
|
|
until (PageRenderInfo.LastChar >= LastChar) or (PageRenderInfo.LastChar = -1);
|
|
end;
|
|
|
|
procedure TdxPSREReportLinkRenderInfo.FormatRichEdit;
|
|
begin
|
|
PrepareFormatRange;
|
|
try
|
|
if LastChar > 0 then
|
|
DoFormatRichEdit;
|
|
finally
|
|
UnprepareFormatRange;
|
|
end;
|
|
end;
|
|
|
|
procedure TdxPSREReportLinkRenderInfo.PrepareFormatRange;
|
|
var
|
|
SelStart, SelLength: Integer;
|
|
begin
|
|
FPageTwipsRect.BottomRight := ScalePoint(PrinterPage.RealPageSizeLoMetric, 1440, 254);
|
|
FDetailsTwipsRect := ScaleRect(PrinterPage.PaintRectLoMetric, 1440, 254, 1440, 254);
|
|
|
|
ReportLink.GetCharRange(SelStart, SelLength);
|
|
if SelLength <> 0 then
|
|
begin
|
|
FirstChar := SelStart;
|
|
LastChar := SelStart + SelLength;
|
|
end
|
|
else
|
|
SetupFormatRangeForNonSelection;
|
|
|
|
with FFormatRange do
|
|
begin
|
|
hDC := GetDC(0);
|
|
hdcTarget := hDC;
|
|
rc := FDetailsTwipsRect;
|
|
rcPage := FPageTwipsRect;
|
|
if SelLength = 0 then
|
|
chrg.cpMax := -1
|
|
else
|
|
chrg.cpMax := LastChar;
|
|
end;
|
|
|
|
SendMessage(REHandle, EM_FORMATRANGE, 0, 0);
|
|
end;
|
|
|
|
procedure TdxPSREReportLinkRenderInfo.SetupFormatRangeForNonSelection;
|
|
var
|
|
TextLenEx: TGetTextLengthEx;
|
|
begin
|
|
FirstChar := 0;
|
|
if ReportLink.RichEditVersion > 1 then
|
|
begin
|
|
with TextLenEx do
|
|
begin
|
|
Flags := GTL_DEFAULT;
|
|
CodePage := CP_ACP;
|
|
end;
|
|
LastChar := GetTextLengthEx(REHandle, TextLenEx);
|
|
end
|
|
else
|
|
LastChar := SendMessage(REHandle, WM_GETTEXTLENGTH, 0, 0);
|
|
end;
|
|
|
|
procedure TdxPSREReportLinkRenderInfo.UnprepareFormatRange;
|
|
begin
|
|
SendMessage(REHandle, EM_FORMATRANGE, 0, 0);
|
|
ReleaseDC(0, FFormatRange.hDC);
|
|
end;
|
|
|
|
{ TdxPSREReportLinkRenderInfo }
|
|
|
|
function TdxPSREReportRenderer.GetUnitsPerInch: Integer;
|
|
begin
|
|
if IsPrinterDC(DC) then
|
|
Result := PPI
|
|
else
|
|
Result := inherited GetUnitsPerInch;
|
|
end;
|
|
|
|
procedure TdxPSREReportRenderer.PrepareRects;
|
|
begin
|
|
with RenderInfo do
|
|
begin
|
|
FPageSize.X := MulDiv(FPageSize.X, PPI, UnitsPerInch);
|
|
FPageSize.Y := MulDiv(FPageSize.Y, PPI, UnitsPerInch);
|
|
PageHeaderBounds := ScaleRect(PageHeaderBounds, PPI, UnitsPerInch, PPI, UnitsPerInch);
|
|
PageFooterBounds := ScaleRect(PageFooterBounds, PPI, UnitsPerInch, PPI, UnitsPerInch);
|
|
TitleBounds := ScaleRect(TitleBounds, PPI, UnitsPerInch, PPI, UnitsPerInch);
|
|
PageRenderInfo.TitleOffset := ScalePoint(PageRenderInfo.TitleOffset, PPI, UnitsPerInch);
|
|
end;
|
|
end;
|
|
|
|
procedure TdxPSREReportRenderer.PrepareRenderPage;
|
|
begin
|
|
PrepareRects;
|
|
inherited;
|
|
end;
|
|
|
|
procedure TdxPSREReportRenderer.RenderPageContent;
|
|
var
|
|
FormatRange: TFormatRange;
|
|
ClipRect: TRect;
|
|
Rgn: HRGN;
|
|
LastChar: Integer;
|
|
begin
|
|
FillChar(FormatRange, SizeOf(TFormatRange), 0);
|
|
with FormatRange do
|
|
begin
|
|
hDC := DC;
|
|
hdcTarget := DC;{3.1}
|
|
rc := PageRenderInfo.DetailsTwipsRect;
|
|
rcPage := RenderInfo.FPageTwipsRect;
|
|
chrg.cpMin := PageRenderInfo.FirstChar;
|
|
chrg.cpMax := PageRenderInfo.LastChar;
|
|
end;
|
|
|
|
ClipRect := ScaleRect(PageRenderInfo.DetailBounds, PPI, RenderInfo.UnitsPerInch, PPI, RenderInfo.UnitsPerInch);
|
|
|
|
Rgn := IntersectClipRect(ClipRect);
|
|
|
|
SendMessage(REHandle, EM_FORMATRANGE, 0, 0);
|
|
try
|
|
LastChar := SendMessage(REHandle, EM_FORMATRANGE, 1, Longint(@FormatRange));
|
|
|
|
if PageRenderInfo.LastChar <> LastChar then
|
|
begin
|
|
PageRenderInfo.LastChar := LastChar;
|
|
if RenderingPageIndex < RenderInfo.VirtualPageCount - 1 then
|
|
RenderInfo.PageRenderInfos[RenderingPageIndex + 1].FirstChar := LastChar;
|
|
|
|
// Small trick: because Print output does not equal Preview output,
|
|
// we should invalidate Preview window after Print-Out
|
|
if IsPrinterDC(DC) and ReportLink.ComponentPrinter.PreviewExists then
|
|
ReportLink.ComponentPrinter.PreviewWindow.InvalidatePage(RenderingPageIndex);
|
|
end;
|
|
finally
|
|
SendMessage(REHandle, EM_FORMATRANGE, 0, 0);
|
|
end;
|
|
|
|
RestoreClipRgn(Rgn);
|
|
end;
|
|
|
|
procedure TdxPSREReportRenderer.UnprepareRects;
|
|
begin
|
|
with RenderInfo do
|
|
begin
|
|
FPageSize.X := MulDiv(FPageSize.X, UnitsPerInch, PPI);
|
|
FPageSize.Y := MulDiv(FPageSize.Y, UnitsPerInch, PPI);
|
|
PageHeaderBounds := ScaleRect(PageHeaderBounds, UnitsPerInch, PPI, UnitsPerInch, PPI);
|
|
PageFooterBounds := ScaleRect(PageFooterBounds, UnitsPerInch, PPI, UnitsPerInch, PPI);
|
|
TitleBounds := ScaleRect(TitleBounds, UnitsPerInch, PPI, UnitsPerInch, PPI);
|
|
PageRenderInfo.TitleOffset := ScalePoint(PageRenderInfo.TitleOffset, UnitsPerInch, PPI);
|
|
end;
|
|
end;
|
|
|
|
procedure TdxPSREReportRenderer.UnprepareRenderPage;
|
|
begin
|
|
inherited;
|
|
UnprepareRects;
|
|
end;
|
|
|
|
function TdxPSREReportRenderer.GetREHandle: {$IFDEF BCB}Integer {$ELSE}HWND {$ENDIF};
|
|
begin
|
|
Result := ReportLink.REHandle;
|
|
end;
|
|
|
|
function TdxPSREReportRenderer.GetPageRenderInfo: TdxPSREPageRenderInfo;
|
|
begin
|
|
Result := inherited PageRenderInfo as TdxPSREPageRenderInfo;
|
|
end;
|
|
|
|
function TdxPSREReportRenderer.GetRenderInfo: TdxPSREReportLinkRenderInfo;
|
|
begin
|
|
Result := inherited RenderInfo as TdxPSREReportLinkRenderInfo;
|
|
end;
|
|
|
|
function TdxPSREReportRenderer.GetReportLink: TAbstractdxRichEditReportLink;
|
|
begin
|
|
Result := inherited ReportLink as TAbstractdxRichEditReportLink;
|
|
end;
|
|
|
|
{ TAbstractdxRichEditReportLink }
|
|
|
|
constructor TAbstractdxRichEditReportLink.Create(AOwner: TComponent);
|
|
begin
|
|
inherited;
|
|
FRichEditVersion := dxDefaultRichEditVersion;
|
|
end;
|
|
|
|
class function TAbstractdxRichEditReportLink.Aggregable: Boolean;
|
|
begin
|
|
Result := False;
|
|
end;
|
|
|
|
class function TAbstractdxRichEditReportLink.CanBeUsedAsStub: Boolean;
|
|
begin
|
|
Result := False;
|
|
end;
|
|
|
|
class function TAbstractdxRichEditReportLink.Serializable: Boolean;
|
|
begin
|
|
Result := False;
|
|
end;
|
|
|
|
function TAbstractdxRichEditReportLink.SupportsScaling: Boolean;
|
|
begin
|
|
Result := False;
|
|
end;
|
|
|
|
procedure TAbstractdxRichEditReportLink.ConstructReport(AReportCells: TdxReportCells);
|
|
begin
|
|
end;
|
|
|
|
procedure TAbstractdxRichEditReportLink.DoCustomDrawPageHeaderOrFooter(
|
|
AHFObject: TCustomdxPageObject; ACanvas: TCanvas; APageIndex: Integer;
|
|
R: TRect; var ADefaultDrawText, ADefaultDrawBackground: Boolean);
|
|
var
|
|
APixelsNumerator: Integer;
|
|
begin
|
|
APixelsNumerator := Renderer.PPI;
|
|
DoParentCustomDrawPageHeaderOrFooter(AHFObject, ACanvas, APageIndex, R,
|
|
ADefaultDrawText, ADefaultDrawBackground, APixelsNumerator);
|
|
if ADefaultDrawText or ADefaultDrawBackground then
|
|
if AHFObject is TdxPageHeader then
|
|
begin
|
|
if Assigned(OnCustomDrawPageHeader) then
|
|
OnCustomDrawPageHeader(Self, ACanvas, APageIndex, R,
|
|
APixelsNumerator, PixelsDenominator, ADefaultDrawText,
|
|
ADefaultDrawBackground)
|
|
end
|
|
else
|
|
if Assigned(OnCustomDrawPageFooter) then
|
|
OnCustomDrawPageFooter(Self, ACanvas, APageIndex, R,
|
|
APixelsNumerator, PixelsDenominator, ADefaultDrawText,
|
|
ADefaultDrawBackground);
|
|
end;
|
|
|
|
procedure TAbstractdxRichEditReportLink.DoCustomDrawPageTitle(ACanvas: TCanvas;
|
|
R: TRect; var ATextAlignX: TcxTextAlignX; var ATextAlignY: TcxTextAlignY;
|
|
var AColor: TColor; AFont: TFont; var ADone: Boolean);
|
|
var
|
|
APixelsNumerator: Integer;
|
|
begin
|
|
APixelsNumerator := Renderer.PPI;
|
|
DoParentCustomDrawReportTitle(ACanvas, R, ATextAlignX, ATextAlignY,
|
|
AColor, AFont, ADone, APixelsNumerator);
|
|
if not ADone and Assigned(OnCustomDrawReportLinkTitle) then
|
|
OnCustomDrawReportLinkTitle(Self, ACanvas, R, APixelsNumerator,
|
|
PixelsDenominator, ATextAlignX, ATextAlignY, AColor, AFont, ADone);
|
|
end;
|
|
|
|
function TAbstractdxRichEditReportLink.GetRealScaleFactor: Integer;
|
|
begin
|
|
Result := 100;
|
|
end;
|
|
|
|
function TAbstractdxRichEditReportLink.GetRendererClass: TdxPSReportRendererClass;
|
|
begin
|
|
Result := TdxPSREReportRenderer;
|
|
end;
|
|
|
|
function TAbstractdxRichEditReportLink.GetRenderInfoClass: TdxPSReportRenderInfoClass;
|
|
begin
|
|
Result := TdxPSREReportLinkRenderInfo;
|
|
end;
|
|
|
|
procedure TAbstractdxRichEditReportLink.InternalRestoreDefaults;
|
|
begin
|
|
inherited;
|
|
OnlySelected := False;
|
|
end;
|
|
|
|
{ IdxPSNativeWin32ControlHandleSupport }
|
|
|
|
function TAbstractdxRichEditReportLink.GetNativeHandle: {$IFDEF BCB}Integer {$ELSE}HWND {$ENDIF};
|
|
begin
|
|
Result := REHandle;
|
|
end;
|
|
|
|
procedure TAbstractdxRichEditReportLink.SetNativeHandle(Value: {$IFDEF BCB}Integer {$ELSE}HWND {$ENDIF});
|
|
begin
|
|
end;
|
|
|
|
function TAbstractdxRichEditReportLink.TryLoadRichEditDLL(AVersion: Integer): Boolean;
|
|
const
|
|
REVersions: array[Boolean] of string = ('RICHED32.DLL', 'RICHED20.DLL');
|
|
var
|
|
OldError: Longint;
|
|
LibHandle: THandle;
|
|
begin
|
|
OldError := SetErrorMode(SEM_NOOPENFILEERRORBOX);
|
|
try
|
|
LibHandle := LoadLibrary(PChar(REVersions[AVersion > 1]));
|
|
try
|
|
if (LibHandle > 0) and (LibHandle < HINSTANCE_ERROR) then
|
|
LibHandle := 0;
|
|
Result := LibHandle <> 0;
|
|
finally
|
|
if LibHandle <> 0 then FreeLibrary(LibHandle);
|
|
end;
|
|
finally
|
|
SetErrorMode(OldError);
|
|
end;
|
|
end;
|
|
|
|
function TAbstractdxRichEditReportLink.GetHasText: Boolean;
|
|
begin
|
|
Result := (REHandle <> 0) and (SendMessage(REHandle, WM_GETTEXTLENGTH, 0, 0) > 0);
|
|
end;
|
|
|
|
procedure TAbstractdxRichEditReportLink.SetOnlySelected(Value: Boolean);
|
|
begin
|
|
if FOnlySelected <> Value then
|
|
begin
|
|
FOnlySelected := Value;
|
|
LinkModified(True);
|
|
end;
|
|
end;
|
|
|
|
procedure TAbstractdxRichEditReportLink.SetRichEditVersion(Value: TdxRichEditVersion);
|
|
begin
|
|
if FRichEditVersion <> Value then
|
|
if TryLoadRichEditDLL(Value) then
|
|
begin
|
|
FRichEditVersion := Value;
|
|
LinkModified(True);
|
|
end;
|
|
end;
|
|
|
|
procedure TAbstractdxRichEditReportLink.GetCharRange(var ASelStart, ASelLength: Integer);
|
|
var
|
|
CharRange: TCharRange;
|
|
begin
|
|
ASelStart := 0;
|
|
ASelLength := 0;
|
|
if (REHandle <> 0) and OnlySelected and HasText then
|
|
begin
|
|
SendMessage(REHandle, EM_EXGETSEL, 0, Longint(@CharRange));
|
|
ASelStart := CharRange.cpMin;
|
|
ASelLength := CharRange.cpMax - CharRange.cpMin;
|
|
end;
|
|
end;
|
|
|
|
{ TCustomdxRichEditReportLink }
|
|
|
|
function TCustomdxRichEditReportLink.GetCustomRichEdit: TCustomRichEdit;
|
|
begin
|
|
Result := TCustomRichEdit(Component);
|
|
end;
|
|
|
|
function TCustomdxRichEditReportLink.GetRichEditHandle: {$IFDEF BCB}Integer {$ELSE}HWND {$ENDIF};
|
|
begin
|
|
if CustomRichEdit <> nil then
|
|
begin
|
|
CustomRichEdit.HandleNeeded;
|
|
Result := CustomRichEdit.Handle;
|
|
end
|
|
else
|
|
Result := 0;
|
|
end;
|
|
|
|
{ TdxRichEditReportLink }
|
|
|
|
function TdxRichEditReportLink.GetRichEdit: TRichEdit;
|
|
begin
|
|
Result := inherited Component as TRichEdit;
|
|
end;
|
|
|
|
{ Assistants }
|
|
|
|
procedure RegisterProducers;
|
|
begin
|
|
TdxPSCustomRichEditProducer.Register;
|
|
end;
|
|
|
|
procedure UnregisterProducers;
|
|
begin
|
|
TdxPSCustomRichEditProducer.Unregister;
|
|
end;
|
|
|
|
initialization
|
|
dxPSRegisterReportLink(TdxRichEditReportLink, TRichEdit, nil);
|
|
RegisterProducers;
|
|
|
|
finalization
|
|
UnregisterProducers;
|
|
dxPSUnregisterReportLink(TdxRichEditReportLink, TRichEdit, nil);
|
|
|
|
end.
|