问题描述
我正在尝试使用设置为我的 C# win 表单应用程序中打印机 DEVMODE
结构的新属性来更新打印作业。特别是要打印到的托盘。
[StructLayout(LayoutKind.Sequential,CharSet = CharSet.Ansi)]
public class DOCINFOA
{
[MarshalAs(UnmanagedType.LPStr)]
public string lpszDocName;
[MarshalAs(UnmanagedType.LPStr)]
public string lpszOutput;
[MarshalAs(UnmanagedType.LPStr)]
public string lpszDatatype;
}
[StructLayout(LayoutKind.Sequential,CharSet = CharSet.Auto)]
private struct PRINTER_INFO_2
{
[MarshalAs(UnmanagedType.LPStr)]
public string pServerName;
[MarshalAs(UnmanagedType.LPStr)]
public string pprinterName;
[MarshalAs(UnmanagedType.LPStr)]
public string pShareName;
[MarshalAs(UnmanagedType.LPStr)]
public string pPortName;
[MarshalAs(UnmanagedType.LPStr)]
public string pDriverName;
[MarshalAs(UnmanagedType.LPStr)]
public string pComment;
[MarshalAs(UnmanagedType.LPStr)]
public string pLocation;
public IntPtr pDevMode;
[MarshalAs(UnmanagedType.LPStr)]
public string pSepFile;
[MarshalAs(UnmanagedType.LPStr)]
public string pprintProcessor;
[MarshalAs(UnmanagedType.LPStr)]
public string pDatatype;
[MarshalAs(UnmanagedType.LPStr)]
public string pParameters;
public IntPtr pSecurityDescriptor;
public int Attributes;
public int Priority;
public int DefaultPriority;
public int StartTime;
public int UntilTime;
public int Status;
public int cJobs;
public int AveragePPM;
}
[StructLayout(LayoutKind.Sequential,CharSet = CharSet.Ansi)]
public class DEVMODE
{
private const int CCHDEVICENAME = 32;
private const int CCHFORMNAME = 32;
[MarshalAs(UnmanagedType.ByValTStr,SizeConst = CCHDEVICENAME)]
public string dmDeviceName;
public ushort dmSpecVersion;
public ushort dmDriverVersion;
public ushort dmSize;
public ushort dmDriverExtra;
public uint dmFields;
// values to set based on dmFields bits
public short dmOrientation;
public short dmPaperSize;
public short dmPaperLength;
public short dmPaperWidth;
public short dmScale;
public short dmcopies;
public short dmDefaultSource;
public short dmPrintQuality;
public int dmPositionX;
public int dmPositionY;
public uint dmdisplayOrientation;
public uint dmdisplayFixedOutput;
public short dmColor;
public short dmDuplex;
public short dmYResolution;
public short dmTTOption;
public short dmCollate;
[MarshalAs(UnmanagedType.ByValTStr,SizeConst = CCHFORMNAME)]
public string dmFormName;
public ushort dmLogPixels;
public uint dmBitsPerPel;
public uint dmPelsWidth;
public uint dmPelsHeight;
public uint dmdisplayFlags;
public uint dmdisplayFrequency;
public uint dmICMMethod;
public uint dmICMIntent;
public uint dmMediaType;
public uint dmDitherType;
public uint dmReserved1;
public uint dmReserved2;
public uint dmPanningWidth;
public uint dmPanningHeight;
}
[StructLayout(LayoutKind.Sequential,CharSet = CharSet.Ansi)]
public class PRINTER_DEFAULTS
{
public IntPtr pDatatype;
public IntPtr pDevMode;
public int DesiredAccess;
}
[Flags]
public enum FModes
{
DM_SIZEOF = 0,DM_UPDATE = 1,DM_copY = 2,DM_PROMPT = 4,DM_MODIFY = 8,DM_OUT_DEFAULT = DM_UPDATE,DM_OUT_BUFFER = DM_copY,DM_IN_PROMPT = DM_PROMPT,DM_IN_BUFFER = DM_MODIFY,}
[Flags]
public enum DevModeFields : uint
{
DM_ICMMETHOD = 0x10000,DM_FORMNAME = 0x00010000,DM_ICMINTENT = 0x04000000,DM_MEDIATYPE = 0x08000000,DM_DITHERTYPE = 0x10000000,DM_copIES = 0x00000100,DM_DEFAULTSOURCE = 0x00000200,DM_PRINT_QUALITY = 0x00000400,DM_COLOR = 0x00000800,DM_DUPLEX = 0x00001000,DM_YRESOLUTION = 0x00002000,DM_TTOPTION = 0x00004000,DM_COLLATE = 0x00008000,DM_ORIENTATION = 0x00000001,DM_PAPERSIZE = 0x00000002,DM_PAPERLENGTH = 0x00000004,DM_PAPERWIDTH = 0x00000008,DM_SCALE = 0x00000010
}
// DesiredAccess properties
const int PRINTER_ACCESS_ADMINISTER = 0x4;
const int PRINTER_ACCESS_USE = 0x8;
const int STANDARD_RIGHTS_required = 0xF0000;
const int PRINTER_ALL_ACCESS = (STANDARD_RIGHTS_required | PRINTER_ACCESS_ADMINISTER | PRINTER_ACCESS_USE);
public enum PaperSource
{
DMRES_HIGH = -4,DMRES_MEDIUM = -3,DMRES_LOW = -2,DMRES_DRAFT = -1,DMBIN_UPPER = 1,DMBIN_LOWER = 2,DMBIN_MIDDLE = 3,DMBIN_MANUAL = 4,DMBIN_ENVELOPE = 5,DMBIN_ENVMANUAL = 6,DMBIN_AUTO = 7,DMBIN_TRACTOR = 8,DMBIN_SMALLFMT = 9,DMBIN_LARGEFMT = 10,DMBIN_LARGECAPACITY = 11,DMBIN_CASSETTE = 14,DMBIN_FORMSOURCE = 15
}
PRINTER_DEFAULTS settings = new PRINTER_DEFAULTS
{
pDatatype = IntPtr.Zero,pDevMode = IntPtr.Zero,DesiredAccess = PRINTER_ACCESS_USE
};
int bytesNeeded = 0;
// get the printer handle
if (OpenPrinter(szPrinterName.normalize(),out IntPtr hPrinter,settings))
{
// find out size needed for buffer first
GetPrinter(hPrinter,2,IntPtr.Zero,out bytesNeeded);
if (bytesNeeded > 0)
{
// allocate memory for the printer info
IntPtr pprinterInfo = Marshal.AllocHGlobal(bytesNeeded);
// fetch pointer to printer info at level 2 (gives us DEVMODE data)
if (GetPrinter(hPrinter,pprinterInfo,bytesNeeded,out _))
{
// convert the pointer to the readable data
PRINTER_INFO_2 printerInfo = (PRINTER_INFO_2)Marshal.PtrToStructure(pprinterInfo,typeof(PRINTER_INFO_2));
// for some reason it didnt fetch the DEVMODE data we need,try getting it elsewhere
if (true)
{
// find out size needed for buffer first
bytesNeeded = DocumentProperties(IntPtr.Zero,hPrinter,printerInfo.pprinterName,(int)FModes.DM_SIZEOF);
if (bytesNeeded > 0)
{
// allocate memory for the DEVMODE info
IntPtr pDevMode = Marshal.AllocHGlobal(bytesNeeded);
// fetch pointer to DEVMODE info
int result = DocumentProperties(IntPtr.Zero,szPrinterName.normalize(),pDevMode,(int)FModes.DM_OUT_BUFFER);
if (result > 0)
{
printerInfo.pDevMode = pDevMode;
}
}
}
// create the print job
DOCINFOA di = new DOCINFOA
{
lpszDocName = "My C#.NET RAW Document",lpszDatatype = "RAW"
};
if (StartDocPrinter(hPrinter,1,di))
{
if (StartPagePrinter(hPrinter))
{
// convert the pointer to readable data
DEVMODE dm = (DEVMODE)Marshal.PtrToStructure(printerInfo.pDevMode,typeof(DEVMODE));
// set new properties for printer
dm.dmFields |= (uint)DevModeFields.DM_DEFAULTSOURCE;
dm.dmDefaultSource = (short)PaperSource.DMBIN_UPPER;
Marshal.StructuretoPtr(dm,printerInfo.pDevMode,false);
//overwrite the printers settings
int res = DocumentProperties(IntPtr.Zero,(int)FModes.DM_IN_BUFFER | (int)FModes.DM_OUT_BUFFER);
if (res > 0)
{
WritePrinter(hPrinter,pBytes,dwCount,out _);
EndPagePrinter(hPrinter);
}
EndDocPrinter(hPrinter);
}
ClosePrinter(hPrinter);
}
}
}
我遇到的问题是对 DocumentProperties
的最终调用没有更新打印机作业设置。我通过在每次读取或写入结构时插入 IsDevmodeValid
调用来检查结构是否有效,并且返回正常。我已经尝试在设置作业之前和之后设置 DEVMODE
结构。当我查看打印作业属性时,它只是不更新设置。
谁能告诉我我在这里遗漏了什么?仅供参考,它可以正常打印任何文档,但打印到打印机的默认托盘。
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)