📄 frxprinter.pas
字号:
FreeDevMode;
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
{$IFDEF Delphi12}
FPapers.AddObject(StrPas(PWideChar(PaperNames + i * 64)), Pointer(PaperSizes[i]));
{$ELSE}
FPapers.AddObject(StrPas(PAnsiChar(PaperNames + i * 64)), Pointer(PaperSizes[i]));
{$ENDIF}
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));
DeviceCapabilities(PChar(FName), PChar(FPort), DC_BINNAMES, BinNames, FMode);
for i := 0 to BinsCount - 1 do
if BinNumbers[i] <> DMBIN_AUTO then
{$IFDEF Delphi12}
FBins.AddObject(StrPas(PwideChar(BinNames + i * 24)), Pointer(BinNumbers[i]));
{$ELSE}
FBins.AddObject(StrPas(BinNames + i * 24), Pointer(BinNumbers[i]));
{$ENDIF}
FreeMem(BinNames, BinsCount * 24 * sizeof(char));
end;
begin
if FInitialized then Exit;
CreateDevMode;
if FDeviceMode = 0 then Exit;
RecreateDC;
if not UpdateDeviceCaps then Exit;
FDefPaper := FMode.dmPaperSize;
FPaper := FDefPaper;
FDefPaperWidth := FPaperWidth;
FDefPaperHeight := FPaperHeight;
if FMode.dmOrientation = DMORIENT_PORTRAIT then
FDefOrientation := poPortrait else
FDefOrientation := poLandscape;
FOrientation := FDefOrientation;
FillPapers;
FillBins;
FBin := -1;
FInitialized := True;
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);
DocInfo.lpszDocName := PChar(FTitle);
if FFileName <> '' then
DocInfo.lpszOutput := PChar(FFileName);
RecreateDC;
StartDoc(FDC, DocInfo);
end;
procedure TfrxPrinter.BeginPage;
begin
StartPage(FDC);
end;
procedure TfrxPrinter.EndDoc;
var
Saved8087CW: Word;
begin
Saved8087CW := Default8087CW;
Set8087CW($133F);
try
Windows.EndDoc(FDC);
except
end;
Set8087CW(Saved8087CW);
FPrinting := False;
RecreateDC;
FBin := -1;
end;
procedure TfrxPrinter.EndPage;
begin
Windows.EndPage(FDC);
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;
procedure TfrxPrinter.CreateDevMode;
var
bufSize: Integer;
{$IFNDEF Delphi12}
dm: TDeviceMode;
{$ENDIF}
begin
if OpenPrinter(PChar(FName), FHandle, nil) then
begin
{$IFDEF Delphi12}
bufSize := DocumentProperties(0, FHandle, PChar(FName), nil, nil, 0);
{$ELSE}
bufSize := DocumentProperties(0, FHandle, PChar(FName), dm, dm, 0);
{$ENDIF}
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.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;
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);
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;
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 ADuplex <> 1 then
FMode.dmFields := FMode.dmFields or DM_DUPLEX;
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 FBin <> -1 then
ABin := FBin;
if ABin <> DMBIN_AUTO then
FMode.dmDefaultSource := ABin;
if ADuplex = 4 then
FMode.dmDuplex := DMDUP_SIMPLEX
else if ADuplex <> 1 then
FMode.dmDuplex := ADuplex;
FDC := ResetDC(FDC, FMode^);
FDC := ResetDC(FDC, FMode^); // needed for some printers
FCanvas.Refresh;
if not UpdateDeviceCaps then Exit;
FPaper := APaperSize;
FOrientation := AOrientation;
end;
function TfrxPrinter.UpdateDeviceCaps: Boolean;
begin
Result := True;
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;
begin
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;
RecreateDC;
end;
end;
{ TfrxPrinters }
constructor TfrxPrinters.Create;
begin
FPrinterList := TList.Create;
FPrinters := TStringList.Create;
FillPrinters;
if FPrinterList.Count = 0 then
begin
FPrinterList.Add(TfrxVirtualPrinter.Create(frxResources.Get('prVirtual'), ''));
FHasPhysicalPrinters := False;
PrinterIndex := 0;
end
else
begin
FHasPhysicalPrinters := True;
PrinterIndex := IndexOf(GetDefaultPrinter);
if PrinterIndex = -1 then // important
PrinterIndex := 0;
end;
end;
destructor TfrxPrinters.Destroy;
begin
Clear;
FPrinterList.Free;
FPrinters.Free;
inherited;
end;
procedure TfrxPrinters.Clear;
begin
while FPrinterList.Count > 0 do
begin
TObject(FPrinterList[0]).Free;
FPrinterList.Delete(0);
end;
FPrinters.Clear;
end;
function TfrxPrinters.GetItem(Index: Integer): TfrxCustomPrinter;
begin
if Index >= 0 then
Result := FPrinterList[Index]
else
Result := nil
end;
function TfrxPrinters.IndexOf(AName: String): Integer;
var
i: Integer;
begin
Result := -1;
for i := 0 to FPrinterList.Count - 1 do
if AnsiCompareText(Items[i].Name, AName) = 0 then
begin
Result := i;
break;
end;
end;
procedure TfrxPrinters.SetPrinterIndex(Value: Integer);
begin
if Value <> -1 then
FPrinterIndex := Value
else
FPrinterIndex := IndexOf(GetDefaultPrinter);
if FPrinterIndex <> -1 then
Items[FPrinterIndex].Init;
end;
function TfrxPrinters.GetCurrentPrinter: TfrxCustomPrinter;
begin
Result := Items[PrinterIndex];
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;
function frxPrinters: TfrxPrinters;
begin
if FPrinters = nil then
FPrinters := TfrxPrinters.Create;
Result := FPrinters;
end;
initialization
finalization
if FPrinters <> nil then
FPrinters.Free;
FPrinters := nil;
end.
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -