Componentes.Terceros.DevExp.../internal/x.36/1/ExpressPrinting System/Sources/dxPrnDev.pas
2008-09-04 11:31:51 +00:00

2381 lines
67 KiB
ObjectPascal

{*******************************************************************}
{ }
{ Developer Express Visual Component Library }
{ ExpressPrinting System(tm) COMPONENT SUITE }
{ }
{ Copyright (C) 1998-2008 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 dxPrnDev;
interface
(*$HPPEMIT '#include <winspool.h>' *)
{$I cxVer.inc}
uses
Windows, Classes, ImgList, Controls, SysUtils, Graphics, Messages, dxPSGlbl;
type
// Follow structures are supported only in W2K and upper
// specifies the global default printer settings
{$IFDEF CBUILDER5}
{$EXTERNALSYM _PRINTER_INFO_8A}
{$ENDIF}
_PRINTER_INFO_8A = record
DevMode: PDeviceModeA ;
end;
{$IFDEF CBUILDER5}
{$EXTERNALSYM _PRINTER_INFO_8W}
{$ENDIF}
_PRINTER_INFO_8W = record
DevMode: PDeviceModeW ;
end;
{$IFDEF CBUILDER5}
{$EXTERNALSYM _PRINTER_INFO_8}
{$ENDIF}
_PRINTER_INFO_8 = _PRINTER_INFO_8A;
TPrinterInfo8A = _PRINTER_INFO_8A;
TPrinterInfo8W = _PRINTER_INFO_8W;
TPrinterInfo8 = TPrinterInfo8A;
{$IFDEF CBUILDER5}
{$EXTERNALSYM PRINTER_INFO_8A}
{$ENDIF}
PRINTER_INFO_8A = _PRINTER_INFO_8A;
{$IFDEF CBUILDER5}
{$EXTERNALSYM PRINTER_INFO_8W}
{$ENDIF}
PRINTER_INFO_8W = _PRINTER_INFO_8W;
{$IFDEF CBUILDER5}
{$EXTERNALSYM PRINTER_INFO_8}
{$ENDIF}
PRINTER_INFO_8 = PRINTER_INFO_8A;
PPrinterInfo8A = ^TPrinterInfo8A;
PPrinterInfo8W = ^TPrinterInfo8W;
PPrinterInfo8 = PPrinterInfo8A;
// specifies the per-user default printer settings
{$IFDEF CBUILDER5}
{$EXTERNALSYM _PRINTER_INFO_9A}
{$ENDIF}
_PRINTER_INFO_9A = record
DevMode: PDeviceModeA ;
end;
{$IFDEF CBUILDER5}
{$EXTERNALSYM _PRINTER_INFO_9W}
{$ENDIF}
_PRINTER_INFO_9W = record
DevMode: PDeviceModeW ;
end;
{$IFDEF CBUILDER5}
{$EXTERNALSYM _PRINTER_INFO_8}
{$ENDIF}
_PRINTER_INFO_9 = _PRINTER_INFO_9A;
TPrinterInfo9A = _PRINTER_INFO_9A;
TPrinterInfo9W = _PRINTER_INFO_9W;
TPrinterInfo9 = TPrinterInfo9A;
{$IFDEF CBUILDER5}
{$EXTERNALSYM PRINTER_INFO_9A}
{$ENDIF}
PRINTER_INFO_9A = _PRINTER_INFO_9A;
{$IFDEF CBUILDER5}
{$EXTERNALSYM PRINTER_INFO_9W}
{$ENDIF}
PRINTER_INFO_9W = _PRINTER_INFO_9W;
{$IFDEF CBUILDER5}
{$EXTERNALSYM PRINTER_INFO_9}
{$ENDIF}
PRINTER_INFO_9 = PRINTER_INFO_9A;
PPrinterInfo9A = ^TPrinterInfo9A;
PPrinterInfo9W = ^TPrinterInfo9W;
PPrinterInfo9 = PPrinterInfo9A;
TdxPrinterState = (psNoHandle, psHandleIC, psHandleDC);
TdxDuplexMode = (dmSimplex, dmHorizontal, dmVertical);
TdxPrinterOrientation = (poPortrait, poLandscape);
TdxPrinterCapability = (pcCopies, pcOrientation, pcCollation);//, pcDuplex, pcColor);
TdxPrinterCapabilities = set of TdxPrinterCapability;
EdxPrintDevice = class(Exception);
TdxPrintDeviceInfo = class
private
FDevice: PChar ;
FDriver: PChar ;
FPort: PChar ;
FIsDefault: Boolean;
FIsNetwork: Boolean;
public
constructor Create(ADriver, ADevice, APort: PChar ;
AnIsDefault, AnIsNetwork: Boolean);
destructor Destroy; override;
function IsEqual(ADriver, ADevice, APort: PChar ): Boolean;
property Device: PChar read FDevice;
property Driver: PChar read FDriver;
property Port: PChar read FPort;
property IsDefault: Boolean read FIsDefault write FIsDefault;
property IsNetwork: Boolean read FIsNetwork;
end;
TdxPrintDevice = class
private
FAborted: Boolean;
FAutoRefresh: Boolean;
FBins: TStrings;
FCanvas: TCanvas;
FCapabilities: TdxPrinterCapabilities;
FCurrentDevice: PChar ;
FCurrentDriver: PChar ;
FCurrentPort: PChar ;
FDC: HDC;
FDeviceHandle: THandle;
FDeviceMode: PDeviceMode ;
FDeviceModeChanged: Boolean;
FHDeviceMode: THandle;
FFileName: string;
FFonts: TStrings;
FIsDeviceModePersistent: Boolean;
FMaxCopies: Integer;
FMaxExtents: Integer;
FMinExtents: Integer;
FPageNumber: Integer;
FPapers: TStrings;
FPrinters: TStrings;
FPrinterIndex: Integer;
FPrinting: Boolean;
FState: TdxPrinterState;
FTitle: string;
FWindowHandle: HWND;
FOnNewPage: TNotifyEvent;
FOnPrinterChange: TNotifyEvent;
FOnRefresh: TNotifyEvent;
function GetBinIndex: Integer;
function GetBins: TStrings;
function GetCanvas: TCanvas;
function GetCollate: Boolean;
function GetColorMode: Boolean;
function GetCurrentDevice: PChar ;
function GetCurrentDriver: PChar ;
function GetCurrentPort: PChar ;
function GetDefaultDMPaper: Integer;
function GetDeviceMode: PDeviceMode;
function GetDuplex: TdxDuplexMode;
function GetFonts: TStrings;
function GetHandle: HDC;
function GetHDeviceMode: THandle;
function GetIsDefault: Boolean;
function GetIsInitialized: Boolean;
function GetIsNetwork: Boolean;
function GetMaxExtents(Index: Integer): Integer;
function GetMinExtents(Index: Integer): Integer;
function GetNumCopies: Integer;
function GetOrientation: TdxPrinterOrientation;
function GetPageHeight: Integer;
function GetPageHeightLoMetric: Integer;
function GetPageWidth: Integer;
function GetPageWidthLoMetric: Integer;
function GetPaperCount: Integer;
function GetPaperIndex: Integer;
function GetPapers: TStrings;
function GetPhysOffset(Index: Integer): Integer;
function GetPrinterCount: Integer;
function GetPrinterIndex: Integer;
function GetPrinterInfo(Index: Integer): TdxPrintDeviceInfo;
function GetPrinters: TStrings;
procedure SetBinIndex(Value: Integer);
procedure SetCollate(Value: Boolean);
procedure SetColorMode(Value: Boolean);
procedure SetDuplex(Value: TdxDuplexMode);
procedure SetIsDefault(Value: Boolean);
procedure SetNumCopies(Value: Integer);
procedure SetOrientation(Value: TdxPrinterOrientation);
procedure SetPaperIndex(Value: Integer);
procedure SetPrinterCapabilities(Value: Integer);
procedure SetPrinterIndex(Value: Integer);
procedure CheckPrinting(Value: Boolean);
procedure ClosePrintDevice;
procedure DeselectHandles;
procedure FixMinMaxExtents;
procedure FreeAndNilBins;
procedure FreeAndNilCanvas;
procedure FreeAndNilFonts;
procedure FreeAndNilPapers;
procedure FreeAndNilPrinters;
procedure InternalSelectPaperBySize(var AWidth, AHeight: Integer);
procedure OpenPrintDevice(AIndex: Integer);
procedure SetState(Value: TdxPrinterState);
procedure SetToDefaultPrintDevice;
procedure WndProc(var Message: TMessage);
protected
procedure DoNewPage; dynamic;
procedure DoPrinterChanged; dynamic;
procedure DoRefresh; dynamic;
public
constructor Create;
destructor Destroy; override;
procedure Abort;
function BeginDoc: Integer; {returns the print job identifier for the document}
procedure EndDoc;
procedure NewPage;
function FindPrintDevice(ADevice, APort: PChar ): Integer;
function IsDeviceModeChanged: Boolean;
procedure Refresh;
procedure ResetDC(IsForced: Boolean);
procedure ResetPrintDevice;
function FindBin(ABin: Integer): Integer; overload;
function FindBin(const AName: string): Integer; overload;
function IsAutoSelectBin(AIndex: Integer): Boolean;
function IsUserPaperSource(AIndex: Integer): Boolean;
function SelectBin(Value: Integer): Boolean; overload;
function SelectBin(const AName: string): Boolean; overload;
function FindPaper(ADMPaper: Integer): Integer; overload;
function FindPaper(const AName: string): Integer; overload;
function FindPaper(const ASize: TPoint): Integer; overload;
function FindPaper(AWidth, AHeight: Integer): Integer; overload;
function IsEnvelopePaper(AIndex: Integer): Boolean;
function IsUserPaperSize(AIndex: Integer): Boolean;
function SelectPaper(ADMPaper: Integer): Boolean; overload;
function SelectPaper(const AName: string): Boolean; overload;
function SelectPaper(var AWidth, AHeight: Integer): Boolean; overload;
function IsSupportColoration: Boolean;
function IsSupportDuplex: Boolean;
property Aborted: Boolean read FAborted;
property AutoRefresh: Boolean read FAutoRefresh write FAutoRefresh;
property BinIndex: Integer read GetBinIndex write SetBinIndex;
property Bins: TStrings read GetBins;
property Canvas: TCanvas read GetCanvas;
property Capabilities: TdxPrinterCapabilities read FCapabilities;
property Collate: Boolean read GetCollate write SetCollate;
property ColorMode: Boolean read GetColorMode write SetColorMode;
property Copies: Integer read GetNumCopies write SetNumCopies;
property CurrentDevice: PChar read GetCurrentDevice;
property CurrentDriver: PChar read GetCurrentDriver;
property CurrentPort: PChar read GetCurrentPort;
property DefaultDMPaper: Integer read GetDefaultDMPaper;
property DeviceMode: PDeviceMode read GetDeviceMode;
property Duplex: TdxDuplexMode read GetDuplex write SetDuplex;
property FileName: string read FFileName write FFileName;
property Fonts: TStrings read GetFonts;
property Handle: HDC read GetHandle;
property HDeviceMode: THandle read GetHDeviceMode;
property IsDefault: Boolean read GetIsDefault write SetIsDefault;
property IsDeviceModePersistent: Boolean read FIsDeviceModePersistent write FIsDeviceModePersistent;
property IsInitialized: Boolean read GetIsInitialized;
property IsNetwork: Boolean read GetIsNetwork;
property MaxCopies: Longint read FMaxCopies;
property MaxExtentX: Integer index 0 read GetMaxExtents;
property MaxExtentY: Integer index 1 read GetMaxExtents;
property MinExtentX: Integer index 0 read GetMinExtents;
property MinExtentY: Integer index 1 read GetMinExtents;
property Orientation: TdxPrinterOrientation read GetOrientation write SetOrientation;
property PageHeight: Integer read GetPageHeight;
property PageHeightLoMetric: Integer read GetPageHeightLoMetric;
property PageWidth: Integer read GetPageWidth;
property PageWidthLoMetric: Integer read GetPageWidthLoMetric;
property PageNumber: Integer read FPageNumber;
property PaperIndex: Integer read GetPaperIndex write SetPaperIndex;
property PaperCount: Integer read GetPaperCount;
property Papers: TStrings read GetPapers;
property PhysOffsetX: Integer index 0 read GetPhysOffset;
property PhysOffsetY: Integer index 1 read GetPhysOffset;
property PrinterCount: Integer read GetPrinterCount;
property PrinterIndex: Integer read GetPrinterIndex write SetPrinterIndex;
property PrinterInfos[Index: Integer]: TdxPrintDeviceInfo read GetPrinterInfo;
property Printers: TStrings read GetPrinters;
property Printing: Boolean read FPrinting;
property Title: string read FTitle write FTitle;
property OnNewPage: TNotifyEvent read FOnNewPage write FOnNewPage;
property OnPrinterChange: TNotifyEvent read FOnPrinterChange write FOnPrinterChange;
property OnRefresh: TNotifyEvent read FOnRefresh write FOnRefresh;
end;
TdxPaperInfo = class
private
FDMPaper: Integer;
FName: string;
FPrintDevice: TdxPrintDevice;
FSize: TPoint;
function GetSize(Index: Integer): Integer;
procedure SetSize(Index: Integer; Value: Integer);
public
constructor Create(APrintDevice: TdxPrintDevice);
procedure Assign(Source: TdxPaperInfo);
function IsEqual(Source: TdxPaperInfo): Boolean;
property DMPaper: Integer read FDMPaper;
property Height: Integer index 1 read GetSize write SetSize;
property Name: string read FName;
property Size: TPoint read FSize;
property Width: Integer index 0 read GetSize write SetSize;
end;
function dxConnectToNetPrinter(AParentWnd: HWND): Boolean;
function dxDocumentProperties(AParentWnd: HWND): Boolean;
function dxInitPrintDevice(ARaiseException: Boolean): Boolean;
function dxIsAutoSelectBin(const AName: string): Boolean;
function dxIsEnvelopePaper(const AName: string): Boolean;
function dxIsPrintDeviceAllocated: Boolean;
function dxIsPrintDeviceInitialized: Boolean;
function dxPrintDevice: TdxPrintDevice;
procedure dxReleasePrintDevice;
function dxSetPrintDevice(APrintDevice: TdxPrintDevice): TdxPrintDevice;
procedure dxDrawPrinter(ACanvas: TCanvas; ARect: TRect; const AText: string;
AImageList: TCustomImageList; AImageIndex: Integer);
procedure dxGetPrinterList(AStrings: TStrings);
function dxGetDefaultDMPaper: Integer;
function dxGetDefaultPrinter: string;
function dxIsDefaultPrinter(ADevice: PChar ): Boolean;
procedure dxSetDefaultPrinter(ADevice: PChar );
type
TConnectToPrinterDlg = function(hWnd: HWND; Flags: DWORD): THandle; stdcall;
TGetDefaultPrinter = function(pszBuffer: PChar; var cchBuffer: DWORD): BOOL; stdcall;
TGetDefaultPrinterA = function(pszBuffer: PAnsiChar; var cchBuffer: DWORD): BOOL; stdcall;
TGetDefaultPrinterW = function(pszBuffer: PWideChar; var cchBuffer: DWORD): BOOL; stdcall;
TSetDefaultPrinter = function(pszPrinter: PChar): BOOL; stdcall;
TSetDefaultPrinterA = function(pszPrinter: PAnsiChar): BOOL; stdcall;
TSetDefaultPrinterW = function(pszPrinter: PWideChar): BOOL; stdcall;
var
dxPSUseCachedDMPaper: Boolean = True;
const
cMinPaperExtent = 254;
cMaxPaperExtent = 30 * cMinPaperExtent;
{$EXTERNALSYM LOCALE_IPAPERSIZE}
LOCALE_IPAPERSIZE = $0000100A;
implementation
uses
Forms, WinSpool, cxClasses, dxPSUtl, dxPSRes;
const
dxDefaultMaxPaperExtents = 5000;
dxDefaultMinPaperExtents = 500;
DuplexModeMap: array[DMDUP_SIMPLEX..DMDUP_HORIZONTAL] of TdxDuplexMode = (dmSimplex, dmHorizontal, dmVertical);
OrientationMap: array[DMORIENT_PORTRAIT..DMORIENT_LANDSCAPE] of TdxPrinterOrientation = (poPortrait, poLandscape);
PrinterOrientationMap: array[TdxPrinterOrientation] of Integer = (DMORIENT_PORTRAIT, DMORIENT_LANDSCAPE);
var
FPrintDevice: TdxPrintDevice = nil;
FConnectToPrinterDlg: TConnectToPrinterDlg = nil;
FGetDefaultPrinter: TGetDefaultPrinter = nil;
FSetDefaultPrinter: TSetDefaultPrinter = nil;
function DocumentProperties(hWnd: HWND; hPrinter: THandle; pDeviceName: PChar;
pDevModeOutput, pDevModeInput: PDeviceMode; fMode: DWORD): Longint;
overload; stdcall; external winspl name 'DocumentPropertiesA';
function DocumentPropertiesA(hWnd: HWND; hPrinter: THandle; pDeviceName: PAnsiChar;
pDevModeOutput, pDevModeInput: PDeviceModeA; fMode: DWORD): Longint;
overload; stdcall; external winspl name 'DocumentPropertiesA';
function DocumentProperties(hWnd: HWND; hPrinter: THandle; pDeviceName: PWideChar;
pDevModeOutput, pDevModeInput: PDeviceModeW; fMode: DWORD): Longint;
overload; stdcall; external winspl name 'DocumentPropertiesW';
function IsConnectToPrinterDlgInitialized: Boolean;
begin
Result := @FConnectToPrinterDlg <> nil;
end;
function IsGetDefaultPrinterInitialized: Boolean;
begin
Result := @FGetDefaultPrinter <> nil;
end;
function IsSetDefaultPrinterInitialized: Boolean;
begin
Result := @FSetDefaultPrinter <> nil;
end;
{ Memory Management Routines }
function dxAllocMem(ASize: Integer): Pointer;
begin
Result := AllocMem(ASize);
end;
procedure dxFreeMem(var P: Pointer; ASize: Integer);
begin
FreeMem(P, ASize);
P := nil;
end;
{.$DEFINE DEBUG_PRINTDEVICE}
{$IFDEF DEBUG_PRINTDEVICE}
var
LogFile: TextFile;
procedure RewriteLog;
begin
Rewrite(LogFile);
end;
procedure WriteLog(const S: string);
begin
WriteLn(LogFile, S);
end;
{$ENDIF}
function FetchStr(var Str: PChar): PChar;
var
P: PChar;
begin
Result := Str;
if Str = nil then Exit;
P := Str;
while P^ = ' ' do
Inc(P);
Result := P;
while (P^ <> #0) and (P^ <> ',') do
P := StrNextChar(P);
if P^ = ',' then
begin
P^ := #0;
Inc(P);
end;
Str := P;
end;
procedure RaiseError(const Msg: string);
begin
raise EdxPrintDevice.Create(Msg);
end;
function AbortProc(Prn: HDC; Error: Integer): Bool; stdcall;
begin
{$IFDEF DEBUG_PRINTDEVICE}
WriteLog('AbortProc');
{$ENDIF}
// Application.ProcessMessages;
Result := not FPrintDevice.Aborted;
end;
function dxIsPrintDeviceAllocated: Boolean;
begin
Result := FPrintDevice <> nil;
end;
function dxIsPrintDeviceInitialized: Boolean;
begin
Result := dxIsPrintDeviceAllocated and dxPrintDevice.IsInitialized;
end;
function dxPrintDevice: TdxPrintDevice;
begin
if FPrintDevice = nil then FPrintDevice := TdxPrintDevice.Create;
Result := FPrintDevice;
end;
function dxConnectToNetPrinter(AParentWnd: HWND): Boolean;
var
Handle: THandle;
begin
if IsConnectToPrinterDlgInitialized then
begin
Handle := FConnectToPrinterDlg(AParentWnd, 0);
Result := Handle <> 0;
if Result then
begin
ClosePrinter(Handle);
dxPrintDevice.Refresh;
end;
end
else
Result := False;
end;
{.$WARN SYMBOL_DEPRECATED OFF}
function dxDocumentProperties(AParentWnd: HWND): Boolean;
var
HNewDevMode: THandle;
PNewDevMode: PDevMode ;
begin
Result := False;
HNewDevMode := 0;
try
HNewDevMode := CopyDeviceMode(dxPrintDevice.HDeviceMode);
if HNewDevMode <> 0 then
try
PNewDevMode := GlobalLock(HNewDevMode);
try
with dxPrintDevice do
Result := IDOK = DocumentProperties(AParentWnd, FDeviceHandle, CurrentDevice,
PNewDevMode, DeviceMode, DM_IN_PROMPT or DM_OUT_BUFFER or DM_IN_BUFFER);
finally
GlobalUnlock(HNewDevMode);
end;
finally
if Result then
with dxPrintDevice do
begin
while GlobalUnlock(FHDeviceMode) do;
GlobalFree(FHDeviceMode);
FHDeviceMode := HNewDevMode;
FDeviceMode := GlobalLock(FHDeviceMode);
end
else
if HNewDevMode <> 0 then GlobalFree(HNewDevMode);
end;
except
if HNewDevMode <> 0 then GlobalFree(HNewDevMode);
end;
end;
{.$WARN SYMBOL_DEPRECATED ON}
{$HINTS OFF}
function dxInitPrintDevice(ARaiseException: Boolean): Boolean;
var
Stub: HDC;
begin
Result := True;
try
Result := dxPrintDevice.Printers.Count > 0;
if Result then Stub := dxPrintDevice.Handle;
except
Result := False;
if ARaiseException then raise;
end;
end;
{$HINTS ON}
procedure dxReleasePrintDevice;
begin
dxSetPrintDevice(nil).Free;
end;
function dxSetPrintDevice(APrintDevice: TdxPrintDevice): TdxPrintDevice;
begin
Result := FPrintDevice;
FPrintDevice := APrintDevice;
end;
function dxIsAutoSelectBin(const AName: string): Boolean;
begin
Result := Pos(UpperCase(cxGetResourceString(@sdxAuto)), UpperCase(AName)) > 0;
end;
function dxIsEnvelopePaper(const AName: string): Boolean;
begin
Result := Pos(UpperCase(cxGetResourceString(@sdxEnv)), UpperCase(AName)) > 0;
end;
function dxGetDefaultDMPaper: Integer;
const
CachedDMPaper: Integer = -1;
var
Device: string;
HPrinter: THandle;
dwNeeded: DWORD;
PI9: PPrinterInfo9;
begin
if not dxPSUseCachedDMPaper or (CachedDMPaper = -1) then
begin
Result := Windows.DMPAPER_FIRST;
if IsWin2KOrXP then
begin
Device := dxGetDefaultPrinter;
if (Device <> '') and OpenPrinter(PChar(Device), HPrinter, nil) and (HPrinter <> 0) then
try
dwNeeded := 0; {3.03}
if GetPrinter(HPrinter, 9, nil, 0, @dwNeeded) or (dwNeeded <> 0) then
begin
PI9 := GlobalAllocPtr(GPTR, dwNeeded);
if PI9 <> nil then
try
if GetPrinter(HPrinter, 9, PI9, dwNeeded, @dwNeeded) then
if PI9^.DevMode <> nil then
try
Result := PI9^.DevMode^.dmPaperSize;
finally
//GlobalFreePtr(PI9^.DevMode); //TODO: check necessity
end;
finally
GlobalFreePtr(PI9);
end;
end;
finally
ClosePrinter(HPrinter);
end
else
case GetLocaleChar(LOCALE_USER_DEFAULT, LOCALE_IPAPERSIZE, '0') of
'1': Result := Windows.DMPAPER_LETTER;
'5': Result := Windows.DMPAPER_LEGAL;
'8': Result := Windows.DMPAPER_A3;
'9': Result := Windows.DMPAPER_A4;
end;
end;
CachedDMPaper := Result;
end
else
Result := CachedDMPaper;
end;
function dxGetDefaultPrinter: string;
const
MAX_BUFFER_SIZE = 1024;
var
L: DWORD;
Buffer: array[0..MAX_BUFFER_SIZE] of Char;
C: PChar;
begin
Result := '';
L := MAX_BUFFER_SIZE;
FillChar(Buffer, SizeOf(Buffer), 0);
if false and IsGetDefaultPrinterInitialized and FGetDefaultPrinter(@Buffer, L) and
(GetLastError = ERROR_SUCCESS) then
Result := Buffer
else
if GetProfileString('WINDOWS', 'DEVICE', '', Buffer, L) > 0 then
begin
C := @Buffer[0];
Result := FetchStr(C);
end;
end;
function dxIsDefaultPrinter(ADevice: PChar ): Boolean;
begin
Result := StrIComp(PChar(dxGetDefaultPrinter), ADevice) = 0;
end;
procedure dxSetDefaultPrinter(ADevice: PChar );
var
dwNeeded: DWORD;
HPrinter: THandle;
PI2: PPrinterInfo2;
S: string;
begin
if IsSetDefaultPrinterInitialized then // Win2KOrXP
FSetDefaultPrinter(ADevice)
else
if OpenPrinter(ADevice, HPrinter, nil) and (HPrinter <> 0) then
try
dwNeeded := 0; {3.03}
if GetPrinter(HPrinter, 2, nil, 0, @dwNeeded) or (dwNeeded <> 0) then
begin
PI2 := GlobalAllocPtr(GPTR, dwNeeded);
if PI2 <> nil then
try
if GetPrinter(HPrinter, 2, PI2, dwNeeded, @dwNeeded) then
if IsWin95Or98 then // Win9x
begin
PI2^.Attributes := PI2^.Attributes or PRINTER_ATTRIBUTE_DEFAULT;
SetPrinter(HPrinter, 2, PI2, 0);
SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0, LPARAM(PChar('windows')), SMTO_NORMAL, 1000, dwNeeded);
end
else // WinNT or earlier
if (PI2^.pDriverName <> nil) and (PI2^.pPortName <> nil) then
begin
S := PI2^.pPrinterName + ',' + PI2^.pDriverName + ',' + PI2^.pDriverName;
if WriteProfileString('windows', 'device', PChar(S)) then
begin
dwNeeded := Length(S);
SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0, 0, SMTO_NORMAL, 1000, dwNeeded);
end;
end;
finally
GlobalFreePtr(PI2);
end;
end;
finally
ClosePrinter(hPrinter);
end;
end;
procedure dxDrawPrinter(ACanvas: TCanvas; ARect: TRect; const AText: string;
AImageList: TCustomImageList; AImageIndex: Integer);
var
Offset: Integer;
begin
with ACanvas, ARect do
begin
FillRect(ARect);
// Image
InflateRect(ARect, -1, -1);
Offset := (Bottom - Top - AImageList.Height) div 2;
Inc(Left, Offset);
Inc(Top, Offset);
AImageList.Draw(ACanvas, Left, Top, AImageIndex);
// Text
Inc(Offset);
Inc(Left, Offset + AImageList.Width + Offset);
Brush.Style := bsClear;
TextRect(ARect, Left + Offset, Top + Offset, AText);
Brush.Style := bsSolid;
end;
end;
procedure dxGetPrinterList(AStrings: TStrings);
begin
with AStrings do
begin
BeginUpdate;
try
Clear;
if dxPrintDevice.Printers <> nil then
Assign(dxPrintDevice.Printers);
finally
EndUpdate;
end;
end;
end;
{ TdxPrintDeviceInfo }
constructor TdxPrintDeviceInfo.Create(ADriver, ADevice, APort: PChar ;
AnIsDefault, AnIsNetwork: Boolean);
begin
inherited Create;
FDriver := StrNew(ADriver);
FDevice := StrNew(ADevice);
FPort := StrNew(APort);
FIsDefault := AnIsDefault;
FIsNetwork := AnIsNetwork;
end;
destructor TdxPrintDeviceInfo.Destroy;
begin
StrDispose(FPort);
StrDispose(FDevice);
StrDispose(FDriver);
inherited;
end;
function TdxPrintDeviceInfo.IsEqual(ADriver, ADevice, APort: PChar ): Boolean;
begin
Result := (StrIComp(Device, ADevice) = 0) and ((Port = nil) or (APort = nil) or (StrIComp(Port, APort) = 0));
end;
{ TdxPrintDeviceCanvas }
type
TdxPrintDeviceCanvas = class(TCanvas)
private
FPrintDevice: TdxPrintDevice;
protected
procedure CreateHandle; override;
procedure Changing; override;
procedure UpdateFont;
public
constructor Create(APrintDevice: TdxPrintDevice);
end;
constructor TdxPrintDeviceCanvas.Create(APrintDevice: TdxPrintDevice);
begin
inherited Create;
FPrintDevice := APrintDevice;
end;
procedure TdxPrintDeviceCanvas.CreateHandle;
begin
FPrintDevice.SetState(psHandleIC);
UpdateFont;
Handle := FPrintDevice.FDC;
end;
procedure TdxPrintDeviceCanvas.Changing;
begin
FPrintDevice.CheckPrinting(True);
inherited Changing;
UpdateFont;
end;
procedure TdxPrintDeviceCanvas.UpdateFont;
var
FontSize: Integer;
begin
if GetDeviceCaps(FPrintDevice.FDC, LOGPIXELSY) <> Font.PixelsPerInch then
begin
FontSize := Font.Size;
Font.PixelsPerInch := GetDeviceCaps(FPrintDevice.FDC, LOGPIXELSY);
Font.Size := FontSize;
end;
end;
{ TdxPaperInfo }
constructor TdxPaperInfo.Create(APrintDevice: TdxPrintDevice);
begin
inherited Create;
FPrintDevice := APrintDevice;
end;
function TdxPaperInfo.IsEqual(Source: TdxPaperInfo): Boolean;
begin
Result := (DMPaper = Source.DMPaper) and (FName = Source.Name) and
dxPSUtl.ArePointsEqual(Size, Source.Size);
end;
procedure TdxPaperInfo.Assign(Source: TdxPaperInfo);
begin
FDMPaper := Source.FDMPaper;
FName := Source.FName;
FSize := Source.FSize;
end;
function TdxPaperInfo.GetSize(Index: Integer): Integer;
begin
with Size do
if Index = 0 then
Result := X
else
Result := Y;
end;
procedure TdxPaperInfo.SetSize(Index: Integer; Value: Integer);
begin
if DMPaper < DMPAPER_USER then Exit;
if Index = 0 then
begin
FSize.X := Value;
if (FPrintDevice <> nil) and (FPrintDevice.FDeviceMode <> nil) then
FPrintDevice.DeviceMode^.dmPaperWidth := FSize.X;
end
else
begin
FSize.Y := Value;
if (FPrintDevice <> nil) and (FPrintDevice.FDeviceMode <> nil) then
FPrintDevice.DeviceMode^.dmPaperLength := FSize.Y;
end;
end;
{ TdxPrintDevice }
constructor TdxPrintDevice.Create;
begin
inherited Create;
FAutoRefresh := {True; //}False;
FIsDeviceModePersistent := True;
FPrinterIndex := -MaxInt;
FWindowHandle := dxPSUtl.dxAllocateHWnd(WndProc);
end;
destructor TdxPrintDevice.Destroy;
begin
if Printing then EndDoc;
DeselectHandles;
SetState(psNoHandle);
dxPSUtl.dxDeallocatehWnd(FWindowHandle);
FWindowHandle := 0;
ClosePrintDevice;
FreeAndNilPrinters;
inherited;
end;
procedure TdxPrintDevice.Abort;
begin
CheckPrinting(True);
AbortDoc(Canvas.Handle);
FAborted := True;
EndDoc;
end;
function TdxPrintDevice.BeginDoc: Integer;
var
DocInfo: TDocInfo;
begin
Application.ProcessMessages;
{$IFDEF DEBUG_PRINTDEVICE}
RewriteLog;
WriteLog('BeginDoc');
{$ENDIF}
CheckPrinting(False);
SetState(psNoHandle);
SetState(psHandleDC);
Canvas.Refresh;
TdxPrintDeviceCanvas(Canvas).UpdateFont;
FPrinting := True;
FAborted := False;
FPageNumber := 1;
FillChar(DocInfo, SizeOf(DocInfo), 0);
with DocInfo do
begin
cbSize := SizeOf(DocInfo);
lpszDocName := PChar(Title);
if FileName <> '' then lpszOutput := PChar(FileName);
end;
SetAbortProc(FDC, AbortProc);
Result := StartDoc(FDC, DocInfo);
if Result > 0 then
StartPage(FDC)
else
begin
FPrinting := False;
FAborted := False;
SetState(psNoHandle);
FPageNumber := 0;
end;
end;
procedure TdxPrintDevice.EndDoc;
begin
{$IFDEF DEBUG_PRINTDEVICE}
WriteLog('EndDoc');
{$ENDIF}
CheckPrinting(True);
EndPage(FDC);
if not Aborted then Windows.EndDoc(FDC);
FPrinting := False;
FAborted := False;
SetState(psNoHandle);
FPageNumber := 0;
end;
procedure TdxPrintDevice.NewPage;
begin
{$IFDEF DEBUG_PRINTDEVICE}
WriteLog('NewPage');
{$ENDIF}
CheckPrinting(True);
EndPage(FDC);
Inc(FPageNumber);
Application.ProcessMessages;
DoNewPage;
ResetDC(False);
StartPage(FDC);
Canvas.Refresh;
end;
function TdxPrintDevice.FindPrintDevice(ADevice, APort: PChar ): Integer;
begin
for Result := 0 to Printers.Count - 1 do
if PrinterInfos[Result].IsEqual(nil, ADevice, APort) then Exit;
Result := -1;
end;
function TdxPrintDevice.IsDeviceModeChanged: Boolean;
begin
Result := FDeviceModeChanged;
end;
procedure TdxPrintDevice.Refresh;
var
ADevice, APort: PChar ;
APrinterIndex: Integer;
AHDeviceMode: THandle;
begin
ADevice := StrNew(FCurrentDevice);
try
APort := StrNew(FCurrentPort);
try
AHDeviceMode := 0;
if FHDeviceMode <> 0 then AHDeviceMode := CopyDeviceMode(FHDeviceMode);
try
ClosePrintDevice;
FreeAndNilPrinters;
GetPrinters;
if AHDeviceMode <> 0 then
begin
APrinterIndex := FindPrintDevice(ADevice, APort);
if APrinterIndex <> -1 then
begin
OpenPrintDevice(APrinterIndex);
if FHDeviceMode <> 0 then
begin
while GlobalUnLock(FHDeviceMode) do;
GlobalFree(FHDeviceMode);
FDeviceMode := nil;
FHDeviceMode := CopyDeviceMode(AHDeviceMode);
FDeviceMode := GlobalLock(FHDeviceMode);
end;
end
else
if Printers.Count > 0 then GetPrinterIndex;
end;
finally
if AHDeviceMode <> 0 then GlobalFree(AHDeviceMode);
end;
finally
StrDispose(APort);
end;
finally
StrDispose(ADevice);
end;
DoRefresh;
end;
procedure TdxPrintDevice.ResetDC(IsForced: Boolean);
var
ACanvas: TCanvas;
ABrushBitmap: TBitmap;
procedure SaveCanvas;
begin
ACanvas := TdxPrintDeviceCanvas.Create(Self);
with ACanvas do
begin
OnChanging := Canvas.OnChanging;
OnChange := Canvas.OnChange;
Canvas.OnChanging := nil;
Canvas.OnChange := nil;
Brush := Canvas.Brush;
ABrushBitmap := nil;
if Brush.Bitmap <> nil then ABrushBitmap := Brush.Bitmap;
Font := Canvas.Font;
Pen := Canvas.Pen;
PenPos := Canvas.PenPos;
CopyMode := Canvas.CopyMode;
end;
end;
procedure RestoreCanvas;
begin
with Canvas do
begin
Brush := ACanvas.Brush;
if ABrushBitmap <> nil then Brush.Bitmap := ABrushBitmap;
Font := ACanvas.Font;
Pen := ACanvas.Pen;
PenPos := ACanvas.PenPos;
CopyMode := ACanvas.CopyMode;
OnChanging := ACanvas.OnChanging;
OnChange := ACanvas.OnChange;
end;
ACanvas.Free;
end;
begin
if IsDeviceModeChanged or IsForced then
begin
FDeviceModeChanged := False;
SaveCanvas;
try
if FDeviceMode <> nil then
Windows.ResetDC(FDC, FDeviceMode^);
finally
RestoreCanvas;
end;
end;
end;
procedure TdxPrintDevice.ResetPrintDevice;
var
Index: Integer;
begin
Index := PrinterIndex;
ClosePrintDevice;
OpenPrintDevice(Index);
end;
function TdxPrintDevice.FindBin(ABin: Integer): Integer;
begin
if Bins <> nil then
Result := Bins.IndexOfObject(TObject(ABin))
else
Result := -1;
end;
function TdxPrintDevice.FindBin(const AName: string): Integer;
begin
if Bins <> nil then
Result := Bins.IndexOf(AName)
else
Result := -1;
end;
function TdxPrintDevice.IsAutoSelectBin(AIndex: Integer): Boolean;
begin
Result := (Bins <> nil) and (AIndex > -1) and (AIndex < Bins.Count) and
dxIsAutoSelectBin(Bins[AIndex]);
end;
function TdxPrintDevice.IsUserPaperSource(AIndex: Integer): Boolean;
begin
Result := (Bins <> nil) and (AIndex > -1) and (AIndex < Bins.Count) and
(Integer(Papers.Objects[AIndex]) >= DMBIN_USER);
end;
function TdxPrintDevice.SelectBin(Value: Integer): Boolean;
var
Index: Integer;
begin
Index := FindBin(Value);
Result := Index > -1;
if Result then BinIndex := Index;
end;
function TdxPrintDevice.SelectBin(const AName: string): Boolean;
var
Index: Integer;
begin
Index := FindBin(AName);
Result := Index > -1;
if Result then BinIndex := Index;
end;
function TdxPrintDevice.FindPaper(ADMPaper: Integer): Integer;
begin
if Papers <> nil then
for Result := 0 to Papers.Count - 1 do
if TdxPaperInfo(Papers.Objects[Result]).DMPaper = ADMPaper then
Exit;
Result := -1;
end;
function TdxPrintDevice.FindPaper(const AName: string): Integer;
begin
if Papers <> nil then
Result := Papers.IndexOf(AName)
else
Result := -1;
end;
function TdxPrintDevice.FindPaper(const ASize: TPoint): Integer;
begin
if Papers <> nil then
begin
for Result := 0 to Papers.Count - 1 do
if dxPSUtl.ArePointsEqual(TdxPaperInfo(Papers.Objects[Result]).Size, ASize) then
Exit;
Result := Papers.Count - 1;
end
else
Result := -1;
end;
function TdxPrintDevice.FindPaper(AWidth, AHeight: Integer): Integer;
begin
Result := FindPaper(MakePoint(AWidth, AHeight));
end;
function TdxPrintDevice.IsEnvelopePaper(AIndex: Integer): Boolean;
begin
Result := (Papers <> nil) and (AIndex > -1) and (AIndex < Papers.Count) and
dxIsEnvelopePaper(Papers[AIndex]);
end;
function TdxPrintDevice.IsUserPaperSize(AIndex: Integer): Boolean;
var
PaperInfo: TdxPaperInfo;
begin
Result := (Papers <> nil) and (AIndex > -1) and (AIndex < Papers.Count);
if Result then
begin
PaperInfo := TdxPaperInfo(Papers.Objects[AIndex]);
Result := (PaperInfo.DMPaper >= DMPAPER_USER) or
(Pos(cxGetResourceString(@sdxCustom), PaperInfo.Name) > 0);
end;
end;
function TdxPrintDevice.SelectPaper(ADMPaper: Integer): Boolean;
var
Index: Integer;
begin
Index := FindPaper(ADMPaper);
Result := Index > -1;
if Result then PaperIndex := Index;
end;
function TdxPrintDevice.SelectPaper(const AName: string): Boolean;
var
Index: Integer;
begin
Index := FindPaper(AName);
Result := Index > -1;
if Result then PaperIndex := Index;
end;
function TdxPrintDevice.SelectPaper(var AWidth, AHeight: Integer): Boolean;
var
Index: Integer;
begin
Index := FindPaper(AWidth, AHeight);
Result := Index > -1;
if Result then
begin
PaperIndex := Index; // setting FDeviceModeChanged := True;
if FDeviceMode <> nil then
if PaperIndex <> Papers.Count - 1 then
begin
DeviceMode^.dmPaperWidth := 0;
DeviceMode^.dmPaperLength := 0;
end
else
InternalSelectPaperBySize(AWidth, AHeight)
end;
end;
function TdxPrintDevice.IsSupportColoration: Boolean;
begin
Result := 1 = WinSpool.DeviceCapabilities(CurrentDevice, CurrentPort, DC_COLORDEVICE, nil, nil);
end;
function TdxPrintDevice.IsSupportDuplex: Boolean;
begin
Result := 1 = WinSpool.DeviceCapabilities(CurrentDevice, CurrentPort, DC_DUPLEX, nil, nil);
end;
procedure TdxPrintDevice.DoNewPage;
begin
if Assigned(FOnNewPage) then FOnNewPage(Self)
end;
procedure TdxPrintDevice.DoPrinterChanged;
begin
if Assigned(FOnPrinterChange) then FOnPrinterChange(Self);
end;
procedure TdxPrintDevice.DoRefresh;
begin
if Assigned(FOnRefresh) then FOnRefresh(Self);
end;
function TdxPrintDevice.GetBinIndex: Integer;
begin
if FDeviceMode <> nil then
begin
Result := FindBin(FDeviceMode^.dmDefaultSource);
if (Result = -1) and (FBins <> nil) and (FBins.Count <> 0) then
Result := 0;
end
else
Result := 0;
end;
function TdxPrintDevice.GetBins: TStrings;
const
BinSize = SizeOf(Word);
BinNameSize = 24;
type
TdxBin = Word;
TdxBins = array[0..0] of TdxBin;
PdxBins = ^TdxBins;
TdxBinName = array[0..BinNameSize - 1] of Char;
TdxBinNames = array[0..0] of TdxBinName;
PdxBinNames = ^TdxBinNames;
var
BinCount: Integer;
BinValues: PdxBins ;
BinNames: PdxBinNames ;
I: Integer;
BinName: string;
begin
if FBins = nil then
try
if Printers.Count > 0 then
begin
GetPrinterIndex;
if FDeviceMode = nil then
begin
Result := nil;
Exit;
end;
BinCount := DeviceCapabilities(CurrentDevice, CurrentPort, DC_BINS, nil, nil);
if BinCount > 0 then
begin
BinValues := AllocMem(BinSize * BinCount);
try
if DeviceCapabilities(CurrentDevice, CurrentPort, DC_BINS, PChar(BinValues), nil) <> -1 then
begin
BinNames := AllocMem(BinNameSize * BinCount);
try
if DeviceCapabilities(CurrentDevice, CurrentPort, DC_BINNAMES, PChar(BinNames), nil) <> -1 then
begin
FBins := TStringList.Create;
for I := 0 to BinCount - 1 do
begin
BinName := BinNames^[I];
FBins.AddObject(BinName, TObject(BinValues^[I]));
end;
end;
finally
FreeMem(BinNames, BinNameSize * BinCount);
end;
end;
finally
FreeMem(BinValues, BinSize * BinCount);
end;
end;
end
else
begin
FBins := TStringList.Create;
FBins.AddObject(cxGetResourceString(@sdxDefaultTray), TObject(DMBIN_USER));
end;
except
FreeAndNil(FBins);
raise;
end;
Result := FBins;
end;
function TdxPrintDevice.GetCanvas: TCanvas;
begin
if FCanvas = nil then FCanvas := TdxPrintDeviceCanvas.Create(Self);
Result := FCanvas;
end;
function TdxPrintDevice.GetCollate: Boolean;
const
CollationMap: array[DMCOLLATE_FALSE..DMCOLLATE_TRUE] of Boolean = (False, True);
begin
Result := False;
if Printers.Count > 0 then
begin
GetPrinterIndex;
if FDeviceMode <> nil then
Result := CollationMap[FDeviceMode^.dmCollate];
end;
end;
function TdxPrintDevice.GetColorMode: Boolean;
begin
Result := False;
if Printers.Count > 0 then
begin
GetPrinterIndex;
if FDeviceMode <> nil then
Result := FDeviceMode^.dmColor = DMCOLOR_COLOR;
end;
end;
function TdxPrintDevice.GetCurrentDevice: PChar ;
begin
Result := nil;
if Printers.Count > 0 then
begin
GetPrinterIndex;
if FHDeviceMode <> 0 then
Result := FCurrentDevice;
end;
end;
function TdxPrintDevice.GetCurrentDriver: PChar ;
begin
Result := nil;
if Printers.Count > 0 then
begin
GetPrinterIndex;
if FHDeviceMode <> 0 then
Result := FCurrentDriver;
end;
end;
function TdxPrintDevice.GetCurrentPort: PChar ;
begin
Result := nil;
if Printers.Count > 0 then
begin
GetPrinterIndex;
if FHDeviceMode <> 0 then
Result := FCurrentPort;
end;
end;
function TdxPrintDevice.GetDefaultDMPaper: Integer;
begin
if Printers.Count > 0 then
begin
GetPrinterIndex;
if FDeviceMode <> nil then
Result := DeviceMode^.dmPaperSize
else
Result := Windows.DMPAPER_FIRST;
end
else
Result := Windows.DMPAPER_FIRST;
end;
function TdxPrintDevice.GetDeviceMode: PDeviceMode;
begin
if Printers.Count > 0 then
begin
GetPrinterIndex;
Result := FDeviceMode;
end
else
Result := nil;
end;
function TdxPrintDevice.GetDuplex: TdxDuplexMode;
begin
Result := dmSimplex;
if Printers.Count > 0 then
begin
GetPrinterIndex;
if FDeviceMode <> nil then
Result := DuplexModeMap[DeviceMode^.dmDuplex];
end;
end;
function EnumFontsProc(var LogFont: TLogFont; var TextMetric: TTextMetric;
FontType: DWORD; Data: LPARAM): Integer; stdcall;
begin
TStrings(Data).Add(LogFont.lfFaceName);
Result := 1;
end;
function TdxPrintDevice.GetFonts: TStrings;
begin
if FFonts = nil then
try
SetState(psHandleIC);
FFonts := TStringList.Create;
EnumFonts(FDC, nil, @EnumFontsProc, Pointer(FFonts));
except
FreeAndNil(FFonts);
raise;
end;
Result := FFonts;
end;
function TdxPrintDevice.GetHandle: HDC;
begin
SetState(psHandleIC);
Result := FDC;
end;
function TdxPrintDevice.GetHDeviceMode: THandle;
begin
if Printers.Count > 0 then
begin
GetPrinterIndex;
Result := FHDeviceMode;
end
else
Result := 0;
end;
function TdxPrintDevice.GetIsDefault: Boolean;
begin
if PrinterIndex <> -1 then
Result := PrinterInfos[PrinterIndex].IsDefault
else
Result := False;
end;
function TdxPrintDevice.GetIsInitialized: Boolean;
begin
Result := FPrinters <> nil;
end;
function TdxPrintDevice.GetIsNetwork: Boolean;
begin
if PrinterIndex <> -1 then
Result := PrinterInfos[PrinterIndex].IsNetwork
else
Result := False;
end;
function TdxPrintDevice.GetMaxExtents(Index: Integer): Integer;
begin
if Printers.Count > 0 then
begin
GetPrinterIndex;
if Index = 0 then
Result := LOWORD(FMaxExtents)
else
Result := HIWORD(FMaxExtents);
end
else
Result := dxDefaultMaxPaperExtents;
end;
function TdxPrintDevice.GetMinExtents(Index: Integer): Integer;
begin
if Printers.Count > 0 then
begin
GetPrinterIndex;
if Index = 0 then
Result := LOWORD(FMinExtents)
else
Result := HIWORD(FMinExtents);
end
else
Result := dxDefaultMinPaperExtents;
end;
function TdxPrintDevice.GetNumCopies: Integer;
begin
Result := 0;
if Printers.Count > 0 then
begin
GetPrinterIndex;
if FDeviceMode <> nil then
Result := FDeviceMode^.dmCopies;
end;
end;
function TdxPrintDevice.GetOrientation: TdxPrinterOrientation;
begin
Result := poPortrait;
if Printers.Count > 0 then
begin
GetPrinterIndex;
if FDeviceMode <> nil then
if FDeviceMode^.dmOrientation = DMORIENT_LANDSCAPE then
Result := poLandscape;
end;
end;
function TdxPrintDevice.GetPageHeight: Integer;
begin
SetState(psHandleIC);
Result := GetDeviceCaps(FDC, VertRes);
end;
function TdxPrintDevice.GetPageHeightLoMetric: Integer;
begin
SetState(psHandleIC);
Result := 10 * GetDeviceCaps(FDC, VertSize);
end;
function TdxPrintDevice.GetPageWidth: Integer;
begin
SetState(psHandleIC);
Result := GetDeviceCaps(FDC, HorzRes);
end;
function TdxPrintDevice.GetPageWidthLoMetric: Integer;
begin
SetState(psHandleIC);
Result := 10 * GetDeviceCaps(FDC, HorzSize);
end;
function TdxPrintDevice.GetPaperCount: Integer;
begin
if FPapers <> nil then
Result := FPapers.Count
else
Result := 0;
end;
function TdxPrintDevice.GetPaperIndex: Integer;
begin
if FDeviceMode <> nil then
begin
Result := FindPaper(FDeviceMode^.dmPaperSize);
if (Result = -1) and (FPapers <> nil) and (FPapers.Count > 0) then
Result := 0;
end
else
Result := 0;
end;
function TdxPrintDevice.GetPapers: TStrings;
const
PaperNameSize = 64;
PaperValueSize = SizeOf(Word);
PaperSizeSize = SizeOf(TPoint);
type
TdxPaperSize = TPoint;
TdxPaperSizes = array[0..0] of TdxPaperSize;
PdxPaperSizes = ^TdxPaperSizes;
TdxPaperValue = Word;
TdxPaperValues = array[0..0] of TdxPaperValue;
PdxPaperValues = ^TdxPaperValues;
TdxPaperName = array[0..PaperNameSize - 1] of Char;
TdxPaperNames = array[0..0] of TdxPaperName;
PdxPaperNames = ^TdxPaperNames;
var
HasStandardPapers: Boolean;
PaperCount: Integer;
PaperNames: PdxPaperNames ;
PaperValues: PdxPaperValues ;
PaperSizes: PdxPaperSizes ;
I: Integer;
Paper: TdxPaperInfo;
begin
if FPapers = nil then
try
HasStandardPapers := False;
if Printers.Count > 0 then
begin
GetPrinterIndex;
if DeviceMode = nil then
begin
Result := nil;
Exit;
end;
PaperCount := DeviceCapabilities(CurrentDevice, CurrentPort, DC_PAPERNAMES, nil, nil);
if PaperCount > 0 then
begin
PaperNames := AllocMem(PaperNameSize * PaperCount);
try
if DeviceCapabilities(CurrentDevice, CurrentPort, DC_PAPERNAMES, PChar(PaperNames), nil) <> -1 then
begin
PaperValues := AllocMem(PaperValueSize * PaperCount);
try
if DeviceCapabilities(CurrentDevice, CurrentPort, DC_PAPERS, PChar(PaperValues), nil) <> -1 then
begin
PaperSizes := AllocMem(PaperSizeSize * PaperCount);
try
if DeviceCapabilities(CurrentDevice, CurrentPort, DC_PAPERSIZE, PChar(PaperSizes), nil) <> -1 then
begin
HasStandardPapers := True;
FPapers := TStringList.Create;
for I := 0 to PaperCount - 1 do
begin
Paper := TdxPaperInfo.Create(Self);
with Paper do
begin
FSize := PaperSizes^[I];
FDMPaper := PaperValues^[I];
FName := PaperNames^[I];
end;
FPapers.AddObject(Paper.Name, Paper);
end;
if Pos(cxGetResourceString(@sdxCustom), FPapers[PaperCount - 1]) = 0 then
begin
Paper := TdxPaperInfo.Create(Self);
with Paper do
begin
FSize := TdxPaperInfo(FPapers.Objects[0]).Size;
FDMPaper := DMPAPER_USER;
FName := cxGetResourceString(@sdxCustomSize);
end;
FPapers.AddObject(Paper.Name, Paper);
end;
end;
finally
FreeMem(PaperSizes, PaperSizeSize * PaperCount);
end;
end;
finally
FreeMem(PaperValues, PaperValueSize * PaperCount);
end;
end;
finally
FreeMem(PaperNames, PaperNameSize * PaperCount);
end;
end;
end;
if not HasStandardPapers then
begin
FPapers := TStringList.Create;
Paper := TdxPaperInfo.Create(Self);
with Paper do
begin
FSize := Point(2100, 2970); {A4} // TODO: use default locale paper
FDMPaper := DMPAPER_USER;
FName := cxGetResourceString(@sdxCustomSize);
end;
FPapers.AddObject(Paper.Name, Paper);
end;
except
FreeAndNil(FPapers);
raise;
end;
Result := FPapers;
end;
function TdxPrintDevice.GetPhysOffset(Index: Integer): Integer;
const
PhysicalOffsets: array[0..1] of Integer = (PHYSICALOFFSETX, PHYSICALOFFSETY);
begin
if Printers.Count > 0 then
begin
GetPrinterIndex;
try
Result := GetDeviceCaps(Handle, PhysicalOffsets[Index]);
except
Result := 0;
end;
end
else
Result := 0;
end;
function TdxPrintDevice.GetPrinterCount: Integer;
begin
if FPrinters <> nil then
Result := FPrinters.Count
else
Result := 0;
end;
function TdxPrintDevice.GetPrinterIndex: Integer;
begin
if FPrinterIndex = -MaxInt then SetToDefaultPrintDevice;
Result := FPrinterIndex;
end;
function TdxPrintDevice.GetPrinterInfo(Index: Integer): TdxPrintDeviceInfo;
begin
if (FPrinters <> nil) and (Index >= 0) and (Index < FPrinters.Count) then
Result := TdxPrintDeviceInfo(FPrinters.Objects[Index])
else
Result := nil;
end;
function TdxPrintDevice.GetPrinters: TStrings;
function IsDefaultDevice(AnAttributes: DWORD): Boolean;
begin
Result := AnAttributes and PRINTER_ATTRIBUTE_DEFAULT = PRINTER_ATTRIBUTE_DEFAULT;
end;
function IsNetworkDevice(AnAttributes: DWORD): Boolean;
begin
Result := AnAttributes and PRINTER_ATTRIBUTE_NETWORK = PRINTER_ATTRIBUTE_NETWORK;
end;
procedure GetAsPrinterInfo4(var AnOffset: Integer; ABuffer: PChar);
var
PrintDeviceInfo: TdxPrintDeviceInfo;
begin
Inc(ABuffer, AnOffset);
with PPrinterInfo4(ABuffer)^ do
begin
PrintDeviceInfo := TdxPrintDeviceInfo.Create('', pPrinterName, '', dxIsDefaultPrinter(pPrinterName), IsNetworkDevice(Attributes));
FPrinters.AddObject(pPrinterName, PrintDeviceInfo);
end;
Inc(AnOffset, SizeOf(TPrinterInfo4));
end;
procedure GetAsPrinterInfo5(var AnOffset: Integer; ABuffer: PChar);
var
LineCur, PortName: PChar;
PrintDeviceTitle: string;
PrintDeviceInfo: TdxPrintDeviceInfo;
begin
Inc(ABuffer, AnOffset);
with PPrinterInfo5(ABuffer)^ do
begin
LineCur := pPortName;
PortName := FetchStr(LineCur);
while PortName^ <> #0 do
begin
PrintDeviceTitle := Format(cxGetResourceString(@sdxDeviceOnPort), [pPrinterName, PortName]);
PrintDeviceInfo := TdxPrintDeviceInfo.Create(nil, pPrinterName, PortName, dxIsDefaultPrinter(pPrinterName), IsNetworkDevice(Attributes));
FPrinters.AddObject(PrintDeviceTitle, PrintDeviceInfo);
PortName := FetchStr(LineCur);
end;
end;
Inc(AnOffset, SizeOf(TPrinterInfo5));
end;
const
Levels: array[Boolean] of DWORD = (5, 4);
Flags: array[Boolean] of DWORD = (PRINTER_ENUM_LOCAL, PRINTER_ENUM_CONNECTIONS or PRINTER_ENUM_LOCAL);
var
Level, Flag, Count, NumInfo: DWORD;
Buffer: Pointer;
Offset, I: Integer;
begin
if FPrinters = nil then
begin
FPrinters := TStringList.Create;
try
Level := Levels[dxPSGlbl.IsWinNT];
Flag := Flags[dxPSGlbl.IsWinNT];
Count := 0;
EnumPrinters(Flag, nil, Level, nil, 0, Count, NumInfo);
if Count <> 0 then
begin
Buffer := dxAllocMem(Count);
try
if EnumPrinters(Flag, nil, Level, Buffer, Count, Count, NumInfo) then
begin
Offset := 0;
for I := 0 to NumInfo - 1 do
if Level = 4 then
GetAsPrinterInfo4(Offset, Buffer)
else
GetAsPrinterInfo5(Offset, Buffer);
end;
finally
dxFreeMem(Buffer, Count);
end;
end;
except
FreeAndNil(FPrinters);
raise;
end;
end;
Result := FPrinters;
end;
procedure TdxPrintDevice.SetBinIndex(Value: Integer);
begin
if (FDeviceMode <> nil) and (Bins <> nil) and (Value > -1) and (Value < Bins.Count) then
begin
if FDeviceMode^.dmDefaultSource <> Value then
begin
FDeviceMode^.dmDefaultSource := Integer(Bins.Objects[Value]);
FDeviceMode^.dmFields := FDeviceMode^.dmFields or DM_DEFAULTSOURCE;
FDeviceModeChanged := True;
end;
end;
end;
procedure TdxPrintDevice.SetCollate(Value: Boolean);
const
Collations: array[Boolean] of ShortInt = (DMCOLLATE_FALSE, DMCOLLATE_TRUE);
begin
//CheckPrinting(False);
if Printers.Count > 0 then
begin
GetPrinterIndex;
if FDeviceMode <> nil then
begin
FDeviceMode^.dmCollate := Collations[Value];
FDeviceMode^.dmFields := FDeviceMode^.dmFields or DM_COLLATE;
FDeviceModeChanged := True;
end;
end;
end;
procedure TdxPrintDevice.SetColorMode(Value: Boolean);
const
ColorModes: array[Boolean] of ShortInt = (DMCOLOR_MONOCHROME, DMCOLOR_COLOR);
begin
//CheckPrinting(False);
if Printers.Count > 0 then
begin
GetPrinterIndex;
if FDeviceMode <> nil then
begin
FDeviceMode^.dmColor := ColorModes[Value];
FDeviceMode^.dmFields := FDeviceMode^.dmFields or DM_COLOR;
FDeviceModeChanged := True;
end;
end;
end;
procedure TdxPrintDevice.SetDuplex(Value: TdxDuplexMode);
const
DuplexModeMap: array[TdxDuplexMode] of UINT = (DMDUP_SIMPLEX, DMDUP_VERTICAL, DMDUP_HORIZONTAL);
begin
//CheckPrinting(False);
if Printers.Count > 0 then
begin
GetPrinterIndex;
if (FDeviceMode <> nil) and IsSupportDuplex then
begin
FDeviceMode^.dmDuplex := DuplexModeMap[Value];
FDeviceMode^.dmFields := FDeviceMode^.dmFields or DM_DUPLEX;
FDeviceModeChanged := True;
end;
end;
end;
procedure TdxPrintDevice.SetIsDefault(Value: Boolean);
var
I: Integer;
begin
if (PrinterIndex <> -1) and (IsDefault <> Value) then
begin
for I := 0 to Printers.Count - 1 do
PrinterInfos[I].IsDefault := False;
dxSetDefaultPrinter(CurrentDevice);
end
end;
procedure TdxPrintDevice.SetNumCopies(Value: Integer);
begin
CheckPrinting(False);
if Printers.Count > 0 then
begin
GetPrinterIndex;
if FDeviceMode <> nil then
begin
FDeviceMode^.dmCopies := Value;
FDeviceMode^.dmFields := FDeviceMode^.dmFields or DM_COPIES;
FDeviceModeChanged := True;
end;
end;
end;
procedure TdxPrintDevice.SetOrientation(Value: TdxPrinterOrientation);
begin
//CheckPrinting(False);
if Printers.Count > 0 then
begin
GetPrinterIndex;
if FDeviceMode <> nil then
begin
FDeviceMode^.dmOrientation := PrinterOrientationMap[Value];
FDeviceMode^.dmFields := FDeviceMode^.dmFields or DM_ORIENTATION;
FDeviceModeChanged := True;
end;
end;
end;
procedure TdxPrintDevice.SetPaperIndex(Value: Integer);
begin
if (FDeviceMode <> nil) and (Papers <> nil) and (Value > -1) and (Value < Papers.Count) then
begin
FDeviceMode^.dmPaperSize := TdxPaperInfo(Papers.Objects[Value]).DMPaper;
FDeviceMode^.dmFields := FDeviceMode^.dmFields or DM_PAPERSIZE;
if Value = Papers.Count - 1 then
FDeviceMode^.dmFields := FDeviceMode^.dmFields or DM_PAPERWIDTH or DM_PAPERLENGTH;
FDeviceModeChanged := True;
end;
end;
procedure TdxPrintDevice.SetPrinterCapabilities(Value: Integer);
begin
FCapabilities := [];
if Value and DM_ORIENTATION <> 0 then Include(FCapabilities, pcOrientation);
if Value and DM_COPIES <> 0 then Include(FCapabilities, pcCopies);
if Value and DM_COLLATE <> 0 then Include(FCapabilities, pcCollation);
// if Value and DM_DUPLEX <> 0 then Include(FCapabilities, pcDuplex);
// if Value and DM_COLLATE <> 0 then Include(FCapabilities, pcColor);
end;
procedure TdxPrintDevice.SetPrinterIndex(Value: Integer);
begin
CheckPrinting(False);
if (Value < -1) or (Value >= Printers.Count) then
RaiseError(cxGetResourceString(@sdxPrinterIndexError))
else
if Value = -1 then
begin
FPrinterIndex := -MaxInt;
GetPrinterIndex;
end
else
OpenPrintDevice(Value);
SetState(psNoHandle);
end;
procedure TdxPrintDevice.CheckPrinting(Value: Boolean);
begin
if Printing <> Value then
if Value then
RaiseError(cxGetResourceString(@sdxNotPrinting))
else
RaiseError(cxGetResourceString(@sdxPrinting));
end;
procedure TdxPrintDevice.ClosePrintDevice;
begin
StrDispose(FCurrentDevice);
FCurrentDevice := nil;
StrDispose(FCurrentDriver);
FCurrentDriver := nil;
StrDispose(FCurrentPort);
FCurrentPort := nil;
FreeAndNilBins;
FreeAndNilFonts;
FreeAndNilPapers;
if FHDeviceMode <> 0 then
begin
while GlobalUnlock(FHDeviceMode) do;
GlobalFree(FHDeviceMode);
//Marshal.DestroyStructure(DeviceMode, TypeOf(TDeviceMode));
FHDeviceMode := 0;
FDeviceMode := nil;
end;
if FDeviceHandle <> 0 then
begin
ClosePrinter(FDeviceHandle);
FDeviceHandle := 0;
end;
SetState(psNoHandle);
FreeAndNilCanvas;
FPrinterIndex := -MaxInt;
end;
procedure TdxPrintDevice.DeselectHandles;
begin
if FDC <> 0 then
begin
SelectObject(FDC, GetStockObject(BLACK_PEN));
SelectObject(FDC, GetStockObject(HOLLOW_BRUSH));
SelectObject(FDC, GetStockObject(SYSTEM_FONT));
end;
end;
procedure TdxPrintDevice.FixMinMaxExtents;
var
I: Integer;
MaxSize, MinSize, PaperSize: TPoint;
begin
if (FMaxExtents = -1) or (FMaxExtents = 0) then
FMaxExtents := SetLoHiWords(FMaxExtents, cMaxPaperExtent, cMaxPaperExtent);
if (FMinExtents = -1) or (FMinExtents = 0) then
FMinExtents := SetLoHiWords(FMinExtents, cMinPaperExtent, cMinPaperExtent);
if Papers <> nil then
begin
MaxSize := Point(LoWord(FMaxExtents), HiWord(FMaxExtents));
MinSize := Point(LoWord(FMinExtents), HiWord(FMinExtents));
for I := 0 to Papers.Count - 1 do
begin
PaperSize := TdxPaperInfo(Papers.Objects[I]).Size;
if PaperSize.X < MinSize.X then MinSize.X := PaperSize.X;
if PaperSize.X > MaxSize.X then MaxSize.X := PaperSize.X;
if PaperSize.Y < MinSize.Y then MinSize.Y := PaperSize.Y;
if PaperSize.Y > MaxSize.Y then MaxSize.Y := PaperSize.Y;
end;
if MinSize.X <> LoWord(FMinExtents) then
FMinExtents := SetLoWord(FMinExtents, MinSize.X);
if MinSize.Y <> HiWord(FMinExtents) then
FMinExtents := SetHiWord(FMinExtents, MinSize.Y);
if MaxSize.X <> LoWord(FMaxExtents) then
FMaxExtents := SetLoWord(FMaxExtents, MaxSize.X);
if MaxSize.Y <> HiWord(FMaxExtents) then
FMaxExtents := SetHiWord(FMaxExtents, MaxSize.Y);
end;
if LoWord(FMinExtents) < 500 then
FMinExtents := SetLoWord(FMinExtents, 500);
if HiWord(FMinExtents) < 500 then
FMinExtents := SetHiWord(FMinExtents, 500);
if LoWord(FMaxExtents) < LoWord(FMinExtents) then
FMaxExtents := SetLoWord(FMaxExtents, LoWord(FMinExtents));
if HiWord(FMaxExtents) < HiWord(FMinExtents) then
FMaxExtents := SetHiWord(FMaxExtents, HiWord(FMinExtents));
end;
procedure TdxPrintDevice.FreeAndNilBins;
begin
FreeAndNil(FBins);
end;
procedure TdxPrintDevice.FreeAndNilFonts;
begin
FreeAndNil(FFonts);
end;
procedure TdxPrintDevice.FreeAndNilCanvas;
begin
FreeAndNil(FCanvas);
end;
procedure TdxPrintDevice.FreeAndNilPapers;
var
I: Integer;
begin
for I := 0 to PaperCount - 1 do
FPapers.Objects[I].Free;
FreeAndNil(FPapers);
end;
procedure TdxPrintDevice.FreeAndNilPrinters;
var
I: Integer;
begin
for I := 0 to PrinterCount - 1 do
PrinterInfos[I].Free;
FreeAndNil(FPrinters);
end;
procedure TdxPrintDevice.InternalSelectPaperBySize(var AWidth, AHeight: Integer);
var
DeviceMode: TDeviceMode;
begin
if AWidth > MaxExtentX then AWidth := MaxExtentX;
if AWidth < MinExtentX then AWidth := MinExtentX;
if AHeight > MaxExtentY then AHeight := MaxExtentY;
if AHeight < MinExtentY then AHeight := MinExtentY;
if FDeviceMode <> nil then
begin
DeviceMode := FDeviceMode^;
if DeviceMode.dmPaperWidth <> AWidth then
TdxPaperInfo(Papers.Objects[Papers.Count - 1]).Width := AWidth;
if DeviceMode.dmPaperLength <> AHeight then
TdxPaperInfo(Papers.Objects[Papers.Count - 1]).Height := AHeight;
end;
end;
procedure TdxPrintDevice.OpenPrintDevice(AIndex: Integer);
const
dmFields: UINT = DM_ORIENTATION or DM_PAPERSIZE or DM_PAPERLENGTH or
DM_PAPERWIDTH or DM_SCALE or DM_COPIES or DM_DEFAULTSOURCE or DM_PRINTQUALITY or
DM_COLOR or DM_DUPLEX or DM_YRESOLUTION or DM_TTOPTION or DM_COLLATE or
DM_FORMNAME or DM_LOGPIXELS or DM_BITSPERPEL or DM_PELSWIDTH or DM_PELSHEIGHT;
var
DeviceMode: TDeviceMode;
MemSize: Integer;
SaveHDeviceMode: THandle;
SavePaperWidth, SavePaperHeight: Integer;
procedure RestoreDeviceMode(ASaveHDeviceMode: THandle);
var
PDevMode: Pointer ;
DevMode: TDeviceMode;
begin
PDevMode := GlobalLock(ASaveHDeviceMode);
try
DevMode := PDeviceMode(PDevMode)^;
Copies := DevMode.dmCopies;
Duplex := DuplexModeMap[DevMode.dmDuplex];
Orientation := OrientationMap[DevMode.dmOrientation];
if not SelectPaper(DevMode.dmPaperSize) then
SelectPaper(SavePaperWidth, SavePaperHeight);
SelectBin(DevMode.dmDefaultSource);
finally
GlobalUnlock(ASaveHDeviceMode);
end;
end;
begin
if FPrinterIndex = AIndex then Exit;
SaveHDeviceMode := 0;
if IsDeviceModePersistent and (FHDeviceMode <> 0) then
begin
SaveHDeviceMode := CopyDeviceMode(FHDeviceMode);
if (Papers <> nil) and (PaperIndex > -1) and (PaperIndex < Papers.Count) then
with TdxPaperInfo(Papers.Objects[PaperIndex]) do
begin
SavePaperWidth := Width;
SavePaperHeight := Height;
end;
end;
try
ClosePrintDevice;
with PrinterInfos[AIndex] do
begin
FCurrentDevice := StrNew(FDevice);
FCurrentDriver := StrNew(FDriver);
FCurrentPort := StrNew(FPort);
end;
if OpenPrinter(FCurrentDevice, FDeviceHandle, nil) then
begin
MemSize := DocumentProperties(0, FDeviceHandle, FCurrentDevice, nil, nil, 0);
if MemSize <= 0 then
begin
ClosePrintDevice;
Exit;
end;
FHDeviceMode := GlobalAlloc(GHND, MemSize);
if FHDeviceMode = 0 then
begin
ClosePrintDevice;
Exit;
end;
FDeviceMode := GlobalLock(FHDeviceMode);
FDeviceMode^.dmFields := dmFields;
if IDOK <> DocumentProperties(0, FDeviceHandle, FCurrentDevice, FDeviceMode, nil, DM_OUT_BUFFER) then
begin
ClosePrintDevice;
Exit;
end;
FPrinterIndex := AIndex;
SetPrinterCapabilities(DeviceMode.dmFields);
FMaxCopies := DeviceCapabilities(FCurrentDevice, FCurrentPort, DC_COPIES, nil, nil);
FMaxExtents := DeviceCapabilities(FCurrentDevice, FCurrentPort, DC_MAXEXTENT, nil, nil);
FMinExtents := DeviceCapabilities(FCurrentDevice, FCurrentPort, DC_MINEXTENT, nil, nil);
FixMinMaxExtents;
if IsDeviceModePersistent and (SaveHDeviceMode <> 0) then
RestoreDeviceMode(SaveHDeviceMode);
DoPrinterChanged;
end;
finally
if SaveHDeviceMode <> 0 then GlobalFree(SaveHDeviceMode);
end;
end;
procedure TdxPrintDevice.SetState(Value: TdxPrinterState);
type
TCreateHandleFunc = function(DriverName, DeviceName, Output: PChar;
InitData: PDeviceMode): HDC stdcall;
var
CreateHandleFunc: TCreateHandleFunc;
begin
if Value <> FState then
begin
CreateHandleFunc := nil;
case Value of
psNoHandle:
begin
CheckPrinting(False);
if FCanvas <> nil then
FCanvas.Handle := 0;
DeleteDC(FDC);
FDC := 0;
end;
psHandleIC:
if FState <> psHandleDC then
CreateHandleFunc := CreateIC
else
Exit;
psHandleDC:
begin
if FCanvas <> nil then FCanvas.Handle := 0;
if FDC <> 0 then DeleteDC(FDC);
CreateHandleFunc := CreateDC;
end;
end;
if Assigned(CreateHandleFunc) and (PrinterIndex >= 0) and (PrinterIndex < PrinterCount) then
with PrinterInfos[PrinterIndex] do
begin
FDC := CreateHandleFunc(Driver, Device, Port, FDeviceMode);
if FDC = 0 then
RaiseError(cxGetResourceString(@sdxInvalidPrintDevice));
if FCanvas <> nil then
FCanvas.Handle := FDC;
end;
FState := Value;
end;
end;
procedure TdxPrintDevice.SetToDefaultPrintDevice;
var
Device: string;
Index: Integer;
begin
Device := dxGetDefaultPrinter;
if Device <> '' then
begin
Index := FindPrintDevice(PChar(Device), nil);
if Index <> -1 then
begin
OpenPrintDevice(Index);
Exit;
end;
end;
RaiseError(cxGetResourceString(@sdxNoDefaultPrintDevice));
end;
procedure TdxPrintDevice.WndProc(var Message: TMessage);
procedure PostPrnMessage;
begin
PostMessage(FWindowHandle, WMPS_PRINTERLISTCHANGED, 0, 0);
end;
function PeekPrnMessage(ARemove: Boolean): Boolean;
const
RemoveMap: array[Boolean] of UINT = (PM_NOREMOVE, PM_REMOVE);
var
Msg: TMsg;
begin
Result := PeekMessage(Msg, FWindowHandle, WMPS_PRINTERLISTCHANGED, WMPS_PRINTERLISTCHANGED, RemoveMap[ARemove]);
end;
begin
with Message do
begin
case Msg of
WM_SETTINGCHANGE:
if AutoRefresh then PostPrnMessage;
WMPS_PRINTERLISTCHANGED:
if AutoRefresh then
if not FPrinting then
begin
while PeekPrnMessage(True) do ;
Refresh;
end
else
if not PeekPrnMessage(False) then PostPrnMessage;
end;
Result := DefWindowProc(FWindowHandle, Msg, wParam, lParam);
end;
end;
var
LibHandle: THandle = 0;
procedure InitializeProcs;
begin
LibHandle := LoadLibrary(winspl);
if LibHandle > HINSTANCE_ERROR then
begin
@FConnectToPrinterDlg := GetProcAddress(LibHandle, 'ConnectToPrinterDlg');
@FGetDefaultPrinter := GetProcAddress(LibHandle, 'GetDefaultPrinterA');
@FSetDefaultPrinter := GetProcAddress(LibHandle, 'SetDefaultPrinterA');
end
else
LibHandle := 0;
end;
procedure DeinitializeProcs;
begin
if LibHandle <> 0 then
begin
@FConnectToPrinterDlg := nil;
@FGetDefaultPrinter := nil;
@FSetDefaultPrinter := nil;
FreeLibrary(LibHandle);
LibHandle := 0;
end;
end;
initialization
InitializeProcs;
{$IFDEF DEBUG_PRINTDEVICE}
AssignFile(LogFile, 'PrinterLog.txt');
Rewrite(LogFile);
{$ENDIF}
finalization
{$IFDEF DEBUG_PRINTDEVICE}
CloseFile(LogFile);
{$ENDIF}
FreeAndNil(FPrintDevice);
DeinitializeProcs;
end.