失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > 弄了一整天 终于把打印自定义纸张大小搞定了

弄了一整天 终于把打印自定义纸张大小搞定了

时间:2022-05-13 17:03:01

相关推荐

弄了一整天 终于把打印自定义纸张大小搞定了

长江支流说的办法保留太多了,结果不行,很多类都是他在程序集里自定义的,源码又没公开

不过还是要感谢他的提示

今天和小陈搞了一天,他在国外的论坛上看到了一篇文章得到了启示,最后我们在凌晨3点终于把自定义纸张的代码给写出来了,看来必须用API,微软的.NET对打印的支持太菜了

现公开我们工作室实现此功能的部分代码

using System;

using System.Text;

using System.Runtime.InteropServices;

using System.Security;

using ponentModel;

using System.Drawing.Printing;

namespace MCCustomPrintForm

{

/// <summary>

/// 成都微创工作室(电子科技大学微创工作室)

/// Tell 028-82853098

/// Email zyspipi@ , you680@

/// 打印机纸张的真正自定义部分代码

/// -1-2

/// </summary>

public class MCCustomPrintForm

{

// Make a static class

private MCCustomPrintForm()

{

}

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]

internal struct structPrinterDefaults

{

[MarshalAs(UnmanagedType.LPTStr)] public String pDatatype;

public IntPtr pDevMode;

[MarshalAs(UnmanagedType.I4)] public int DesiredAccess;

};

[DllImport("winspool.Drv", EntryPoint="OpenPrinter", SetLastError=true,

CharSet=CharSet.Unicode, ExactSpelling=false,CallingConvention=CallingConvention.StdCall),

SuppressUnmanagedCodeSecurityAttribute()]

internal static extern bool OpenPrinter([MarshalAs(UnmanagedType.LPTStr)]

string printerName,

out IntPtr phPrinter,

ref structPrinterDefaults pd);

[DllImport("winspool.Drv", EntryPoint="ClosePrinter", SetLastError=true,

CharSet=CharSet.Unicode, ExactSpelling=false,

CallingConvention=CallingConvention.StdCall),SuppressUnmanagedCodeSecurityAttribute()]

internal static extern bool ClosePrinter(IntPtr phPrinter);

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]

internal struct structSize

{

public Int32 width;

public Int32 height;

}

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]

internal struct structRect

{

public Int32 left;

public Int32 top;

public Int32 right;

public Int32 bottom;

}

[StructLayout(LayoutKind.Explicit, CharSet=CharSet.Unicode)]

internal struct FormInfo1

{

[FieldOffset(0), MarshalAs(UnmanagedType.I4)] public uint Flags;

[FieldOffset(4), MarshalAs(UnmanagedType.LPWStr)] public String pName;

[FieldOffset(8)] public structSize Size;

[FieldOffset(16)] public structRect ImageableArea;

};

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi/* changed from CharSet=CharSet.Auto */)]

internal struct structDevMode

{

[MarshalAs(UnmanagedType.ByValTStr, SizeConst=32)] public String

dmDeviceName;

[MarshalAs(UnmanagedType.U2)] public short dmSpecVersion;

[MarshalAs(UnmanagedType.U2)] public short dmDriverVersion;

[MarshalAs(UnmanagedType.U2)] public short dmSize;

[MarshalAs(UnmanagedType.U2)] public short dmDriverExtra;

[MarshalAs(UnmanagedType.U4)] public int dmFields;

[MarshalAs(UnmanagedType.I2)] public short dmOrientation;

[MarshalAs(UnmanagedType.I2)] public short dmPaperSize;

[MarshalAs(UnmanagedType.I2)] public short dmPaperLength;

[MarshalAs(UnmanagedType.I2)] public short dmPaperWidth;

[MarshalAs(UnmanagedType.I2)] public short dmScale;

[MarshalAs(UnmanagedType.I2)] public short dmCopies;

[MarshalAs(UnmanagedType.I2)] public short dmDefaultSource;

[MarshalAs(UnmanagedType.I2)] public short dmPrintQuality;

[MarshalAs(UnmanagedType.I2)] public short dmColor;

[MarshalAs(UnmanagedType.I2)] public short dmDuplex;

[MarshalAs(UnmanagedType.I2)] public short dmYResolution;

[MarshalAs(UnmanagedType.I2)] public short dmTTOption;

[MarshalAs(UnmanagedType.I2)] public short dmCollate;

[MarshalAs(UnmanagedType.ByValTStr, SizeConst=32)] public String dmFormName;

[MarshalAs(UnmanagedType.U2)] public short dmLogPixels;

[MarshalAs(UnmanagedType.U4)] public int dmBitsPerPel;

[MarshalAs(UnmanagedType.U4)] public int dmPelsWidth;

[MarshalAs(UnmanagedType.U4)] public int dmPelsHeight;

[MarshalAs(UnmanagedType.U4)] public int dmNup;

[MarshalAs(UnmanagedType.U4)] public int dmDisplayFrequency;

[MarshalAs(UnmanagedType.U4)] public int dmICMMethod;

[MarshalAs(UnmanagedType.U4)] public int dmICMIntent;

[MarshalAs(UnmanagedType.U4)] public int dmMediaType;

[MarshalAs(UnmanagedType.U4)] public int dmDitherType;

[MarshalAs(UnmanagedType.U4)] public int dmReserved1;

[MarshalAs(UnmanagedType.U4)] public int dmReserved2;

}

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]

internal struct PRINTER_INFO_9

{

public IntPtr pDevMode;

}

[DllImport("winspool.Drv", EntryPoint="AddFormW", SetLastError=true,

CharSet=CharSet.Unicode, ExactSpelling=true,

CallingConvention=CallingConvention.StdCall), SuppressUnmanagedCodeSecurityAttribute()]

internal static extern bool AddForm(

IntPtr phPrinter,

[MarshalAs(UnmanagedType.I4)] int level,

ref FormInfo1 form);

/* This method is not used

[DllImport("winspool.Drv", EntryPoint="SetForm", SetLastError=true,

CharSet=CharSet.Unicode, ExactSpelling=false,

CallingConvention=CallingConvention.StdCall), SuppressUnmanagedCodeSecurityAttribute()]

internal static extern bool SetForm(IntPtr phPrinter, string paperName,

[MarshalAs(UnmanagedType.I4)] int level, ref FormInfo1 form);

*/

[DllImport("winspool.Drv", EntryPoint="DeleteForm", SetLastError=true,

CharSet=CharSet.Unicode, ExactSpelling=false,CallingConvention=CallingConvention.StdCall),

SuppressUnmanagedCodeSecurityAttribute()]

internal static extern bool DeleteForm(

IntPtr phPrinter,

[MarshalAs(UnmanagedType.LPTStr)] string pName);

[DllImport("kernel32.dll", EntryPoint="GetLastError", SetLastError=false,

ExactSpelling=true, CallingConvention=CallingConvention.StdCall),

SuppressUnmanagedCodeSecurityAttribute()]

internal static extern Int32 GetLastError();

[DllImport("GDI32.dll", EntryPoint="CreateDC", SetLastError=true,

CharSet=CharSet.Unicode, ExactSpelling=false,

CallingConvention=CallingConvention.StdCall),

SuppressUnmanagedCodeSecurityAttribute()]

internal static extern IntPtr CreateDC([MarshalAs(UnmanagedType.LPTStr)]

string pDrive,

[MarshalAs(UnmanagedType.LPTStr)] string pName,

[MarshalAs(UnmanagedType.LPTStr)] string pOutput,

ref structDevMode pDevMode);

[DllImport("GDI32.dll", EntryPoint="ResetDC", SetLastError=true,

CharSet=CharSet.Unicode, ExactSpelling=false,

CallingConvention=CallingConvention.StdCall),

SuppressUnmanagedCodeSecurityAttribute()]

internal static extern IntPtr ResetDC(

IntPtr hDC,

ref structDevMode

pDevMode);

[DllImport("GDI32.dll", EntryPoint="DeleteDC", SetLastError=true,

CharSet=CharSet.Unicode, ExactSpelling=false,

CallingConvention=CallingConvention.StdCall),

SuppressUnmanagedCodeSecurityAttribute()]

internal static extern bool DeleteDC(IntPtr hDC);

[DllImport("winspool.Drv", EntryPoint="SetPrinterA", SetLastError=true,

CharSet=CharSet.Auto, ExactSpelling=true,

CallingConvention=CallingConvention.StdCall), SuppressUnmanagedCodeSecurityAttribute()]

internal static extern bool SetPrinter(

IntPtr hPrinter,

[MarshalAs(UnmanagedType.I4)] int level,

IntPtr pPrinter,

[MarshalAs(UnmanagedType.I4)] int command);

/*

LONG DocumentProperties(

HWND hWnd, // handle to parent window

HANDLE hPrinter, // handle to printer object

LPTSTR pDeviceName, // device name

PDEVMODE pDevModeOutput, // modified device mode

PDEVMODE pDevModeInput, // original device mode

DWORD fMode // mode options

);

*/

[DllImport("winspool.Drv", EntryPoint="DocumentPropertiesA", SetLastError=true,

ExactSpelling=true, CallingConvention=CallingConvention.StdCall)]

public static extern int DocumentProperties(

IntPtr hwnd,

IntPtr hPrinter,

[MarshalAs(UnmanagedType.LPStr)] string pDeviceName /* changed from String to string */,

IntPtr pDevModeOutput,

IntPtr pDevModeInput,

int fMode

);

[DllImport("winspool.Drv", EntryPoint="GetPrinterA", SetLastError=true,

ExactSpelling=true, CallingConvention=CallingConvention.StdCall)]

public static extern bool GetPrinter(

IntPtr hPrinter,

int dwLevel /* changed type from Int32 */,

IntPtr pPrinter,

int dwBuf /* chagned from Int32*/,

out int dwNeeded /* changed from Int32*/

);

// SendMessageTimeout tools

[Flags] public enum SendMessageTimeoutFlags : uint

{

SMTO_NORMAL = 0x0000,

SMTO_BLOCK = 0x0001,

SMTO_ABORTIFHUNG = 0x0002,

SMTO_NOTIMEOUTIFNOTHUNG = 0x0008

}

const int WM_SETTINGCHANGE = 0x001A;

const int HWND_BROADCAST = 0xffff;

[DllImport("user32.dll", SetLastError=true, CharSet=CharSet.Auto)]

public static extern IntPtr SendMessageTimeout(

IntPtr windowHandle,

uint Msg,

IntPtr wParam,

IntPtr lParam,

SendMessageTimeoutFlags flags,

uint timeout,

out IntPtr result

);

//打印纸张长宽设置

public static void AddMC80MmPaperSizeToDefaultPrinter()

{

AddCustomPaperSizeToDefaultPrinter("MC 80mm * Receipt Length", 80.1f, 4003.9f);

}

public static void AddMC104MmPaperSizeToDefaultPrinter()

{

AddCustomPaperSizeToDefaultPrinter("MC 104mm * Receipt Length", 104.1f, 4003.9f);

}

/// <summary>

/// Adds the printer form to the default printer

/// </summary>

/// <param name="paperName">Name of the printer form</param>

/// <param name="widthMm">Width given in millimeters</param>

/// <param name="heightMm">Height given in millimeters</param>

public static void AddCustomPaperSizeToDefaultPrinter(string paperName, float widthMm, float heightMm)

{

PrintDocument pd = new PrintDocument();

string sPrinterName = pd.PrinterSettings.PrinterName;

AddCustomPaperSize(sPrinterName, paperName, widthMm, heightMm);

}

/// <summary>

/// Add the printer form to a printer

/// </summary>

/// <param name="printerName">The printer name</param>

/// <param name="paperName">Name of the printer form</param>

/// <param name="widthMm">Width given in millimeters</param>

/// <param name="heightMm">Height given in millimeters</param>

public static void AddCustomPaperSize(string printerName, string paperName, float

widthMm, float heightMm)

{

if (PlatformID.Win32NT == Environment.OSVersion.Platform)

{

// The code to add a custom paper size is different for Windows NT then it is

// for previous versions of windows

const int PRINTER_ACCESS_USE = 0x00000008;

const int PRINTER_ACCESS_ADMINISTER = 0x00000004;

const int FORM_PRINTER = 0x00000002;

structPrinterDefaults defaults = new structPrinterDefaults();

defaults.pDatatype = null;

defaults.pDevMode = IntPtr.Zero;

defaults.DesiredAccess = PRINTER_ACCESS_ADMINISTER | PRINTER_ACCESS_USE;

IntPtr hPrinter = IntPtr.Zero;

// Open the printer.

if (OpenPrinter(printerName, out hPrinter, ref defaults))

{

try

{

// delete the form incase it already exists

DeleteForm(hPrinter, paperName);

// create and initialize the FORM_INFO_1 structure

FormInfo1 formInfo = new FormInfo1();

formInfo.Flags = 0;

formInfo.pName = paperName;

// all sizes in 1000ths of millimeters

formInfo.Size.width = (int)(widthMm * 1000.0);

formInfo.Size.height = (int)(heightMm * 1000.0);

formInfo.ImageableArea.left = 0;

formInfo.ImageableArea.right = formInfo.Size.width;

formInfo.ImageableArea.top = 0;

formInfo.ImageableArea.bottom = formInfo.Size.height;

if (!AddForm(hPrinter, 1, ref formInfo))

{

StringBuilder strBuilder = new StringBuilder();

strBuilder.AppendFormat("Failed to add the custom paper size {0} to the printer {1}, System error number: {2}",

paperName, printerName, GetLastError());

throw new ApplicationException(strBuilder.ToString());

}

// INIT

const int DM_OUT_BUFFER = 2;

const int DM_IN_BUFFER = 8;

structDevMode devMode = new structDevMode();

IntPtr hPrinterInfo, hDummy;

PRINTER_INFO_9 printerInfo;

printerInfo.pDevMode = IntPtr.Zero;

int iPrinterInfoSize, iDummyInt;

// GET THE SIZE OF THE DEV_MODE BUFFER

int iDevModeSize = DocumentProperties(IntPtr.Zero, hPrinter, printerName, IntPtr.Zero, IntPtr.Zero, 0);

if(iDevModeSize < 0)

throw new ApplicationException("Cannot get the size of the DEVMODE structure.");

// ALLOCATE THE BUFFER

IntPtr hDevMode = Marshal.AllocCoTaskMem(iDevModeSize + 100);

// GET A POINTER TO THE DEV_MODE BUFFER

int iRet = DocumentProperties(IntPtr.Zero, hPrinter, printerName, hDevMode, IntPtr.Zero, DM_OUT_BUFFER);

if(iRet < 0)

throw new ApplicationException("Cannot get the DEVMODE structure.");

// FILL THE DEV_MODE STRUCTURE

devMode = (structDevMode)Marshal.PtrToStructure(hDevMode, devMode.GetType());

// SET THE FORM NAME FIELDS TO INDICATE THAT THIS FIELD WILL BE MODIFIED

devMode.dmFields = 0x10000; // DM_FORMNAME

// SET THE FORM NAME

devMode.dmFormName = paperName;

// PUT THE DEV_MODE STRUCTURE BACK INTO THE POINTER

Marshal.StructureToPtr(devMode, hDevMode, true);

// MERGE THE NEW CHAGES WITH THE OLD

iRet = DocumentProperties(IntPtr.Zero, hPrinter, printerName,

printerInfo.pDevMode, printerInfo.pDevMode, DM_IN_BUFFER | DM_OUT_BUFFER);

if(iRet < 0)

throw new ApplicationException("Unable to set the orientation setting for this printer.");

// GET THE PRINTER INFO SIZE

GetPrinter(hPrinter, 9, IntPtr.Zero, 0, out iPrinterInfoSize);

if(iPrinterInfoSize == 0)

throw new ApplicationException("GetPrinter failed. Couldn't get the # bytes needed for shared PRINTER_INFO_9 structure");

// ALLOCATE THE BUFFER

hPrinterInfo = Marshal.AllocCoTaskMem(iPrinterInfoSize + 100);

// GET A POINTER TO THE PRINTER INFO BUFFER

bool bSuccess = GetPrinter(hPrinter, 9, hPrinterInfo, iPrinterInfoSize, out iDummyInt);

if(!bSuccess)

throw new ApplicationException("GetPrinter failed. Couldn't get the shared PRINTER_INFO_9 structure");

// FILL THE PRINTER INFO STRUCTURE

printerInfo = (PRINTER_INFO_9)Marshal.PtrToStructure(hPrinterInfo, printerInfo.GetType());

printerInfo.pDevMode = hDevMode;

// GET A POINTER TO THE PRINTER INFO STRUCTURE

Marshal.StructureToPtr(printerInfo, hPrinterInfo, true);

// SET THE PRINTER SETTINGS

bSuccess = SetPrinter(hPrinter, 9, hPrinterInfo, 0);

if(!bSuccess)

throw new Win32Exception(Marshal.GetLastWin32Error(), "SetPrinter() failed. Couldn't set the printer settings");

// Tell all open programs that this change occurred.

SendMessageTimeout(

new IntPtr(HWND_BROADCAST),

WM_SETTINGCHANGE,

IntPtr.Zero,

IntPtr.Zero,

MCCustomPrintForm.SendMessageTimeoutFlags.SMTO_NORMAL,

1000,

out hDummy);

}

finally

{

ClosePrinter(hPrinter);

}

}

else

{

StringBuilder strBuilder = new StringBuilder();

strBuilder.AppendFormat("Failed to open the {0} printer, System error number: {1}",

printerName, GetLastError());

throw new ApplicationException(strBuilder.ToString());

}

}

else

{

structDevMode pDevMode = new structDevMode();

IntPtr hDC = CreateDC(null, printerName, null, ref pDevMode);

if (hDC != IntPtr.Zero)

{

const long DM_PAPERSIZE = 0x00000002L;

const long DM_PAPERLENGTH = 0x00000004L;

const long DM_PAPERWIDTH = 0x00000008L;

pDevMode.dmFields = (int)(DM_PAPERSIZE | DM_PAPERWIDTH | DM_PAPERLENGTH);

pDevMode.dmPaperSize = 256;

pDevMode.dmPaperWidth = (short)(widthMm * 1000.0);

pDevMode.dmPaperLength = (short)(heightMm * 1000.0);

ResetDC(hDC, ref pDevMode);

DeleteDC(hDC);

}

}

}

}

}

如果大家有什么新的改进,请在此评论上说说你的意见

如果觉得《弄了一整天 终于把打印自定义纸张大小搞定了》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。