⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 syneditprintpreview.pas

📁 一个非常好的c++编译器
💻 PAS
📖 第 1 页 / 共 2 页
字号:
{-------------------------------------------------------------------------------
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 + -