Componentes.Terceros.DevExp.../internal/x.44/1/ExpressPrinting System/Sources/dxBkgnd.pas
2009-06-29 12:09:02 +00:00

548 lines
18 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 dxBkGnd;
interface
{$I cxVer.inc}
uses
Windows, Classes, SysUtils, Controls, Graphics, dxBase, dxPSGlbl, dxPSUtl;
type
TdxPicturePaintMode = (ppmCenter, ppmStretch, ppmTile, ppmProportional);
TdxBackgroundMode = (bmNone, bmBrush, bmBrushBitmap, bmPicture);
TdxBackgroundParam = (bpBkColor, bpBrush, bpMode, bpPictureMode, bpPicture);
TdxBackgroundParams = set of TdxBackgroundParam;
TdxPaintSequence = (psBefore, psAfter);
TdxBackgroundChangeEvent = procedure(Sender: TObject; AChangeWhat: TdxBackgroundParams) of object;
TCustomdxBackgroundPaintEvent = procedure(Sender: TObject; Canvas: TCanvas;
Rect: TRect; ASequence: TdxPaintSequence; var ADone: Boolean) of object;
TCustomdxBackgroundPaintExEvent = procedure(Sender: TObject; Canvas: TCanvas;
Rect: TRect; ASequence: TdxPaintSequence; PixelsNumerator,
PixelsDenominator: Integer; var ADone: Boolean) of object;
TdxBackgroundClass = class of TdxBackground;
TdxBackground = class(TdxBaseObject)
private
FBkColor: TColor;
FBrush: TBrush;
FIsRepaintNeeded: Boolean;
FMode: TdxBackgroundMode;
FPicture: TGraphic;
FPictureMode: TdxPicturePaintMode;
FOnApply: TNotifyEvent;
FOnChange: TdxBackgroundChangeEvent;
FOnPaint: TCustomdxBackgroundPaintEvent;
FOnPaintEx: TCustomdxBackgroundPaintExEvent;
function GetPicture: TGraphic;
procedure SetBkColor(Value: tColor);
procedure SetBrush(Value: TBrush);
procedure SetMode(Value: TdxBackgroundMode);
procedure SetPicture(Value: TGraphic);
procedure SetPictureMode(Value: TdxPicturePaintMode);
procedure BrushChanged(Sender: TObject);
procedure PictureChanged(Sender: TObject);
protected
procedure DoAssign(Source: TdxBaseObject); override;
procedure DoRestoreDefaults; override;
procedure DoApply; dynamic;
procedure DoChange(AChangeWhats: TdxBackgroundParams); dynamic;
procedure DoPaint(ACanvas: TCanvas; Rect: TRect; Sequence: TdxPaintSequence;
var ADone: Boolean); virtual;
procedure DoPaintEx(ACanvas: TCanvas; Rect: TRect; Sequence: TdxPaintSequence;
PixelsNumerator, PixelsDenominator: Integer; var ADone: Boolean); virtual;
procedure LockUpdate(ALockState : TdxLockState); override;
function RepaintNeeded(AChangeWhats: TdxBackgroundParams): Boolean; virtual;
property OnApply: TNotifyEvent read FOnApply write FOnApply;
public
constructor Create; override;
destructor Destroy; override;
procedure Clear; virtual;
function IsEmpty: Boolean; override;
function IsEqual(ABaseObject: TdxBaseObject): Boolean; override;
procedure Paint(ACanvas: TCanvas; const R: TRect); virtual;
procedure PaintEx(ACanvas: TCanvas; const R: TRect;
PixelsNumerator, PixelsDenominator: Integer); virtual;
function SetupEffects: Boolean;
property IsRepaintNeeded: Boolean read FIsRepaintNeeded;
property OnChange: TdxBackgroundChangeEvent read FOnChange write FOnChange;
property OnPaint: TCustomdxBackgroundPaintEvent read FOnPaint write FOnPaint;
property OnPaintEx: TCustomdxBackgroundPaintExEvent read FOnPaintEx write FOnPaintEx;
published
property BkColor: TColor read FBkColor write SetBkColor default clWhite;
property Brush: TBrush read FBrush write SetBrush;
property Mode: TdxBackgroundMode read FMode write SetMode default bmNone;
property Picture: TGraphic read GetPicture write SetPicture;
property PictureMode: TdxPicturePaintMode read FPictureMode write SetPictureMode default ppmCenter;
end;
procedure DrawPicture(APicture: TGraphic; ACanvas: TCanvas; const ARect: TRect;
APictureMode: TdxPicturePaintMode; PixelsNumerator, PixelsDenominator: Integer;
AnOffsetX: Integer = 0; AnOffsetY: Integer = 0);
const
cwAll: TdxBackgroundParams = [bpBkColor..bpPicture];
implementation
uses
dxFEFDlg;
constructor TdxBackground.Create;
begin
inherited;
FBkColor := clWhite;
FBrush := TBrush.Create;
FBrush.OnChange := BrushChanged;
FMode := bmNone;
FPictureMode := ppmCenter;
FPicture := TBitmap.Create;
FPicture.OnChange := PictureChanged;
end;
destructor TdxBackground.Destroy;
begin
FreeAndNil(FPicture);
FreeAndNil(FBrush);
inherited;
end;
procedure TdxBackground.Clear;
begin
Brush.Color := clWhite;
Mode := bmNone;
Picture := nil;
end;
function TdxBackground.IsEmpty: Boolean;
begin
case Mode of
bmBrush:
Result := Brush.Style = bsClear;
bmBrushBitmap,
bmPicture:
Result := (Picture = nil) or Picture.Empty;
else //bmNone
Result := True;
end;
end;
function TdxBackground.IsEqual(ABaseObject: TdxBaseObject): Boolean;
begin
Result := inherited IsEqual(ABaseObject);
if Result then
with TdxBackground(ABaseObject) do
Result :=
(Self.BkColor = BkColor) and
(Self.Mode = Mode) and
(Self.PictureMode = PictureMode) and
dxAreBrushesEqual(Self.Brush, Brush) and
dxAreGraphicsEqual(Self.Picture, Picture);
end;
procedure TdxBackground.Paint(ACanvas: TCanvas; const R: TRect);
begin
PaintEx(ACanvas, R, 1, 1);
end;
procedure TdxBackground.PaintEx(ACanvas: TCanvas; const R: TRect;
PixelsNumerator, PixelsDenominator: Integer);
var
PrevColor: COLORREF;
PrevBkMode: Integer;
PrevBrush: TBrush;
Done: Boolean;
DC: HDC;
Pattern: TBitmap;
begin
Done := False;
DoPaintEx(ACanvas, R, psBefore, PixelsNumerator, PixelsDenominator, Done);
if Done then Exit;
DC := ACanvas.Handle;
case Mode of
bmNone: ;
bmBrush:
if Brush.Style <> bsClear then
begin
if Brush.Style > bsClear then {hatched brush}
begin
PrevBkMode := SetBkMode(DC, Windows.TRANSPARENT);
PrevColor := Windows.SetBkColor(DC, ColorToRGB(BkColor));
end
else {bsSolid}
begin
PrevBkMode := GetBkMode(DC);
PrevColor := COLORREF(0);
end;
if (Brush.Style > bsClear) and IsPrinterDC(DC) then {hatched Brush}
begin
Pattern := TBitmap.Create;
with Pattern do
try
Width := 8;
Height := 8;
Canvas.Brush := Self.Brush;
SetBkMode(DC, Windows.TRANSPARENT);
Windows.SetBkColor(DC, ColorToRGB(BkColor));
Canvas.FillRect(Rect(0, 0, Width, Height));
DrawPicture(Pattern, ACanvas, R, ppmTile, PixelsNumerator, PixelsDenominator);
finally
Free;
end;
end
else
FillRect(DC, R, Brush.Handle);
if Brush.Style > bsClear then
begin
Windows.SetBkColor(DC, PrevColor);
SetBkMode(DC, PrevBkMode);
end;
end;
bmBrushBitmap:
if Picture <> nil then
if (Picture.Width <= 8) and (Picture.Height <= 8) and not IsPrinterDC(DC) then
begin
PrevBrush := TBrush.Create;
try
PrevBrush.Assign(ACanvas.Brush);
ACanvas.Brush.Bitmap := TBitmap(Picture);
ACanvas.FillRect(R);
ACanvas.Brush.Bitmap := nil;
ACanvas.Brush := PrevBrush;
finally
PrevBrush.Free;
end;
end
else
DrawPicture(Picture, ACanvas, R, ppmTile, PixelsNumerator, PixelsDenominator);
bmPicture:
if Picture <> nil then
if (PictureMode = ppmTile) and (Picture.Width <= 8) and (Picture.Height <= 8) and not IsPrinterDC(DC) then
begin
PrevBrush := TBrush.Create;
try
PrevBrush.Assign(ACanvas.Brush);
ACanvas.Brush.Bitmap := TBitmap(Picture);
ACanvas.FillRect(R);
ACanvas.Brush.Bitmap := nil;
ACanvas.Brush := PrevBrush;
finally
PrevBrush.Free;
end;
end
else
DrawPicture(Picture, ACanvas, R, PictureMode, PixelsNumerator, PixelsDenominator);
end;
DoPaintEx(ACanvas, R, psAfter, PixelsNumerator, PixelsDenominator, Done);
end;
function TdxBackground.SetupEffects: Boolean;
begin
Result := dxFEFDialog(Self);
end;
procedure TdxBackground.DoAssign(Source: TdxBaseObject);
begin
inherited;
with Source as TdxBackground do
begin
Self.BkColor := BkColor;
Self.Brush := Brush;
Self.Mode := Mode;
Self.PictureMode := PictureMode;
Self.Picture := Picture;
end;
end;
procedure TdxBackground.DoRestoreDefaults;
begin
inherited;
FBkColor := clWhite;
FMode := bmNone;
FPictureMode := ppmCenter;
end;
procedure TdxBackground.DoApply;
begin
if Assigned(FOnApply) then FOnApply(Self);
end;
procedure TdxBackground.DoChange(AChangeWhats: TdxBackgroundParams);
begin
if not IsLocked then
begin
FIsRepaintNeeded := RepaintNeeded(AChangeWhats);
if Assigned(FOnChange) then FOnChange(Self, AChangeWhats);
end;
end;
procedure TdxBackground.DoPaint(ACanvas: TCanvas; Rect: TRect;
Sequence: TdxPaintSequence; var ADone: Boolean);
begin
if Assigned(FOnPaint) then FOnPaint(Self, ACanvas, Rect, Sequence, ADone);
end;
procedure TdxBackground.DoPaintEx(ACanvas: TCanvas; Rect: TRect;
Sequence: TdxPaintSequence; PixelsNumerator, PixelsDenominator: Integer;
var ADone: Boolean);
begin
if Assigned(FOnPaintEx) then
FOnPaintEx(Self, ACanvas, Rect, Sequence, PixelsNumerator, PixelsDenominator, ADone);
if not ADone then
DoPaint(ACanvas, Rect, Sequence, ADone);
end;
procedure TdxBackground.LockUpdate(ALockState : TdxLockState);
begin
if ALockState = lsUnLock then DoChange(cwAll);
inherited LockUpdate(ALockState);
end;
function TdxBackground.RepaintNeeded(AChangeWhats: TdxBackgroundParams): Boolean;
begin
if bpMode in AChangeWhats then
Result := True
else
case Mode of
bmBrush:
Result := (bpBrush in AChangeWhats) or ((bpBkColor in AChangeWhats) and (Brush.Style > bsClear));
bmBrushBitmap:
Result := bpPicture in AChangeWhats;
bmPicture:
Result := [bpPicture, bpPictureMode] * AChangeWhats <> [];
else
Result := False;
end;
end;
procedure TdxBackground.BrushChanged(Sender: TObject);
begin
DoChange([bpBrush]);
end;
procedure TdxBackground.PictureChanged(Sender: TObject);
begin
DoChange([bpPicture]);
end;
procedure TdxBackground.SetBkColor(Value: tColor);
begin
if FBkColor <> Value then
begin
FBkColor := Value;
DoChange([bpBkColor]);
end;
end;
procedure TdxBackground.SetBrush(Value: TBrush);
begin
FBrush.Assign(Value);
end;
procedure TdxBackground.SetMode(Value: TdxBackgroundMode);
begin
if FMode <> Value then
begin
FMode := Value;
DoChange([bpMode]);
end;
end;
function TdxBackground.GetPicture: TGraphic;
begin
if FPicture = nil then FPicture := TBitmap.Create;
Result := FPicture;
end;
procedure TdxBackground.SetPicture(Value: TGraphic);
begin
if Value <> nil then
begin
Picture.Assign(Value);
TBitmap(Picture).HandleType := bmDIB;
end
else
if FPicture <> nil then
begin
TBitmap(FPicture).FreeImage;
TBitmap(FPicture).ReleaseHandle;
end;
end;
procedure TdxBackground.SetPictureMode(Value: TdxPicturePaintMode);
begin
if FPictureMode <> Value then
begin
FPictureMode := Value;
DoChange([bpPictureMode]);
end;
end;
{ utility routines }
function IsGraphicVisible(DC: HDC; const R: TRect): Boolean;
begin
Result := IsPrinterDC(DC) or IsMetafileDC(DC) or RectVisible(DC, R);
end;
procedure DrawGraphicCenter(AGraphic: TGraphic; ACanvas: TCanvas; const ARect: TRect;
PixelsNumerator, PixelsDenominator: Integer);
var
DC: HDC;
W, H: Integer;
R: TRect;
begin
DC := ACanvas.Handle;
with ARect, AGraphic do
begin
W := MulDiv(Width, PixelsNumerator, PixelsDenominator);
H := MulDiv(Height, PixelsNumerator, PixelsDenominator);
R := Bounds(Left + (Right - Left - W) div 2, Top + (Bottom - Top - H) div 2, W, H);
if IsGraphicVisible(DC, R) then
if (W <> Width) or (H <> Height) then
ACanvas.StretchDraw(R, AGraphic)
else
ACanvas.Draw(R.Left, R.Top, AGraphic);
end;
end;
procedure DrawGraphicStretch(AGraphic: TGraphic; ACanvas: TCanvas; const ARect: TRect;
PixelsNumerator, PixelsDenominator: Integer);
begin
if IsGraphicVisible(ACanvas.Handle, ARect) then
ACanvas.StretchDraw(ARect, AGraphic);
end;
procedure DrawGraphicTile(AGraphic: TGraphic; ACanvas: TCanvas; const ARect: TRect;
PixelsNumerator, PixelsDenominator: Integer; AnOffsetX: Integer = 0; AnOffsetY: Integer = 0);
var
DC: HDC;
I, J, W, H: Integer;
Rgn: HRGN;
R: TRect;
begin
DC := ACanvas.Handle;
with ARect, AGraphic do
begin
W := MulDiv(Width, PixelsNumerator, PixelsDenominator);
H := MulDiv(Height, PixelsNumerator, PixelsDenominator);
AnOffsetX := AnOffsetX mod W;
AnOffsetY := AnOffsetY mod H;
Rgn := dxPSUtl.IntersectClipRect(DC, ARect);
for I := 0 to (Right - Left - AnOffsetX) div W do
for J := 0 to (Bottom - Top - AnOffsetX) div H do
begin
R := Bounds(Left + I * W + AnOffsetX, Top + J * H + AnOffsetY, W, H);
if IsGraphicVisible(DC, R) then
if (W <> Width) or (H <> Height) then
ACanvas.StretchDraw(R, AGraphic)
else
ACanvas.Draw(R.Left, R.Top, AGraphic);
end;
dxPSUtl.RestoreClipRgn(DC, Rgn);
end;
end;
procedure DrawGraphicStretchProportional(AGraphic: TGraphic; ACanvas: TCanvas; const ARect: TRect;
PixelsNumerator, PixelsDenominator: Integer);
var
DC: HDC;
W, H, V: Integer;
R: TRect;
begin
DC := ACanvas.Handle;
with ARect, AGraphic do
begin
W := Right - Left;
H := Bottom - Top;
if Width / Height > W / H then
begin
V := MulDiv(Height, W, Width);
R := Bounds(Left, Top + (H - V) div 2, W, V);
end
else
begin
V := MulDiv(Width, H, Height);
R := Bounds(Left + (W - V) div 2, Top, V, H);
end;
if IsGraphicVisible(DC, R) then
ACanvas.StretchDraw(R, AGraphic);
end;
end;
procedure DrawPicture(APicture: TGraphic; ACanvas: TCanvas; const ARect: TRect;
APictureMode: TdxPicturePaintMode; PixelsNumerator, PixelsDenominator: Integer;
AnOffsetX: Integer = 0; AnOffsetY: Integer = 0);
begin
if APicture.Empty or (APicture.Width = 0) or (APicture.Height = 0) then Exit;
case APictureMode of
ppmCenter:
DrawGraphicCenter(APicture, ACanvas, ARect, PixelsNumerator, PixelsDenominator);
ppmStretch:
DrawGraphicStretch(APicture, ACanvas, ARect, PixelsNumerator, PixelsDenominator);
ppmTile:
DrawGraphicTile(APicture, ACanvas, ARect, PixelsNumerator, PixelsDenominator, AnOffsetX, AnOffsetY);
ppmProportional:
DrawGraphicStretchProportional(APicture, ACanvas, ARect, PixelsNumerator, PixelsDenominator);
end;
end;
initialization
RegisterClass(TBitmap);
end.