Portrait 纵向

landscape  横向

RM_reg.pas ;TRMPageSetupForm

打印机设置RM_PageSetup.dfm

 TRMPageSetting定义在RM_Printer.pas

TRMPrinterOrientation = (rmpoPortrait, rmpoLandscape);

 

TRMPageSetting

property PageOr: TRMPrinterOrientation read FPageOr write SetPageOr;

 

TRMPageSetupForm = class(TForm)

property PageSetting: TRMPageSetting read FPageSetting;

 

TRMPageLayout = class(TPersistent)

property PageOrientation: TRMPrinterOrientation read FPageOr write FPageOr;

 

调用打印机设置窗口

RM_reg.pas

procedure TRMPageLayoutProperty.Edit;

打印方法:

RM_Class.pas

procedure TRMReport.PrintReport;

_DoPrintReport函数中

lPrinter := ReportPrinter;

初始值就不对。

ReportPrinter.PaperWidth;
ReportPrinter.PaperHeight;

ReportPrinter.PrintableWidth;
ReportPrinter.PrintableHeight;

 

RMReport1.LoadFromFile('Untitled5.rmf');装载完文件后,RM_Printer.pas里的FRMPrinter变量就变成真实的宽度了从4961变成7016了。也就是说PrintReport无问题了。

RM_Class.pas

TRMReport.LoadFromStream

PrinterName := RMReadString(aStream); 读出原始值。

Pages.LoadFromStream(FReportVersion, aStream);变成7016了

  >lPage.LoadFromStream(aStream);

>TRMReportPage.LoadFromStream

>ChangePaper(FPageSize, PageWidth, PageHeight, FPageBin, FPageOrientation);

RM_Printer.pas

procedure TRMCustomPrinter.DeviceContextChanged;

  >FPaperWidth := GetDeviceCaps(FDC, PHYSICALWIDTH); //纸宽 ,单位为打印机象素

再跟踪

function TRMCustomPrinter.GetDC: HDC;  FDC有为0 的情况,所以获取值。但是xe8没有为0的情况

 

 TRMPrinter.SetPrinterInfo函数里,aPageWidth,aPageHeight根据横竖算过了,在SetSettings又算一遍,不是又退回来了嘛!

procedure TRMPrinter.SetSettings(aPgWidth, aPgHeight: Integer);

 

TRMPrinter.SetSettings

lPDevMode := GlobalLock(lDevMode); 这个lPDevMode 为nil,d7中是正常有值,xe8里为nil,导致后续代码未执行。

FDevMode := GlobalAlloc(GHND,DocumentProperties(0, PrinterHandle, PChar(lPrinterInfo.Device), lStubDevMode, lStubDevMode, 0)); //一直为0

 

D7下

DocumentProperties(0, PrinterHandle, PChar(lPrinterInfo.Device), lStubDevMode, lStubDevMode, 0);=1012;,C6下也是1012;

xe8 delphi下,用Longint类型接受返回值是-1,用dword接受返回的是4294967295,这两个值都是错的,用xe8 c++获得是1076,比c6和d7多是因为用了Unicode的原因?

DocumentProperties()返回最后一个参数设置为 0 时所需的 DEVMODE 缓冲区的字节的数

function DocumentProperties(hWnd: HWND; hPrinter: THandle; pDeviceName: LPWSTR;const pDevModeOutput: TDeviceMode; var pDevModeInput: TDeviceMode;fMode: DWORD): Longint; stdcall; overload;

c6定义

 LONG (APIENTRY* pfnDocumentProperties)(HWND hWnd, HANDLE hPrinter, LPTSTR pDeviceName, PDEVMODE pDevModeOutput, PDEVMODE pDevModeInput,DWORD fMode);

第一步获取nSize不正确,A zero for last param returns the size of buffer needed.最后一个参数为0,后3个都是NULL,不用设定DevMode^参数,就正确了。

焦点就是如何缓冲区的大缓冲区字节的数

https://support.microsoft.com/en-us/kb/167345/zh-cn

https://support.microsoft.com/en-us/kb/140285

http://blog.csdn.net/hjfjoy/article/details/4250164

//果然是unicode的差异,导致获得的字节数不一样,以下代码在c6,xec8下都可以执行。结果验证。
void
__fastcall TForm35::Button1Click(TObject *Sender) { HANDLE hPrinter; DWORD pDevModeBytes; OpenPrinter(L"Microsoft XPS Document Writer", &hPrinter, NULL); pDevModeBytes = DocumentPropertiesW(0, hPrinter, L"Microsoft XPS Document Writer", NULL, NULL, 0); //1076 pDevModeBytes = DocumentPropertiesA(0, hPrinter, "Microsoft XPS Document Writer", NULL, NULL, 0); //1012 }

 

 

LONG
WINAPI
AdvancedDocumentPropertiesA(
IN HWND hWnd,
IN HANDLE hPrinter,
IN LPSTR pDeviceName,
OUT PDEVMODEA pDevModeOutput,
IN PDEVMODEA pDevModeInput
);
LONG
WINAPI
AdvancedDocumentPropertiesW(
IN HWND hWnd,
IN HANDLE hPrinter,
IN LPWSTR pDeviceName,
OUT PDEVMODEW pDevModeOutput,
IN PDEVMODEW pDevModeInput
);

 

RM_Printer.pas  1334 Line

 DocumentProperties(0, PrinterHandle, PChar(lPrinterInfo.Device), lStubDevMode, lStubDevMode, 0); 

>改成下面的就好了。

 DocumentProperties(0, PrinterHandle, PChar(lPrinterInfo.Device), nil, nil, 0);

 

这个计算空间,每一种打印机大小都不一样,打印机牌子、型号不一样,空间大小不相同,只能实际计算了。

 

最后修改正确,监视lPrinter的值如下,和d7相同了。

Draw(MasterReport, lPrinter.Canvas, liRect);

posted on 2015-07-10 11:14  lypzxy  阅读(887)  评论(0编辑  收藏  举报