数据报表(DataReport)是VB6新增功能之一。用过它的朋友对这个设计器可以说是既爱且恨。尽管它功能强大,但却有个非常致命的缺点:无法在设计环境中改变纸张大小及走向。即使你在程序中使用Printer对象改变纸张大小及打印走向,也解决不了问题。对于非A4纸的报表或是横向打印的报表,连报表预览都不行。
问题的原因是:DR基于系统默认的打印设置创建自己的内部设备环境。而这个设备环境是没有向外界展现的。DR的内部设备环境与VB的Printer对象的内部设备环境是完全不同的,因此改变打印机对象的属性对DR一点效果也没有。
解决这个问题的笨办法是,在预览或打印时改变系统默认打印机的设置。使用这个方法连自己都会觉得麻烦,更何况是你的用户。没办法,只能通过代码强行改变系统默认打印机的设置来解决。将下面的代码放入一个模块中:
OptionExplicit
PublicEnumPrinterOrientationConstants OrientPortrait=1 OrientLandscape=2 EndEnum PrivateTypeDEVMODE dmDeviceNameAsString*32 dmSpecVersionAsInteger dmDriverVersionAsInteger dmSizeAsInteger dmDriverExtraAsInteger dmFieldsAsLong dmOrientationAsInteger dmPaperSizeAsInteger dmPaperLengthAsInteger dmPaperWidthAsInteger dmScaleAsInteger dmCopiesAsInteger dmDefaultSourceAsInteger dmPrintQualityAsInteger dmColorAsInteger dmDuplexAsInteger dmYResolutionAsInteger dmTTOptionAsInteger dmCollateAsInteger dmFormNameAsString*32 dmUnusedPaddingAsInteger dmBitsPerPelAsInteger dmPelsWidthAsLong dmPelsHeightAsLong dmDisplayFlagsAsLong dmDisplayFrequencyAsLong EndType PrivateTypePRINTER_DEFAULTS pDataTypeAsString pDevModeAsLong DesiredAccessAsLong EndType PrivateTypePRINTER_INFO_2 pServerNameAsLong pPrinterNameAsLong pShareNameAsLong pPortNameAsLong pDriverNameAsLong pCommentAsLong pLocationAsLong pDevModeAsLong pSepFileAsLong pPrintProcessorAsLong pDataTypeAsLong pParametersAsLong pSecurityDescriptorAsLong AttributesAsLong PriorityAsLong DefaultPriorityAsLong StartTimeAsLong UntilTimeAsLong StatusAsLong cJobsAsLong AveragePPMAsLong EndType
PublicConstDMPAPER_A5=11
PrivateConstDM_IN_BUFFERAsLong=8 PrivateConstDM_OUT_BUFFERAsLong=2 PrivateConstDM_ORIENTATIONAsLong=&H1 PrivateConstDM_PAPERSIZE=&H2&
PrivateConstPRINTER_ACCESS_ADMINISTERAsLong=&H4 PrivateConstPRINTER_ACCESS_USEAsLong=&H8 PrivateConstSTANDARD_RIGHTS_REQUIREDAsLong=&HF0000 PrivateConstPRINTER_ALL_ACCESS=(STANDARD_RIGHTS_REQUIREDOrPRINTER_ACCESS_ADMINISTEROrPRINTER_ACCESS_USE)
PrivateDeclareSubCopyMemoryLib"kernel32"Alias"RtlMoveMemory"(hpvDestAsAny,hpvSourceAsAny,ByValcbCopyAsLong)
PrivateDeclareFunctionOpenPrinterLib"winspool.drv"Alias"OpenPrinterA"(ByValpPrinterNameAsString,phPrinterAsLong,pDefaultAsAny)AsLong
PrivateDeclareFunctionClosePrinterLib"winspool.drv"(ByValhPrinterAsLong)AsLong
PrivateDeclareFunctionDocumentPropertiesLib"winspool.drv"Alias"DocumentPropertiesA"(ByValhWndAsLong,ByValhPrinterAsLong,ByValpDeviceNameAsString,pDevModeOutputAsAny,pDevModeInputAsAny,ByValfModeAsLong)AsLong
PrivateDeclareFunctionGetPrinterLib"winspool.drv"Alias"GetPrinterA"(ByValhPrinterAsLong,ByValLevelAsLong,pPrinterAsAny,ByValcbBufAsLong,pcbNeededAsLong)AsLong
PrivateDeclareFunctionSetPrinterLib"winspool.drv"Alias"SetPrinterA"(ByValhPrinterAsLong,ByValLevelAsLong,pPrinterAsAny,ByValCommandAsLong)AsLong
FunctionSetDefaultPrinterOrientation(ByValeOrientationAsPrinterOrientationConstants)AsBoolean
DimbDevMode()AsByte DimbPrinterInfo2()AsByte DimhPrinterAsLong DimlResultAsLong DimnSizeAsLong DimsPrnNameAsString DimdmAsDEVMODE DimpdAsPRINTER_DEFAULTS Dimpi2AsPRINTER_INFO_2
'获取默认打印机的设备名称 sPrnName=Printer.DeviceName '由于要调用SetPrinter,所以 '如果是在NT下就要求PRINTER_ALL_ACCESS pd.DesiredAccess=PRINTER_ALL_ACCESS
'获取打印机句柄 IfOpenPrinter(sPrnName,hPrinter,pd)Then '获取PRINTER_INFO_2结构要求的字节数
CallGetPrinter(hPrinter,2&,0&,0&,nSize) ReDimbPrinterInfo2(1TonSize)AsByte lResult=GetPrinter(hPrinter,2,bPrinterInfo2(1),nSize,nSize) CallCopyMemory(pi2,bPrinterInfo2(1),Len(pi2)) nSize=DocumentProperties(0&,hPrinter,sPrnName,0&,0&,0) ReDimbDevMode(1TonSize) Ifpi2.pDevModeThen CallCopyMemory(bDevMode(1),ByValpi2.pDevMode,Len(dm)) Else CallDocumentProperties(0&,hPrinter,sPrnName,bDevMode(1),0&,DM_OUT_BUFFER) EndIf
CallCopyMemory(dm,bDevMode(1),Len(dm)) Withdm '设置新的走向 .dmOrientation=eOrientation .dmFields=DM_ORIENTATION '.dmPaperSize=DMPAPER_A5将纸张大小设为A5,请自行更改所需大小 '.dmFields=DM_PAPERSIZE必须,否则无法设置纸张大小 EndWith CallCopyMemory(bDevMode(1),dm,Len(dm))
CallDocumentProperties(0&,hPrinter,sPrnName,_ bDevMode(1),bDevMode(1),DM_IN_BUFFEROr_ DM_OUT_BUFFER)
pi2.pDevMode=VarPtr(bDevMode(1))
lResult=SetPrinter(hPrinter,2,pi2,0&)
CallClosePrinter(hPrinter) SetDefaultPrinterOrientation=True Else SetDefaultPrinterOrientation=False EndIf
EndFunction 在打印或预览之前直接调用SetDefaultPrinterOrientation打印走向常数。注意:红色注释部分用于改变纸张的大小。
这个解决方案仍有两个问题:
1。对有些型号的打印机不起作用,例如佳能的BJC-265SP 2。即使是在预浏DR时,也必须改变打印机的设置。这时如果有其它使用打印机默认设置的程序(如Notepad)要进行打印作业,就可能造成混乱。
尽管如此,这个方法是目前唯一好用的方法。->
|