龙盟编程博客 | 无障碍搜索 | 云盘搜索神器
快速搜索
主页 > 软件开发 > VB开发 >

关于数据报表的打印设置

时间:2009-12-30 15:42来源:未知 作者:admin 点击:
分享到:
数据报表(DataReport)是VB6新增功能之一。用过它的朋友对这个设计器可以说是既爱且恨。尽管它功能强大,但却有个非常致命的缺点:无法在设计环境中改变纸张大小及走向。即使你在
数据报表(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)要进行打印作业,就可能造成混乱。
  
  
  尽管如此,这个方法是目前唯一好用的方法。->

精彩图集

赞助商链接