FastReport_FMX_2.8.12/Source/FMX.Win.frxPrinter.pas

902 lines
22 KiB
ObjectPascal
Raw Permalink Normal View History

2024-01-10 21:50:38 +01:00
{******************************************}
{ }
{ FastReport v4.0 }
{ Printer }
{ }
{ Copyright (c) 1998-2008 }
{ by Alexander Tzyganenko, }
{ Fast Reports Inc. }
{ }
{******************************************}
unit FMX.Win.frxPrinter;
interface
{$I fmx.inc}
{$I frx.inc}
uses
System.Classes, System.SysUtils, Winapi.Windows, Winapi.WinSpool, System.Types, System.UITypes, System.Variants,
FMX.Types, FMX.frxPrinter, FMX.Printer.Win, FMX.Printer, FMX.Canvas.GDIP, FMX.frxClass
{$IFDEF DELPHI19}
, FMX.Graphics
{$ENDIF};
type
THackCanvas = class(TCanvas);
// Fake printer used only for canvas creation
TFakePrinterWin = class(TPrinterWin)
protected
FPageHeight: Integer;
FPageWidth: Integer;
FCanvas: TCanvas;
procedure ActivePrinterChanged; override;
procedure DoAbortDoc; override;
procedure DoBeginDoc; override;
procedure DoEndDoc; override;
procedure DoNewPage; override;
function GetCanvas: TCanvas; override;
function GetNumCopies: Integer; override;
function GetOrientation: TPrinterOrientation; override;
function GetPageHeight: Integer; override;
function GetPageWidth: Integer; override;
function GetCapabilities: TPrinterCapabilities; override;
procedure RefreshFonts; override;
procedure RefreshPrinterDevices; override;
procedure SetOrientation(Value: TPrinterOrientation); override;
procedure SetNumCopies(Value: Integer); override;
procedure SetDefaultPrinter; override;
public
constructor Create; override;
destructor Destroy; override;
end;
TfrxPrinter = class(TfrxCustomPrinter)
private
FDeviceMode: THandle;
FDC: HDC;
FDriver: String;
FMode: PDeviceMode;
FWinPrinter: TFakePrinterWin;
FOldWinPrinter: TPrinterWin;
FOnChangedFont: TNotifyEvent;
procedure CreateDevMode;
procedure FreeDevMode;
procedure GetDC;
procedure FontChanged(Sender: TObject);
public
constructor Create(const AName, APort: String); override;
destructor Destroy; override;
procedure Init; override;
procedure RecreateDC;
procedure Abort; override;
procedure BeginDoc; override;
procedure BeginPage; override;
procedure BeginRAWDoc; override;
procedure EndDoc; override;
procedure EndPage; override;
procedure EndRAWDoc; override;
procedure WriteRAWDoc(const buf: AnsiString); override;
procedure SetViewParams(APaperSize: Integer;
APaperWidth, APaperHeight: Extended;
AOrientation: TPrinterOrientation); override;
procedure SetPrintParams(APaperSize: Integer;
APaperWidth, APaperHeight: Extended; AOrientation: TPrinterOrientation;
ABin, ADuplex, ACopies: Integer); override;
procedure PropertiesDlg; override;
function ShowPrintDialog: Boolean; override;
function UpdateDeviceCaps: Boolean;
property DeviceMode: PDeviceMode read FMode;
end;
TfrxPrinters = class(TfrxCustomPrinters)
protected
function GetDefaultPrinter: String; override;
public
constructor Create;
destructor Destroy; override;
procedure FillPrinters; override;
end;
TfrxPrinterCanvas = class(TCanvas)
{$IFNDEF FMX}
private
FPrinter: TfrxCustomPrinter;
procedure UpdateFont;
public
procedure Changing; override;
{$ENDIF}
end;
function frxGetPaperDimensions(PaperSize: Integer; var Width, Height: Extended): Boolean;
function ActualfrxPrinterClass : TfrxCustomPrintersClass;
implementation
uses
FMX.frxUtils, FMX.frxRes, FMX.frxFMX;
type
TPaperInfo = {packed} record
Typ: Integer;
Name: String;
X, Y: Integer;
end;
const
PAPERCOUNT = 66;
PaperInfo: array[0..PAPERCOUNT - 1] of TPaperInfo = (
(Typ:1; Name: ''; X:2159; Y:2794),
(Typ:2; Name: ''; X:2159; Y:2794),
(Typ:3; Name: ''; X:2794; Y:4318),
(Typ:4; Name: ''; X:4318; Y:2794),
(Typ:5; Name: ''; X:2159; Y:3556),
(Typ:6; Name: ''; X:1397; Y:2159),
(Typ:7; Name: ''; X:1842; Y:2667),
(Typ:8; Name: ''; X:2970; Y:4200),
(Typ:9; Name: ''; X:2100; Y:2970),
(Typ:10; Name: ''; X:2100; Y:2970),
(Typ:11; Name: ''; X:1480; Y:2100),
(Typ:12; Name: ''; X:2500; Y:3540),
(Typ:13; Name: ''; X:1820; Y:2570),
(Typ:14; Name: ''; X:2159; Y:3302),
(Typ:15; Name: ''; X:2150; Y:2750),
(Typ:16; Name: ''; X:2540; Y:3556),
(Typ:17; Name: ''; X:2794; Y:4318),
(Typ:18; Name: ''; X:2159; Y:2794),
(Typ:19; Name: ''; X:984; Y:2254),
(Typ:20; Name: ''; X:1048; Y:2413),
(Typ:21; Name: ''; X:1143; Y:2635),
(Typ:22; Name: ''; X:1207; Y:2794),
(Typ:23; Name: ''; X:1270; Y:2921),
(Typ:24; Name: ''; X:4318; Y:5588),
(Typ:25; Name: ''; X:5588; Y:8636),
(Typ:26; Name: ''; X:8636; Y:11176),
(Typ:27; Name: ''; X:1100; Y:2200),
(Typ:28; Name: ''; X:1620; Y:2290),
(Typ:29; Name: ''; X:3240; Y:4580),
(Typ:30; Name: ''; X:2290; Y:3240),
(Typ:31; Name: ''; X:1140; Y:1620),
(Typ:32; Name: ''; X:1140; Y:2290),
(Typ:33; Name: ''; X:2500; Y:3530),
(Typ:34; Name: ''; X:1760; Y:2500),
(Typ:35; Name: ''; X:1760; Y:1250),
(Typ:36; Name: ''; X:1100; Y:2300),
(Typ:37; Name: ''; X:984; Y:1905),
(Typ:38; Name: ''; X:920; Y:1651),
(Typ:39; Name: ''; X:3778; Y:2794),
(Typ:40; Name: ''; X:2159; Y:3048),
(Typ:41; Name: ''; X:2159; Y:3302),
(Typ:42; Name: ''; X:2500; Y:3530),
(Typ:43; Name: ''; X:1000; Y:1480),
(Typ:44; Name: ''; X:2286; Y:2794),
(Typ:45; Name: ''; X:2540; Y:2794),
(Typ:46; Name: ''; X:3810; Y:2794),
(Typ:47; Name: ''; X:2200; Y:2200),
(Typ:50; Name: ''; X:2355; Y:3048),
(Typ:51; Name: ''; X:2355; Y:3810),
(Typ:52; Name: ''; X:2969; Y:4572),
(Typ:53; Name: ''; X:2354; Y:3223),
(Typ:54; Name: ''; X:2101; Y:2794),
(Typ:55; Name: ''; X:2100; Y:2970),
(Typ:56; Name: ''; X:2355; Y:3048),
(Typ:57; Name: ''; X:2270; Y:3560),
(Typ:58; Name: ''; X:3050; Y:4870),
(Typ:59; Name: ''; X:2159; Y:3223),
(Typ:60; Name: ''; X:2100; Y:3300),
(Typ:61; Name: ''; X:1480; Y:2100),
(Typ:62; Name: ''; X:1820; Y:2570),
(Typ:63; Name: ''; X:3220; Y:4450),
(Typ:64; Name: ''; X:1740; Y:2350),
(Typ:65; Name: ''; X:2010; Y:2760),
(Typ:66; Name: ''; X:4200; Y:5940),
(Typ:67; Name: ''; X:2970; Y:4200),
(Typ:68; Name: ''; X:3220; Y:4450));
function frxGetPaperDimensions(PaperSize: Integer; var Width, Height: Extended): Boolean;
var
i: Integer;
begin
Result := False;
for i := 0 to PAPERCOUNT - 1 do
if PaperInfo[i].Typ = PaperSize then
begin
Width := PaperInfo[i].X / 10;
Height := PaperInfo[i].Y / 10;
Result := True;
break;
end;
end;
{$IFNDEF FMX}
{ TfrxPrinterCanvas }
procedure TfrxPrinterCanvas.Changing;
begin
inherited;
UpdateFont;
end;
procedure TfrxPrinterCanvas.UpdateFont;
var
FontSize: Integer;
begin
if FPrinter.DPI.Y <> Font.PixelsPerInch then
begin
FontSize := Font.Size;
Font.PixelsPerInch := FPrinter.DPI.Y;
Font.Size := FontSize;
end;
end;
{$ENDIF}
destructor TfrxPrinter.Destroy;
begin
if Assigned(FOldWinPrinter) then
SetPrinter(FOldWinPrinter);
FreeDevMode;
FWinPrinter.Free;
inherited;
end;
procedure TfrxPrinter.Init;
procedure FillPapers;
var
i, PaperSizesCount: Integer;
PaperSizes: array[0..255] of Word;
PaperNames: PChar;
begin
FillChar(PaperSizes, SizeOf(PaperSizes), 0);
PaperSizesCount := DeviceCapabilities(PChar(FName), PChar(FPort), DC_PAPERS, @PaperSizes, FMode);
GetMem(PaperNames, PaperSizesCount * 64 * sizeof(char));
DeviceCapabilities(PChar(FName), PChar(FPort), DC_PAPERNAMES, PaperNames, FMode);
for i := 0 to PaperSizesCount - 1 do
if PaperSizes[i] <> 256 then
FPapers.AddObject(StrPas(PWideChar(PaperNames + i * 64)), Pointer(PaperSizes[i]));
FreeMem(PaperNames, PaperSizesCount * 64 * sizeof(char));
end;
procedure FillBins;
var
i, BinsCount: Integer;
BinNumbers: array[0..255] of Word;
BinNames: PChar;
begin
FillChar(BinNumbers, SizeOf(BinNumbers), 0);
BinsCount := DeviceCapabilities(PChar(FName), PChar(FPort), DC_BINS, @BinNumbers[0], FMode);
GetMem(BinNames, BinsCount * 24 * sizeof(char));
try
DeviceCapabilities(PChar(FName), PChar(FPort), DC_BINNAMES, BinNames, FMode);
except
end;
for i := 0 to BinsCount - 1 do
if BinNumbers[i] <> DMBIN_AUTO then
FBins.AddObject(StrPas(PwideChar(BinNames + i * 24)), Pointer(BinNumbers[i]));
FreeMem(BinNames, BinsCount * 24 * sizeof(char));
end;
begin
if FInitialized then Exit;
CreateDevMode;
if FDeviceMode = 0 then Exit;
RecreateDC;
if not UpdateDeviceCaps then
begin
FreeDevMode;
Exit;
end;
FDefPaper := FMode.dmPaperSize;
FDefBin := FMode.dmDefaultSource;
FDefDuplex := FMode.dmDuplex;
FPaper := FDefPaper;
FDefPaperWidth := FPaperWidth;
FDefPaperHeight := FPaperHeight;
if FMode.dmOrientation = DMORIENT_PORTRAIT then
FDefOrientation := poPortrait else
FDefOrientation := poLandscape;
FOrientation := FDefOrientation;
FillPapers;
FillBins;
FBin := -1;
FDuplex := -1;
FInitialized := True;
FOldWinPrinter := nil;
end;
procedure TfrxPrinter.Abort;
begin
AbortDoc(FDC);
EndDoc;
end;
procedure TfrxPrinter.BeginDoc;
var
DocInfo: TDocInfo;
begin
FPrinting := True;
FillChar(DocInfo, SizeOf(DocInfo), 0);
DocInfo.cbSize := SizeOf(DocInfo);
if FTitle <> '' then
DocInfo.lpszDocName := PChar(FTitle)
else DocInfo.lpszDocName := PChar('Fast Report Document');
if FFileName <> '' then
DocInfo.lpszOutput := PChar(FFileName);
RecreateDC;
StartDoc(FDC, DocInfo);
end;
procedure TfrxPrinter.BeginPage;
begin
StartPage(FDC);
{$IFDEF DELPHI28}
Canvas.BeginScene;
{$ENDIF}
end;
procedure TfrxPrinter.EndDoc;
var
Saved8087CW: Word;
begin
Saved8087CW := Default8087CW;
Set8087CW($133F);
try
Winapi.Windows.EndDoc(FDC);
except
end;
Set8087CW(Saved8087CW);
FPrinting := False;
RecreateDC;
FBin := -1;
FDuplex := -1;
FMode.dmFields := FMode.dmFields or DM_DEFAULTSOURCE or DM_DUPLEX;
FMode.dmDefaultSource := FDefBin;
FMode.dmDuplex := FDefDuplex;
if FCanvas <> nil then
FCanvas.Free;
FDC := ResetDC(FDC, FMode^);
TFakePrinterWin(FWinPrinter).FDC := FDC;
{$IFNDEF Delphi17}
FCanvas := DefaultCanvasClass.CreateFromPrinter(FWinPrinter);
{$ELSE}
FCanvas := TCanvasManager.CreateFromPrinter(FWinPrinter);
{$ENDIF}
FOnChangedFont := THackCanvas(FCanvas).FFont.OnChanged;
THackCanvas(FCanvas).FFont.OnChanged := FontChanged;
SetPrinter(FOldWinPrinter);
FOldWinPrinter := nil;
end;
procedure TfrxPrinter.EndPage;
begin
Winapi.Windows.EndPage(FDC);
{$IFDEF Delphi28}
Canvas.EndScene;
{$ENDIF}
end;
procedure TfrxPrinter.BeginRAWDoc;
var
DocInfo1: TDocInfo1;
begin
RecreateDC;
DocInfo1.pDocName := PChar(FTitle);
DocInfo1.pOutputFile := nil;
DocInfo1.pDataType := 'RAW';
StartDocPrinter(FHandle, 1, @DocInfo1);
StartPagePrinter(FHandle);
end;
procedure TfrxPrinter.EndRAWDoc;
begin
EndPagePrinter(FHandle);
EndDocPrinter(FHandle);
end;
procedure TfrxPrinter.WriteRAWDoc(const buf: AnsiString);
var
N: DWORD;
begin
WritePrinter(FHandle, PAnsiChar(buf), Length(buf), N);
end;
constructor TfrxPrinter.Create(const AName, APort: String);
begin
inherited Create(AName, APort);
FWinPrinter := TFakePrinterWin.Create;
end;
procedure TfrxPrinter.CreateDevMode;
var
bufSize: Integer;
begin
if OpenPrinter(PChar(FName), FHandle, nil) then
begin
bufSize := DocumentProperties(0, FHandle, PChar(FName), nil, nil, 0);
if bufSize > 0 then
begin
FDeviceMode := GlobalAlloc(GHND, bufSize);
if FDeviceMode <> 0 then
begin
FMode := GlobalLock(FDeviceMode);
if DocumentProperties(0, FHandle, PChar(FName), FMode^, FMode^,
DM_OUT_BUFFER) < 0 then
begin
GlobalUnlock(FDeviceMode);
GlobalFree(FDeviceMode);
FDeviceMode := 0;
FMode := nil;
end
end;
end;
end;
end;
procedure TfrxPrinter.FontChanged(Sender: TObject);
begin
if Assigned(FOnChangedFont) then
FOnChangedFont(Sender);
//if FDPI.Y <> FCanvas.Font.PixelsPerInch then
begin
//FontSize := Round(FCanvas.Font.Size);
///Font.PixelsPerInch := FPrinter.DPI.Y;
//FCanvas.Font.Size := MulDiv(FontSize, DPI.Y, 72)
end;
end;
procedure TfrxPrinter.FreeDevMode;
begin
//FCanvas.Handle := 0;
if FDC <> 0 then
DeleteDC(FDC);
if FHandle <> 0 then
ClosePrinter(FHandle);
if FDeviceMode <> 0 then
begin
GlobalUnlock(FDeviceMode);
GlobalFree(FDeviceMode);
end;
FDeviceMode := 0;
FDC := 0;
FHandle := 0;
if FCanvas <> nil then
FCanvas.Free;
end;
procedure TfrxPrinter.RecreateDC;
begin
if FDC <> 0 then
try
DeleteDC(FDC);
except
end;
FDC := 0;
GetDC;
end;
procedure TfrxPrinter.GetDC;
begin
if FDC = 0 then
begin
if FPrinting then
FDC := CreateDC(PChar(FDriver), PChar(FName), nil, FMode) else
FDC := CreateIC(PChar(FDriver), PChar(FName), nil, FMode);
TFakePrinterWin(FWinPrinter).FDC := FDC;
//FWinPrinter.PageHeight
TFakePrinterWin(FWinPrinter).FState := TPrinterState.psHandleDC;
{$IFNDEF Delphi17}
if FCanvas <> nil then
FCanvas.CreateFromPrinter(FWinPrinter)
else
FCanvas := DefaultCanvasClass.CreateFromPrinter(FWinPrinter);
{$ELSE}
if FCanvas <> nil then
FreeAndNil(FCanvas);
FCanvas := TCanvasManager.CreateFromPrinter(FWinPrinter);
{$ENDIF}
FOnChangedFont := THackCanvas(FCanvas).FFont.OnChanged;
THackCanvas(FCanvas).FFont.OnChanged := FontChanged;
{$IFDEF Delphi28}
FCanvas.SetSize(Round(FPaperWidth * FDPI.X / 25.4), Round(FPaperHeight * FDPI.Y / 25.4));
{$ENDIF}
// FDC := THackPrinterWin(FWinPrinter).FDC;
//
// THackPrinterWin(FWinPrinter).SetState(TPrinterState.psNoHandle);
// THackPrinterWin(FWinPrinter).SetState(TPrinterState.psHandleDC);
// // on a second document printing process, the canvas must reconnect its
// // underlying objects to the new DC
// THackPrinterWin(FWinPrinter).Canvas.CreateFromPrinter(FWinPrinter);
// THackPrinterWin(FWinPrinter).SetCanvasDefaultSettings;
// FCanvas := THackPrinterWin(FWinPrinter).Canvas;
// FDC := THackPrinterWin(FWinPrinter).FDC;
// FHandle := THackPrinterWin(FWinPrinter).FPrinterHandle;
// FMode := THackPrinterWin(FWinPrinter).FDevMode;
// FDeviceMode := THackPrinterWin(FWinPrinter).FDeviceMode;
//FCanvas.Handle := FDC;
//FCanvas.Refresh;
//FCanvas.UpdateFont;
end;
end;
procedure TfrxPrinter.SetViewParams(APaperSize: Integer;
APaperWidth, APaperHeight: Extended; AOrientation: TPrinterOrientation);
begin
if APaperSize <> 256 then
begin
FMode.dmFields := DM_PAPERSIZE or DM_ORIENTATION;
FMode.dmPaperSize := APaperSize;
if AOrientation = poPortrait then
FMode.dmOrientation := DMORIENT_PORTRAIT else
FMode.dmOrientation := DMORIENT_LANDSCAPE;
RecreateDC;
if not UpdateDeviceCaps then Exit;
end
else
begin
// copy the margins from A4 paper
SetViewParams(DMPAPER_A4, 0, 0, AOrientation);
FPaperHeight := APaperHeight;
FPaperWidth := APaperWidth;
end;
FPaper := APaperSize;
FOrientation := AOrientation;
end;
function TfrxPrinter.ShowPrintDialog: Boolean;
begin
Result := False;
end;
procedure TfrxPrinter.SetPrintParams(APaperSize: Integer;
APaperWidth, APaperHeight: Extended; AOrientation: TPrinterOrientation;
ABin, ADuplex, ACopies: Integer);
begin
FMode.dmFields := FMode.dmFields or DM_PAPERSIZE or DM_ORIENTATION or DM_COPIES
or DM_DEFAULTSOURCE;
if APaperSize = 256 then
begin
FMode.dmFields := FMode.dmFields or DM_PAPERLENGTH or DM_PAPERWIDTH;
if AOrientation = poLandscape then
begin
FMode.dmPaperLength := Round(APaperWidth * 10);
FMode.dmPaperWidth := Round(APaperHeight * 10);
end
else
begin
FMode.dmPaperLength := Round(APaperHeight * 10);
FMode.dmPaperWidth := Round(APaperWidth * 10);
end;
end
else
begin
FMode.dmPaperLength := 0;
FMode.dmPaperWidth := 0;
end;
FMode.dmPaperSize := APaperSize;
if AOrientation = poPortrait then
FMode.dmOrientation := DMORIENT_PORTRAIT else
FMode.dmOrientation := DMORIENT_LANDSCAPE;
FMode.dmCopies := ACopies;
if ABin = DMBIN_AUTO then
if FBin <> -1 then
ABin := FBin
else
ABin := DefBin;
FMode.dmDefaultSource := ABin;
if ADuplex = 0 then
ADuplex := FDefDuplex
else Inc(ADuplex);
if ADuplex = 4 then
ADuplex := DMDUP_SIMPLEX;
if FDuplex <> -1 then
ADuplex := FDuplex;
if ADuplex <> 1 then
FMode.dmFields := FMode.dmFields or DM_DUPLEX;
FMode.dmDuplex := ADuplex;
{ strange behaviour with GDI+ canvas
need to release canvas and all gdi+ objects before call ResetDC
otherwise it return error }
if FCanvas <> nil then
FCanvas.Free;
FDC := ResetDC(FDC, FMode^);
FDC := ResetDC(FDC, FMode^); // needed for some printers
TFakePrinterWin(FWinPrinter).FDC := FDC;
{$IFNDEF Delphi17}
FCanvas := DefaultCanvasClass.CreateFromPrinter(FWinPrinter);
{$ELSE}
FCanvas := TCanvasManager.CreateFromPrinter(FWinPrinter);
{$ENDIF}
FWinPrinter.FCanvas := FCanvas;
if {PrinterAssigned and} not Assigned(FOldWinPrinter) then
FOldWinPrinter := TPrinterWin(Printer);
SetPrinter(FWinPrinter);
FOnChangedFont := THackCanvas(FCanvas).FFont.OnChanged;
THackCanvas(FCanvas).FFont.OnChanged := FontChanged;
//FCanvas.Refresh;
if not UpdateDeviceCaps then Exit;
FPaper := APaperSize;
FOrientation := AOrientation;
{$IFDEF Delphi28}
FCanvas.SetSize(Round(FPaperWidth * FDPI.X / 25.4), Round(FPaperHeight * FDPI.Y / 25.4));
{$ENDIF}
end;
function TfrxPrinter.UpdateDeviceCaps: Boolean;
begin
Result := True;
if FDC = 0 then GetDC;
FDPI := Point(GetDeviceCaps(FDC, LOGPIXELSX), GetDeviceCaps(FDC, LOGPIXELSY));
if (FDPI.X = 0) or (FDPI.Y = 0) then
begin
Result := False;
frxErrorMsg('Printer selected is not valid');
Exit;
end;
FPaperHeight := Round(GetDeviceCaps(FDC, PHYSICALHEIGHT) / FDPI.Y * 25.4);
FPaperWidth := Round(GetDeviceCaps(FDC, PHYSICALWIDTH) / FDPI.X * 25.4);
FLeftMargin := Round(GetDeviceCaps(FDC, PHYSICALOFFSETX) / FDPI.X * 25.4);
FTopMargin := Round(GetDeviceCaps(FDC, PHYSICALOFFSETY) / FDPI.Y * 25.4);
FRightMargin := FPaperWidth - Round(GetDeviceCaps(FDC, HORZRES) / FDPI.X * 25.4) - FLeftMargin;
FBottomMargin := FPaperHeight - Round(GetDeviceCaps(FDC, VERTRES) / FDPI.Y * 25.4) - FTopMargin;
end;
procedure TfrxPrinter.PropertiesDlg;
var
h: THandle;
PrevDuplex: Integer;
begin
PrevDuplex := FMode.dmDuplex;
//if Screen.ActiveForm <> nil then
// h := Screen.ActiveForm.Handle else
h := 0;
if DocumentProperties(h, FHandle, PChar(FName), FMode^,
FMode^, DM_IN_BUFFER or DM_OUT_BUFFER or DM_IN_PROMPT) > 0 then
begin
FBin := FMode.dmDefaultSource;
if PrevDuplex <> FMode.dmDuplex then
FDuplex := FMode.dmDuplex;
RecreateDC;
end;
end;
{ TfrxPrinters }
constructor TfrxPrinters.Create;
begin
Inherited;
end;
destructor TfrxPrinters.Destroy;
begin
inherited;
end;
function TfrxPrinters.GetDefaultPrinter: String;
var
prnName: array[0..255] of Char;
begin
GetProfileString('windows', 'device', '', prnName, 255);
Result := Copy(prnName, 1, Pos(',', prnName) - 1);
end;
procedure TfrxPrinters.FillPrinters;
var
i, j: Integer;
Buf, prnInfo: PByte;
Flags, bufSize, prnCount: DWORD;
Level: Byte;
sl: TStringList;
procedure AddPrinter(ADevice, APort: String);
begin
FPrinterList.Add(TfrxPrinter.Create(ADevice, APort));
FPrinters.Add(ADevice);
end;
begin
Clear;
if Win32Platform = VER_PLATFORM_WIN32_NT then
begin
Flags := PRINTER_ENUM_CONNECTIONS or PRINTER_ENUM_LOCAL;
Level := 4;
end
else
begin
Flags := PRINTER_ENUM_LOCAL;
Level := 5;
end;
bufSize := 0;
EnumPrinters(Flags, nil, Level, nil, 0, bufSize, prnCount);
if bufSize = 0 then Exit;
GetMem(Buf, bufSize);
try
if not EnumPrinters(Flags, nil, Level, PByte(Buf), bufSize, bufSize, prnCount) then
Exit;
prnInfo := Buf;
for i := 0 to prnCount - 1 do
if Level = 4 then
with PPrinterInfo4(prnInfo)^ do
begin
AddPrinter(pPrinterName, '');
Inc(prnInfo, SizeOf(TPrinterInfo4));
end
else
with PPrinterInfo5(prnInfo)^ do
begin
sl := TStringList.Create;
frxSetCommaText(pPortName, sl, ',');
for j := 0 to sl.Count - 1 do
AddPrinter(pPrinterName, sl[j]);
sl.Free;
Inc(prnInfo, SizeOf(TPrinterInfo5));
end;
finally
FreeMem(Buf, bufSize);
end;
end;
{ THackPrinterWin }
procedure TFakePrinterWin.ActivePrinterChanged;
begin
//do nothing
end;
constructor TFakePrinterWin.Create;
begin
//inherited;
inherited;
end;
destructor TFakePrinterWin.Destroy;
begin
FCanvas := nil;
inherited;
//inherited;
end;
procedure TFakePrinterWin.DoAbortDoc;
begin
//do nothing
end;
procedure TFakePrinterWin.DoBeginDoc;
begin
//do nothing
end;
procedure TFakePrinterWin.DoEndDoc;
begin
//do nothing
end;
procedure TFakePrinterWin.DoNewPage;
begin
//do nothing
end;
function TFakePrinterWin.GetCanvas: TCanvas;
begin
Result := FCanvas;
end;
function TFakePrinterWin.GetCapabilities: TPrinterCapabilities;
begin
Result := FCapabilities;
end;
function TFakePrinterWin.GetNumCopies: Integer;
begin
Result := 0;
//do nothing
end;
function TFakePrinterWin.GetOrientation: TPrinterOrientation;
begin
Result := TPrinterOrientation.poPortrait;
//do nothing
end;
function TFakePrinterWin.GetPageHeight: Integer;
begin
Result := FPageHeight;
end;
function TFakePrinterWin.GetPageWidth: Integer;
begin
Result := FPageWidth;
end;
procedure TFakePrinterWin.RefreshFonts;
begin
//do nothing
end;
procedure TFakePrinterWin.RefreshPrinterDevices;
begin
//do nothing
end;
procedure TFakePrinterWin.SetDefaultPrinter;
begin
//do nothing
end;
procedure TFakePrinterWin.SetNumCopies(Value: Integer);
begin
//do nothing
end;
procedure TFakePrinterWin.SetOrientation(Value: TPrinterOrientation);
begin
//do nothing
end;
function ActualfrxPrinterClass : TfrxCustomPrintersClass;
begin
Result := TfrxPrinters;
end;
initialization
finalization
end.