📄 syneditprintpreview.pas
字号:
{-------------------------------------------------------------------------------
The contents of this file are subject to the Mozilla Public License
Version 1.1 (the "License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.mozilla.org/MPL/
Software distributed under the License is distributed on an "AS IS" basis,
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
the specific language governing rights and limitations under the License.
The Original Code is: SynEditPrintPreview.pas, released 2000-06-01.
The Initial Author of the Original Code is Morten J. Skovrup.
Portions written by Morten J. Skovrup are copyright 2000 Morten J. Skovrup.
Portions written by Michael Hieke are copyright 2000 Michael Hieke.
All Rights Reserved.
Contributors to the SynEdit project are listed in the Contributors.txt file.
Alternatively, the contents of this file may be used under the terms of the
GNU General Public License Version 2 or later (the "GPL"), in which case
the provisions of the GPL are applicable instead of those above.
If you wish to allow use of your version of this file only under the terms
of the GPL and not to allow others to use your version of this file
under the MPL, indicate your decision by deleting the provisions above and
replace them with the notice and other provisions required by the GPL.
If you do not delete the provisions above, a recipient may use your version
of this file under either the MPL or the GPL.
$Id: SynEditPrintPreview.pas,v 1.6 2005/01/08 17:04:28 specu Exp $
You may retrieve the latest version of this file at the SynEdit home page,
located at http://SynEdit.SourceForge.net
Known Issues:
-------------------------------------------------------------------------------}
{-------------------------------------------------------------------------------
CONTENTS:
Print preview component. Allmost identical to code developed by Michael Hieke.
It is important to call UpdatePreview whenever things change (i.e. just
before the preview is shown, and when the printer is changed)
-------------------------------------------------------------------------------}
{$IFNDEF QSYNEDITPRINTPREVIEW}
unit SynEditPrintPreview;
{$ENDIF}
{$I SynEdit.inc}
{$M+}
interface
uses
{$IFDEF SYN_CLX}
Qt,
QControls,
QGraphics,
QForms,
Types,
QSynEditPrint,
{$ELSE}
{$IFDEF SYN_COMPILER_7}
Themes,
{$ENDIF}
Windows,
Controls,
Messages,
Graphics,
Forms,
SynEditPrint,
{$ENDIF}
Classes,
SysUtils;
type
//Event raised when page is changed in preview
TPreviewPageEvent = procedure(Sender: TObject; PageNumber: Integer) of object;
TSynPreviewScale = (pscWholePage, pscPageWidth, pscUserScaled);
{$IFNDEF SYN_COMPILER_4_UP}
TWMMouseWheel = record
Msg: Cardinal;
Keys: SmallInt;
WheelDelta: SmallInt;
case Integer of
0: (
XPos: Smallint;
YPos: Smallint);
1: (
Pos: TSmallPoint;
Result: Longint);
end;
{$ENDIF}
TSynEditPrintPreview = class(TCustomControl)
protected
FBorderStyle: TBorderStyle;
FSynEditPrint: TSynEditPrint;
FScaleMode: TSynPreviewScale;
FScalePercent: Integer;
// these are in pixels ( = screen device units)
FVirtualSize: TPoint;
FVirtualOffset: TPoint;
FPageSize: TPoint;
FScrollPosition: TPoint;
FPageBG: TColor;
FPageNumber: Integer;
FShowScrollHint: Boolean;
FOnPreviewPage: TPreviewPageEvent;
FOnScaleChange: TNotifyEvent; // JD 2002-01-9
{$IFNDEF SYN_CLX}
FWheelAccumulator: Integer;
{$ENDIF}
procedure SetBorderStyle(Value: TBorderStyle);
procedure SetPageBG(Value: TColor);
procedure SetSynEditPrint(Value: TSynEditPrint);
procedure SetScaleMode(Value: TSynPreviewScale);
procedure SetScalePercent(Value: Integer);
private
{$IFNDEF SYN_CLX}
procedure WMEraseBkgnd(var Msg: TWMEraseBkgnd); message WM_ERASEBKGND;
procedure WMHScroll(var Msg: TWMHScroll); message WM_HSCROLL;
procedure WMSize(var Msg: TWMSize); message WM_SIZE;
procedure WMVScroll(var Msg: TWMVScroll); message WM_VSCROLL;
procedure WMMouseWheel(var Message: TWMMouseWheel); message
{$IFDEF SYN_COMPILER_3_UP} WM_MOUSEWHEEL {$ELSE} $020A {$ENDIF};
{$ENDIF}
procedure PaintPaper;
function GetPageCount: Integer;
protected
{$IFNDEF SYN_CLX}
procedure CreateParams(var Params: TCreateParams); override;
{$ENDIF}
function GetPageHeightFromWidth(AWidth: Integer): Integer;
function GetPageHeight100Percent: Integer;
function GetPageWidthFromHeight(AHeight: Integer): Integer;
function GetPageWidth100Percent: Integer;
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
procedure ScrollHorzFor(Value: Integer);
procedure ScrollHorzTo(Value: Integer); virtual;
procedure ScrollVertFor(Value: Integer);
procedure ScrollVertTo(Value: Integer); virtual;
procedure UpdateScrollbars; virtual;
procedure SizeChanged; virtual;
public
constructor Create(AOwner: TComponent); override;
procedure Paint; override;
procedure UpdatePreview;
procedure NextPage;
procedure PreviousPage;
procedure FirstPage;
procedure LastPage;
procedure Print;
property PageNumber: Integer read FPageNumber;
property PageCount: Integer read GetPageCount;
published
property Align default alClient;
property BorderStyle: TBorderStyle read FBorderStyle write SetBorderStyle
default bsSingle;
property Color default clAppWorkspace;
property Cursor;
property PageBGColor: TColor read FPageBG write SetPageBG default clWhite;
property PopupMenu; // JD 2002-01-9
property SynEditPrint: TSynEditPrint read FSynEditPrint
write SetSynEditPrint;
property ScaleMode: TSynPreviewScale read FScaleMode write SetScaleMode
default pscUserScaled;
property ScalePercent: Integer read FScalePercent write SetScalePercent
default 100;
property Visible default True;
property ShowScrollHint: Boolean read FShowScrollHint write FShowScrollHint
default True;
property OnClick;
property OnMouseDown;
property OnMouseUp;
property OnPreviewPage: TPreviewPageEvent read FOnPreviewPage
write FOnPreviewPage;
property OnScaleChange: TNotifyEvent read FOnScaleChange // JD 2002-01-9
write FOnScaleChange; // JD 2002-01-9
end;
implementation
uses
{$IFDEF SYN_CLX}
QSynEditStrConst;
{$ELSE}
SynEditStrConst;
{$ENDIF}
const
MARGIN_X = 12; // margin width left and right of page
MARGIN_Y = 12; // margin height above and below page
SHADOW_SIZE = 2; // page shadow width
{ TSynEditPrintPreview }
constructor TSynEditPrintPreview.Create(AOwner: TComponent);
begin
inherited;
{$IFDEF SYN_COMPILER_7_UP}
{$IFNDEF SYN_CLX}
ControlStyle := ControlStyle + [csNeedsBorderPaint];
{$ENDIF}
{$ENDIF}
FBorderStyle := bsSingle;
FScaleMode := pscUserScaled;
FScalePercent := 100;
FPageBG := clWhite;
Width := 200;
Height := 120;
ParentColor := False;
Color := clAppWorkspace;
Visible := True;
FPageNumber := 1;
FShowScrollHint := True;
Align := alClient;
{$IFNDEF SYN_CLX}
FWheelAccumulator := 0;
{$ENDIF}
end;
{$IFNDEF SYN_CLX}
procedure TSynEditPrintPreview.CreateParams(var Params: TCreateParams);
const
BorderStyles: array[TBorderStyle] of DWord = (0, WS_BORDER);
begin
inherited;
with Params do begin
Style := Style or WS_HSCROLL or WS_VSCROLL or BorderStyles[FBorderStyle]
or WS_CLIPCHILDREN;
if NewStyleControls and Ctl3D and (FBorderStyle = bsSingle) then begin
Style := Style and not WS_BORDER;
ExStyle := ExStyle or WS_EX_CLIENTEDGE;
end;
end;
end;
{$ENDIF}
function TSynEditPrintPreview.GetPageHeightFromWidth(AWidth: Integer): Integer;
begin
if Assigned(FSynEditPrint) then begin
with FSynEditPrint.PrinterInfo do
Result := MulDiv(AWidth, PhysicalHeight, PhysicalWidth);
end
else
Result := MulDiv(AWidth, 141, 100); // fake A4 size
end;
function TSynEditPrintPreview.GetPageWidthFromHeight(AHeight: Integer): Integer;
begin
if Assigned(FSynEditPrint) then begin
with FSynEditPrint.PrinterInfo do
Result := MulDiv(AHeight, PhysicalWidth, PhysicalHeight);
end
else
Result := MulDiv(AHeight, 100, 141); // fake A4 size
end;
function TSynEditPrintPreview.GetPageHeight100Percent: Integer;
var
{$IFNDEF SYN_CLX}
DC: HDC;
{$ENDIF}
ScreenDPI: Integer;
begin
Result := 0;
{$IFDEF SYN_CLX}
ScreenDPI := Screen.Height;
{$ELSE}
DC := GetDC(0);
ScreenDPI := GetDeviceCaps(DC, LogPixelsY);
ReleaseDC(0, DC);
{$ENDIF}
if Assigned(FSynEditPrint) then
with FSynEditPrint.PrinterInfo do
Result := MulDiv(PhysicalHeight, ScreenDPI, YPixPrInch);
end;
function TSynEditPrintPreview.GetPageWidth100Percent: Integer;
var
{$IFNDEF SYN_CLX}
DC: HDC;
{$ENDIF}
ScreenDPI: Integer;
begin
Result := 0;
{$IFDEF SYN_CLX}
ScreenDPI := Screen.Height;
{$ELSE}
DC := GetDC(0);
ScreenDPI := GetDeviceCaps(DC, LogPixelsX);
ReleaseDC(0, DC);
{$ENDIF}
if Assigned(FSynEditPrint) then
with FSynEditPrint.PrinterInfo do
Result := MulDiv(PhysicalWidth, ScreenDPI, XPixPrInch);
end;
procedure TSynEditPrintPreview.Notification(AComponent: TComponent;
Operation: TOperation);
begin
inherited;
if (Operation = opRemove) and (AComponent = FSynEditPrint) then
SynEditPrint := nil;
end;
procedure TSynEditPrintPreview.PaintPaper;
var
rcClip, rcPaper: TRect;
{$IFNDEF SYN_CLX}
rgnPaper: HRGN;
{$ENDIF}
i: Integer;
begin
with Canvas do begin
// we work in MM_TEXT mapping mode here...
rcClip := ClipRect;
if IsRectEmpty(rcClip) then Exit;
Brush.Color := Self.Color;
Brush.Style := bsSolid;
Pen.Color := clBlack;
Pen.Width := 1;
Pen.Style := psSolid;
if (csDesigning in ComponentState) or (not Assigned(FSynEditPrint)) then begin
FillRect(rcClip);
Brush.Color := FPageBG;
Rectangle(MARGIN_X, MARGIN_Y, MARGIN_X + 30, MARGIN_Y + 43);
Exit;
end;
// fill background around paper
with rcPaper do begin
Left := FVirtualOffset.X + FScrollPosition.X;
if ScaleMode = pscWholePage then
Top := FVirtualOffset.Y
else
Top := FVirtualOffset.Y + FScrollPosition.Y;
Right := Left + FPageSize.X;
Bottom := Top + FPageSize.Y;
{$IFNDEF SYN_CLX}
rgnPaper := CreateRectRgn(Left, Top, Right + 1, Bottom + 1);
{$ENDIF}
end;
{$IFNDEF SYN_CLX}
if (NULLREGION <> ExtSelectClipRgn(Handle, rgnPaper, RGN_DIFF)) then
FillRect(rcClip);
{$ENDIF}
// paper shadow
Brush.Color := clDkGray;
with rcPaper do begin
for i := 1 to SHADOW_SIZE do
PolyLine([Point(Left + i, Bottom + i), Point(Right + i, Bottom + i),
Point(Right + i, Top + i)]);
end;
// paint paper background
{$IFNDEF SYN_CLX}
SelectClipRgn(Handle, rgnPaper);
{$ENDIF}
Brush.Color := FPageBG;
with rcPaper do
Rectangle(Left, Top, Right + 1, Bottom + 1);
{$IFNDEF SYN_CLX}
DeleteObject(rgnPaper);
{$ENDIF}
end;
end;
procedure TSynEditPrintPreview.Paint;
var
ptOrgScreen: TPoint;
begin
with Canvas do begin
PaintPaper;
if (csDesigning in ComponentState) or (not Assigned(FSynEditPrint)) then
Exit;
// paint the contents, clipped to the area inside of the print margins
// correct scaling for output:
{$IFNDEF SYN_CLX}
SetMapMode(Handle, MM_ANISOTROPIC);
{$ENDIF}
// compute the logical point (0, 0) in screen pixels
with FSynEditPrint.PrinterInfo do
begin
{$IFNDEF SYN_CLX}
SetWindowExtEx(Handle, PhysicalWidth, PhysicalHeight, nil);
SetViewPortExtEx(Handle, FPageSize.X, FPageSize.Y, nil);
{$ENDIF}
ptOrgScreen.X := MulDiv(LeftGutter, FPageSize.X, PhysicalWidth);
ptOrgScreen.Y := MulDiv(TopGutter, FPageSize.Y, PhysicalHeight);
Inc(ptOrgScreen.X, FVirtualOffset.X + FScrollPosition.X);
if ScaleMode = pscWholePage then
Inc(ptOrgScreen.Y, FVirtualOffset.Y)
else
Inc(ptOrgScreen.Y, FVirtualOffset.Y + FScrollPosition.Y);
{$IFNDEF SYN_CLX}
SetViewPortOrgEx(Handle, ptOrgScreen.X, ptOrgScreen.Y, nil);
// clip the output to the print margins
IntersectClipRect(Handle, 0, 0, PrintableWidth, PrintableHeight);
{$ENDIF}
end;
FSynEditPrint.PrintToCanvas(Canvas, FPageNumber);
end;
end;
procedure TSynEditPrintPreview.ScrollHorzFor(Value: Integer);
begin
ScrollHorzTo(FScrollPosition.X + Value);
end;
procedure TSynEditPrintPreview.ScrollHorzTo(Value: Integer);
var
nW, n: Integer;
begin
nW := ClientWidth;
n := nW - FVirtualSize.X;
if (Value < n) then Value := n;
if (Value > 0) then Value := 0;
if (Value <> FScrollPosition.X) then
begin
n := Value - FScrollPosition.X;
FScrollPosition.X := Value;
UpdateScrollbars;
if (Abs(n) > nW div 2) then
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -