# 改变Printer 之印列设定,有解了(附 API)

Posted by 资源分享 on May 25, 1999 at 12:38:51:

使用 Data Report 时被 Printer 困扰已久,后来乾脆观察 windows 的
注册档变化,写出符合公司需求之 API(可改变印列方向,纸张大小,还原 等),
但只符合公司需求.

近日于国外讨论园地发现程式码,为微软之 MCP 所张贴,分享大家

'---- 以下原文照刊
This is a problem when we work with with data report (VB6). We must use some API functions to deal with this problem.
The code below is not test on all printer, if you find any error or bug, please sent to me.
The using of this code is easy, just call "Call SetOrientation(vbPRORLandscape) " before to show the report and call "Call SetOrientation(vbPRORPortrait)" after closing the report to restore the previous setting of printer.
Please feel free to modify this code to make it satisfy your need. You can make it to print on A3 paper size or do much as well . . .

Bye and good luck to you.
Huynh Quang Cuong
MCP
===================================
Paste the following code into a module.
(请加入以下程式码于"模组"内)
'-----------------------------
Option Explicit

Private Const CCHDEVICENAME = 32
Private Const CCHFORMNAME = 32

Private Const STANDARD_RIGHTS_REQUIRED = &HF0000
Private Const PRINTER_ACCESS_ADMINISTER = &H4
Private Const PRINTER_ACCESS_USE = &H8
Private Const PRINTER_ALL_ACCESS = _
(STANDARD_RIGHTS_REQUIRED Or _
PRINTER_ACCESS_ADMINISTER Or _
PRINTER_ACCESS_USE)

Private Const DM_MODIFY = 8
Private Const DM_IN_BUFFER = DM_MODIFY
Private Const DM_COPY = 2
Private Const DM_OUT_BUFFER = DM_COPY
Private Const DMORIENT_PORTRAIT = 1
Private Const DMORIENT_LANDSCAPE = 2
Private Const DM_ORIENTATION = &H1

Private Type DEVMODE
dmDeviceName As String * CCHDEVICENAME
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 As String * CCHFORMNAME
dmLogPixels As Integer
dmBitsPerPel As Long
dmPelsWidth As Long
dmPelsHeight As Long
dmDisplayFlags As Long
dmDisplayFrequency As Long
dmICMMethod As Long
dmICMIntent As Long
dmMediaType As Long
dmDitherType As Long
dmReserved1 As Long
dmReserved2 As Long
End Type

Private Type PRINTER_DEFAULTS
pDatatype As String
pDevMode As Long
DesiredAccess As Long
End Type

Private Declare Function OpenPrinter Lib "winspool.drv" Alias "OpenPrinterA" _
(ByVal pPrinterName As String, phPrinter As Long, pDefault _
As PRINTER_DEFAULTS) As Long
Private Declare Function SetPrinter Lib "winspool.drv" Alias "SetPrinterA" _
(ByVal hPrinter As Long, ByVal Level As Long, pPrinter As Any, _
ByVal Command As Long) As Long
Private Declare Function GetPrinter Lib "winspool.drv" Alias "GetPrinterA" _
(ByVal hPrinter As Long, ByVal Level As Long, pPrinter As Any, _
ByVal cbBuf As Long, pcbNeeded As Long) As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
(hpvDest As Any, hpvSource As Any, ByVal cbCopy As Long)
Private Declare Function ClosePrinter Lib "winspool.drv" _
(ByValhPrinter As Long) As Long

Private Declare Function DocumentProperties Lib "winspool.drv" Alias _
"DocumentPropertiesA" (ByVal hwnd As Long, ByVal hPrinter As Long, _
ByVal pDeviceName As String, ByVal pDevModeOutput As Any, _
ByVal pDevModeInput As Any, ByVal fMode As Long) As Long

Public Sub SetOrientation(NewOrientation As Long)
Dim PrinterHandle As Long
Dim PrinterName As String
Dim pd As PRINTER_DEFAULTS
Dim lpDevMode As DEVMODE
Dim Result As Long
Dim Needed As Long
Dim pFullDevMode As Long
Dim pi2_buffer() As Long

On Error GoTo errHandle
PrinterName = Printer.DeviceName
If PrinterName = "" Then Exit Sub

pd.pDatatype = vbNullString
pd.pDevMode = 0&
pd.DesiredAccess = PRINTER_ALL_ACCESS

Result = OpenPrinter(PrinterName, PrinterHandle, pd)
Result = GetPrinter(PrinterHandle, 2, ByVal 0&, 0, Needed)
ReDim pi2_buffer((Needed \ 4))
Result = GetPrinter(PrinterHandle, 2, pi2_buffer(0), Needed, Needed)

pFullDevMode = pi2_buffer(7)

Call CopyMemory(lpDevMode, ByVal pFullDevMode, Len(lpDevMode))

'-------- 以下为适宜自行更改部份
lpDevMode.dmOrientation = NewOrientation
lpDevMode.dmFields = DM_ORIENTATION
'------------------------------

Call CopyMemory(ByVal pFullDevMode, lpDevMode, Len(lpDevMode))

Result = DocumentProperties(0, PrinterHandle, PrinterName, ByVal _
pFullDevMode, ByVal pFullDevMode, DM_IN_BUFFER Or DM_OUT_BUFFER)

Result = SetPrinter(PrinterHandle, 2, pi2_buffer(0), 0&)

Call ClosePrinter(PrinterHandle)

Dim p As Printer
For Each p In Printers
If p.DeviceName = PrinterName Then
Set Printer = p
Exit For
End If
Next p
Printer.Orientation = lpDevMode.dmOrientation
Exit Sub

errHandle:
'--- Your Error Handle Here
End Sub

Follow Ups:

- Re: 改变Printer 之印列设定,有解了(附 API) Mark 08:45:48 5/26/99 (0)