Office中国论坛/Access中国论坛

标题: [分享]深入分析打印设置 PrtDevMode、PrtDevNames 和 PrtMip [会让你头大] [打印本页]

作者: lynnwang    时间: 2012-9-20 23:26
标题: [分享]深入分析打印设置 PrtDevMode、PrtDevNames 和 PrtMip [会让你头大]
本帖最后由 lynnwang 于 2012-9-20 23:39 编辑

PrtDevMode、PrtDevNames 和 PrtMip,参数众多让很多人头大。
而 PrtDevMode 是其中最难搞定的,因为它的数据结构的大小是随着系统的不同或编译方式是变化的。

看下面4段声明
1.access 2007 access 2003帮助中的声明(在篇文章中有好多错误,让你误导(我曾经也被它搞糊涂了),不是翻译错误,英文版也是这样,因为它的内容与代码基本上与 ACCESS 95 中内容差不多,错误在哪,后面我会一一分析)
原文链接:http://office.microsoft.com/zh-cn/access-help/HA001232784.aspx
Private Type str_DEVMODE
    RGB As String * 94
End Type

Private Type type_DEVMODE
    strDeviceName As String * 32
    intSpecVersion As Integer
    intDriverVersion As Integer
    intSize As Integer
    intDriverExtra As Integer
    lngFields As Long
    intOrientation As Integer
    intPaperSize As Integer
    intPaperLength As Integer
    intPaperWidth As Integer
    intScale As Integer
    intCopies As Integer
    intDefaultSource As Integer
    intPrintQuality As Integer
    intColor As Integer
    intDuplex As Integer
    intResolution As Integer
    intTTOption As Integer
    intCollate As Integer
    strFormName As String * 32
    lngPad As Long
    lngBits As Long
    lngPW As Long
    lngPH As Long
    lngDFI As Long
    lngDFr As Long
End Type


作者: lynnwang    时间: 2012-9-20 23:31
2.这是另一种声明方式
在作者的环境调试下可以很好的运行。
原文链接:http://www.accessoft.com/article-view.asp?id=4471
(用VBA代码设置access报表的页面设置)

Type str_DEVMODE
    RGB As String * 94
End Type
Type type_DEVMODE
    strDeviceName As String * 16
    intSpecVersion As Integer
    intDriverVersion As Integer
    intSize As Integer
    intDriverExtra As Integer
    lngFields As Long
    intOrientation As Integer
    intPaperSize As Integer
    intPaperLength As Integer
    intPaperWidth As Integer
    intScale As Integer
    intCopies As Integer
    intDefaultSource As Integer
    intPrintQuality As Integer
    intColor As Integer
    intDuplex As Integer
    intResolution As Integer
    intTTOption As Integer
    intCollate As Integer
    strFormName As String * 16
    lngPad As Long
    lngBits As Long
    lngPW As Long
    lngPH As Long
    lngDFI As Long
    lngDFr As Long
End Type
作者: lynnwang    时间: 2012-9-20 23:33
3.VB中的示例声明
原文链接:http://support.microsoft.com/kb/190218/en-us
( How To Retrieve Settings From a Printer Driver )
Option Explicit

      Private Const NULLPTR = 0&
      ' Constants for DEVMODE
      Private Const CCHDEVICENAME = 32
      Private Const CCHFORMNAME = 32
      ' Constants for DocumentProperties
      Private Const DM_MODIFY = 8
      Private Const DM_COPY = 2
      Private Const DM_IN_BUFFER = DM_MODIFY
      Private Const DM_OUT_BUFFER = DM_COPY
      ' Constants for dmOrientation
      Private Const DMORIENT_PORTRAIT = 1
      Private Const DMORIENT_LANDSCAPE = 2
      ' Constants for dmPrintQuality
      Private Const DMRES_DRAFT = (-1)
      Private Const DMRES_HIGH = (-4)
      Private Const DMRES_LOW = (-2)
      Private Const DMRES_MEDIUM = (-3)
      ' Constants for dmTTOption
      Private Const DMTT_BITMAP = 1
      Private Const DMTT_DOWNLOAD = 2
      Private Const DMTT_DOWNLOAD_OUTLINE = 4
      Private Const DMTT_SUBDEV = 3
      ' Constants for dmColor
      Private Const DMCOLOR_COLOR = 2
      Private Const DMCOLOR_MONOCHROME = 1
      ' Constants for dmCollate
      Private Const DMCOLLATE_FALSE = 0
      Private Const DMCOLLATE_TRUE = 1
      Private Const DM_COLLATE As Long = &H8000
      ' Constants for dmDuplex
      Private Const DM_DUPLEX = &H1000&
      Private Const DMDUP_HORIZONTAL = 3
      Private Const DMDUP_SIMPLEX = 1
      Private Const DMDUP_VERTICAL = 2

      Private Type DEVMODE
          dmDeviceName(1 To CCHDEVICENAME) As Byte
          dmSpecVersion As Integer
          dmDriverVersion As Integer
          dmSize As Integer
          dmDriverExtra As Integer
          dmFields As Long
          dmOrientation As Integer
          dmPaperSize As Integer
          dmPaperLength As Integer
          dmPaperWidth As Integer
          dmScale As Integer
          dmCopies As Integer
          dmDefaultSource As Integer
          dmPrintQuality As Integer
          dmColor As Integer
          dmDuplex As Integer
          dmYResolution As Integer
          dmTTOption As Integer
          dmCollate As Integer
          dmFormName(1 To CCHFORMNAME) As Byte
          dmUnusedPadding As Integer
          dmBitsPerPel As Integer
          dmPelsWidth As Long
          dmPelsHeight As Long
          dmDisplayFlags As Long
          dmDisplayFrequency As Long
               
      End Type
作者: lynnwang    时间: 2012-9-20 23:35
4.c++中的DevMode原型
C++
typedef struct _devicemode {
  TCHAR dmDeviceName[CCHDEVICENAME];
  WORD  dmSpecVersion;
  WORD  dmDriverVersion;
  WORD  dmSize;
  WORD  dmDriverExtra;
  DWORD dmFields;
  union {
    struct {
      short dmOrientation;
      short dmPaperSize;
      short dmPaperLength;
      short dmPaperWidth;
      short dmScale;
      short dmCopies;
      short dmDefaultSource;
      short dmPrintQuality;
    };
    struct {
      POINTL dmPosition;
      DWORD  dmDisplayOrientation;
      DWORD  dmDisplayFixedOutput;
    };
  };
  short dmColor;
  short dmDuplex;
  short dmYResolution;
  short dmTTOption;
  short dmCollate;
  TCHAR dmFormName[CCHFORMNAME];
  WORD  dmLogPixels;
  DWORD dmBitsPerPel;
  DWORD dmPelsWidth;
  DWORD dmPelsHeight;
  union {
    DWORD dmDisplayFlags;
    DWORD dmNup;
  };
  DWORD dmDisplayFrequency;
#if (WINVER >= 0x0400)
  DWORD dmICMMethod;
  DWORD dmICMIntent;
  DWORD dmMediaType;
  DWORD dmDitherType;
  DWORD dmReserved1;
  DWORD dmReserved2;
#if (WINVER >= 0x0500) || (_WIN32_WINNT >= 0x0400)
  DWORD dmPanningWidth;
  DWORD dmPanningHeight;
#endif
#endif
} DEVMODE, *PDEVMODE, *LPDEVMODE;
作者: lynnwang    时间: 2012-9-21 00:16
通过对比,我们就会发现 PrtDevMode 中的 strDeviceName 可以多种方式声明
这就是为什么我要贴出4种
通过这个比较,我们可以理解字符串即为BYTE()型数组,BYTE占1个字节,一个字符的STRING占2个字节。

先指出而ACCESS 的PrtDevMode帮助文档中错误说明

1.错误一”PrtDevMode 属性设置是一个 94 个字节的结构,该结构是在 Win32 软件开发工具包中定义的 DEVMODE 结构的镜像。“

我们用LENB,LENB(type_DEVMODE) 、LENB(str_DEVMODE),分别得到192字节、188字节
你再用 LenB(Form.PrtDevMode) (要在设计模式下罗) 得到至少长度在200字节以上,我这里到了1000多字节了。

说了这么多,其实我就想说 PrtDevMode 属性设置的不止是一个 94 个字节的结构

2. 错误二”DeviceName 最多为 32 字节的字符串 “
一个字符的STRING占2个字节。 strDeviceName As String * 32 =64字节
strFormName As String * 32 =64字节

3.错误三“FormName 最大长度为 16 个字符的字符串,用于指定要使用的纸张大小,例如,“Letter”或“Legal”。 ”
同2,实际最大为32个字符64个字节



索马里的老大们,别把我文档中的参考链接删除了,参考很重要,要不然不好理解。

困了,坚持不了了,睡觉了{:soso_e101:} (本来要针对每一组声明分别进行说明,不过大家都应该会慢慢理解的)

有理解错误请指出,错别字请原谅





作者: liangshu-fu    时间: 2012-9-21 07:55
太难了,你们是怎么学的呀?
作者: 风中漫步    时间: 2012-9-21 08:04
谢谢分享,期待继续
作者: xuwenning    时间: 2012-9-21 09:02
收藏
学习
作者: roych    时间: 2012-9-22 00:28
本帖最后由 roych 于 2012-9-22 00:28 编辑

我觉得,对于大多数用户而言,并不需要要设置打印机很多参数的,利用内置的打印机对象,又或者在Access里设置好默认格式就好了。
如果要个性化纸张之类,则可能需要写很多代码,当然,声明API也是必须的。
作者: lynnwang    时间: 2012-9-23 16:14
roych 发表于 2012-9-22 00:28
我觉得,对于大多数用户而言,并不需要要设置打印机很多参数的,利用内置的打印机对象,又或者在Access里设 ...

是的,基本上[Printer]对象足以应付打印设置了。

其实[Printer]类,它本身就是对 PrtDevMode、PrtDevNames 和 PrtMip这三参数来进行封装操作的。

注意;PrtDevMode、PrtDevNames 和 PrtMip这三个就是[窗体]和[报表]的属性来着
作者: lynnwang    时间: 2012-9-23 16:30
这里贴出来 PrtDevMode、PrtDevNames 和 PrtMip这个三参数,是为以后大家认为[Printer]满足不了要求,在这里作个说明与提示

因为这里PrtDevMode、PrtDevNames这两个参考其实就是AP所返回的打印设备的数据。
因为其中要返的字符串,所以这里就涉及到UNICODE与ANSI的转换了。
我们看看例4中的定义:  TCHAR dmDeviceName[CCHDEVICENAME];
TCHAR:具体不说了,百度百科有详解。
所以这里[窗体]和[报表]的属性返回的字符串值全部为ANSI码
而转到VBA中全部为UNICODE


这里看看例3与例1对比就知道了,一个是64个字节声明,一个是32字节数组声明
为什么一个是64字节,一个是32字节,因为api的 char 到VB的string会转换到UNICODE,而字节数组却不会自动转换

以上就是关键点,提个醒,大家用到时再看看

作者: lynnwang    时间: 2012-9-23 16:36
所以大家看出来了,例2中声明,就有问题了——总共就32个字节怎么存得下,只有往后移了。
为什么作者通过了,就不得而知了(他的代码我没测试),我在自己代码中改过后不能通过。


作者: t小宝    时间: 2012-9-23 21:40
我用第2种声明方式 ... strDeviceName As String * 16 ...,可以设置纸张大小、页边距等
作者: t小宝    时间: 2012-9-23 21:44
帮助中说 type_DEVMODE 结构的 intScale 项可以设置页面缩放,我测试是设置不了的。

作者: huangli0356    时间: 2012-11-13 16:58
牛人的牛作...现在还不太明白...继续努力学习..




欢迎光临 Office中国论坛/Access中国论坛 (http://www.office-cn.net/) Powered by Discuz! X3.3