C#中通过API实现的打印类 实例代码

代码如下:

using System;
using System.Collections;
using System.Text;
using System.Runtime.InteropServices;
using System.Security;
using System.ComponentModel;
using System.Drawing.Printing;
namespace PrinterAPI
{
 public class Printer
 {
  private Printer()
  {

}
 ///泥人张版本加强版
  #region API声明

[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)]
   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);

[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);

[DllImport("winspool.Drv", EntryPoint = "DocumentPropertiesA", SetLastError = true,
    ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
  internal static extern int DocumentProperties(
   IntPtr hwnd,
   IntPtr hPrinter,
   [MarshalAs(UnmanagedType.LPStr)] string pDeviceName,
   IntPtr pDevModeOutput,
   IntPtr pDevModeInput,
   int fMode
   );

[DllImport("winspool.Drv", EntryPoint = "GetPrinterA", SetLastError = true,
    ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
  internal static extern bool GetPrinter(
   IntPtr hPrinter,
   int dwLevel,
   IntPtr pPrinter,
   int dwBuf,
   out int dwNeeded
   );

[Flags]
   internal 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)]
  internal static extern IntPtr SendMessageTimeout(
   IntPtr windowHandle,
   uint Msg,
   IntPtr wParam,
   IntPtr lParam,
   SendMessageTimeoutFlags flags,
   uint timeout,
   out IntPtr result
   );

//EnumPrinters用到的函数和结构体
  [DllImport("winspool.drv", CharSet = CharSet.Auto, SetLastError = true)]
  private static extern bool EnumPrinters(PrinterEnumFlags Flags, string Name, uint Level,
   IntPtr pPrinterEnum, uint cbBuf,
   ref uint pcbNeeded, ref uint pcReturned);

[StructLayout(LayoutKind.Sequential)]
   internal struct PRINTER_INFO_2
  {
   public string pServerName;
   public string pPrinterName;
   public string pShareName;
   public string pPortName;
   public string pDriverName;
   public string pComment;
   public string pLocation;
   public IntPtr pDevMode;
   public string pSepFile;
   public string pPrintProcessor;
   public string pDatatype;
   public string pParameters;
   public IntPtr pSecurityDescriptor;
   public uint Attributes;
   public uint Priority;
   public uint DefaultPriority;
   public uint StartTime;
   public uint UntilTime;
   public uint Status;
   public uint cJobs;
   public uint AveragePPM;
  }

[FlagsAttribute]
   internal enum PrinterEnumFlags
  {
   PRINTER_ENUM_DEFAULT = 0x00000001,
   PRINTER_ENUM_LOCAL = 0x00000002,
   PRINTER_ENUM_CONNECTIONS = 0x00000004,
   PRINTER_ENUM_FAVORITE = 0x00000004,
   PRINTER_ENUM_NAME = 0x00000008,
   PRINTER_ENUM_REMOTE = 0x00000010,
   PRINTER_ENUM_SHARED = 0x00000020,
   PRINTER_ENUM_NETWORK = 0x00000040,
   PRINTER_ENUM_EXPAND = 0x00004000,
   PRINTER_ENUM_CONTAINER = 0x00008000,
   PRINTER_ENUM_ICONMASK = 0x00ff0000,
   PRINTER_ENUM_ICON1 = 0x00010000,
   PRINTER_ENUM_ICON2 = 0x00020000,
   PRINTER_ENUM_ICON3 = 0x00040000,
   PRINTER_ENUM_ICON4 = 0x00080000,
   PRINTER_ENUM_ICON5 = 0x00100000,
   PRINTER_ENUM_ICON6 = 0x00200000,
   PRINTER_ENUM_ICON7 = 0x00400000,
   PRINTER_ENUM_ICON8 = 0x00800000,
   PRINTER_ENUM_HIDE = 0x01000000
  }

//打印机状态
  [FlagsAttribute]
   internal enum PrinterStatus
  {
   PRINTER_STATUS_BUSY                 =       0x00000200,
   PRINTER_STATUS_DOOR_OPEN            =       0x00400000,
   PRINTER_STATUS_ERROR                =       0x00000002,
   PRINTER_STATUS_INITIALIZING         =       0x00008000,
   PRINTER_STATUS_IO_ACTIVE            =       0x00000100,
   PRINTER_STATUS_MANUAL_FEED          =       0x00000020,
   PRINTER_STATUS_NO_TONER             =       0x00040000,
   PRINTER_STATUS_NOT_AVAILABLE        =       0x00001000,
   PRINTER_STATUS_OFFLINE              =       0x00000080,
   PRINTER_STATUS_OUT_OF_MEMORY        =       0x00200000,
   PRINTER_STATUS_OUTPUT_BIN_FULL      =       0x00000800,
   PRINTER_STATUS_PAGE_PUNT            =       0x00080000,
   PRINTER_STATUS_PAPER_JAM            =       0x00000008,
   PRINTER_STATUS_PAPER_OUT            =       0x00000010,
   PRINTER_STATUS_PAPER_PROBLEM        =       0x00000040,
   PRINTER_STATUS_PAUSED               =       0x00000001,
   PRINTER_STATUS_PENDING_DELETION     =       0x00000004,
   PRINTER_STATUS_PRINTING             =       0x00000400,
   PRINTER_STATUS_PROCESSING           =       0x00004000,
   PRINTER_STATUS_TONER_LOW            =       0x00020000,
   PRINTER_STATUS_USER_INTERVENTION    =       0x00100000,
   PRINTER_STATUS_WAITING              =       0x20000000,
   PRINTER_STATUS_WARMING_UP           =       0x00010000
  }

//GetDefaultPrinter用到的API函数说明
  [DllImport("winspool.drv", CharSet = CharSet.Auto, SetLastError = true)]
  internal static extern bool GetDefaultPrinter(StringBuilder pszBuffer, ref int size);

//SetDefaultPrinter用到的API函数声明
  [DllImport("winspool.drv", CharSet = CharSet.Auto, SetLastError = true)]
  internal static extern bool SetDefaultPrinter(string Name);

//EnumFormsA用到的函数声明,应该和EnumPrinters类似
  [DllImport("winspool.drv", EntryPoint = "EnumForms")]
  internal static extern int EnumFormsA(IntPtr hPrinter, int Level, ref byte pForm, int cbBuf, ref int pcbNeeded, ref int pcReturned);

#endregion   API声明

internal static int GetPrinterStatusInt(string PrinterName)
  {
   int intRet = 0;
   IntPtr hPrinter;
   structPrinterDefaults defaults = new structPrinterDefaults();

if (OpenPrinter(PrinterName, out hPrinter, ref defaults))
   {
    int cbNeeded = 0;
    bool bolRet = GetPrinter(hPrinter, 2, IntPtr.Zero, 0, out cbNeeded);
    if (cbNeeded > 0)
    {
     IntPtr pAddr = Marshal.AllocHGlobal((int)cbNeeded);
     bolRet = GetPrinter(hPrinter, 2, pAddr, cbNeeded, out cbNeeded);
     if (bolRet)
     {
      PRINTER_INFO_2 Info2 = new PRINTER_INFO_2();

Info2 = (PRINTER_INFO_2)Marshal.PtrToStructure(pAddr, typeof(PRINTER_INFO_2));

intRet = System.Convert.ToInt32(Info2.Status);
     }
     Marshal.FreeHGlobal(pAddr);
    }
    ClosePrinter(hPrinter);
   }

return intRet;
  }

internal static PRINTER_INFO_2[] EnumPrintersByFlag(PrinterEnumFlags Flags)
  {
   uint cbNeeded = 0;
   uint cReturned = 0;
   bool ret = EnumPrinters( PrinterEnumFlags.PRINTER_ENUM_LOCAL, null, 2, IntPtr.Zero, 0, ref cbNeeded, ref cReturned);

IntPtr pAddr = Marshal.AllocHGlobal((int)cbNeeded);
   ret = EnumPrinters(PrinterEnumFlags.PRINTER_ENUM_LOCAL, null, 2, pAddr, cbNeeded, ref cbNeeded, ref cReturned);

if (ret)
   {
    PRINTER_INFO_2[] Info2 = new PRINTER_INFO_2[cReturned];

int offset = pAddr.ToInt32();

for (int i = 0; i < cReturned; i++)
    {
     Info2[i].pServerName = Marshal.PtrToStringAuto(Marshal.ReadIntPtr(new IntPtr(offset)));
     offset += 4;
     Info2[i].pPrinterName = Marshal.PtrToStringAuto(Marshal.ReadIntPtr(new IntPtr(offset)));
     offset += 4;
     Info2[i].pShareName = Marshal.PtrToStringAuto(Marshal.ReadIntPtr(new IntPtr(offset)));
     offset += 4;
     Info2[i].pPortName = Marshal.PtrToStringAuto(Marshal.ReadIntPtr(new IntPtr(offset)));
     offset += 4;
     Info2[i].pDriverName = Marshal.PtrToStringAuto(Marshal.ReadIntPtr(new IntPtr(offset)));
     offset += 4;
     Info2[i].pComment = Marshal.PtrToStringAuto(Marshal.ReadIntPtr(new IntPtr(offset)));
     offset += 4;
     Info2[i].pLocation = Marshal.PtrToStringAuto(Marshal.ReadIntPtr(new IntPtr(offset)));
     offset += 4;
     Info2[i].pDevMode = Marshal.ReadIntPtr(new IntPtr(offset));
     offset += 4;
     Info2[i].pSepFile = Marshal.PtrToStringAuto(Marshal.ReadIntPtr(new IntPtr(offset)));
     offset += 4;
     Info2[i].pPrintProcessor = Marshal.PtrToStringAuto(Marshal.ReadIntPtr(new IntPtr(offset)));
     offset += 4;
     Info2[i].pDatatype = Marshal.PtrToStringAuto(Marshal.ReadIntPtr(new IntPtr(offset)));
     offset += 4;
     Info2[i].pParameters = Marshal.PtrToStringAuto(Marshal.ReadIntPtr(new IntPtr(offset)));
     offset += 4;
     Info2[i].pSecurityDescriptor = Marshal.ReadIntPtr(new IntPtr(offset));
     offset += 4;
     Info2[i].Attributes = (uint )Marshal.ReadIntPtr(new IntPtr(offset));
     offset += 4;
     Info2[i].Priority = (uint)Marshal.ReadInt32(new IntPtr(offset));
     offset += 4;
     Info2[i].DefaultPriority = (uint)Marshal.ReadInt32(new IntPtr(offset));
     offset += 4;
     Info2[i].StartTime = (uint)Marshal.ReadInt32(new IntPtr(offset));
     offset += 4;
     Info2[i].UntilTime = (uint)Marshal.ReadInt32(new IntPtr(offset));
     offset += 4;
     Info2[i].Status = (uint)Marshal.ReadInt32(new IntPtr(offset));
     offset += 4;
     Info2[i].cJobs = (uint)Marshal.ReadInt32(new IntPtr(offset));
     offset += 4;
     Info2[i].AveragePPM = (uint)Marshal.ReadInt32(new IntPtr(offset));
     offset += 4;

}

Marshal.FreeHGlobal(pAddr);

return Info2;

}
   else
   {
    return new PRINTER_INFO_2[0];
   }
  }

#region 获取当前指定打印机的状态
  /// </summary>
  /// 获取当前指定打印机的状态
  /// </summary>
  /// <param name="PrinterName">打印机名称</param>
  /// <returns>打印机状态描述</returns>

public static string GetPrinterStatus(string PrinterName)
  {
   int intValue = GetPrinterStatusInt(PrinterName);
   string strRet = string.Empty;
   switch (intValue)
   {
    case 0:
     strRet = "准备就绪(Ready)";
     break;
    case 0x00000200:
     strRet = "忙(Busy)";
     break;
    case 0x00400000:
     strRet = "门被打开(Printer Door Open)";
     break;
    case 0x00000002:
     strRet = "错误(Printer Error)";
     break;
    case 0x0008000:
     strRet = "正在初始化(Initializing)";
     break;
    case 0x00000100:
     strRet = "正在输入或输出(I/O Active)";
     break;
    case 0x00000020:
     strRet = "手工送纸(Manual Feed)";
     break;
    case 0x00040000:
     strRet = "无墨粉(No Toner)";
     break;
    case 0x00001000:
     strRet = "不可用(Not Available)";
     break;
    case 0x00000080:
     strRet = "脱机(Off Line)";
     break;
    case 0x00200000:
     strRet = "内存溢出(Out of Memory)";
     break;
    case 0x00000800:
     strRet = "输出口已满(Output Bin Full)";
     break;
    case 0x00080000:
     strRet = "当前页无法打印(Page Punt)";
     break;
    case 0x00000008:
     strRet = "塞纸(Paper Jam)";
     break;
    case 0x00000010:
     strRet = "打印纸用完(Paper Out)";
     break;
    case 0x00000040:
     strRet = "纸张问题(Page Problem)";
     break;
    case 0x00000001:
     strRet = "暂停(Paused)";
     break;
    case 0x00000004:
     strRet = "正在删除(Pending Deletion)";
     break;
    case 0x00000400:
     strRet = "正在打印(Printing)";
     break;
    case 0x00004000:
     strRet = "正在处理(Processing)";
     break;
    case 0x00020000:
     strRet = "墨粉不足(Toner Low)";
     break;
    case 0x00100000:
     strRet = "需要用户干预(User Intervention)";
     break;
    case 0x20000000:
     strRet = "等待(Waiting)";
     break;
    case 0x00010000:
     strRet = "正在准备(Warming Up)";
     break;
    default:
     strRet = "未知状态(Unknown Status)";
     break;
   }
   return strRet;
  }
  #endregion 获取当前指定打印机的状态
  #region 删除已经存在的自定义纸张
  /**/
  /// <summary>
  /// 删除已经存在的自定义纸张
  /// </summary>
  /// <param name="PrinterName">打印机名称</param>
  /// <param name="PaperName">纸张名称</param>
  public static void DeleteCustomPaperSize(string PrinterName, string PaperName)
  {
   const int PRINTER_ACCESS_USE = 0x00000008;
   const int PRINTER_ACCESS_ADMINISTER = 0x00000004;

structPrinterDefaults defaults = new structPrinterDefaults();
   defaults.pDatatype = null;
   defaults.pDevMode = IntPtr.Zero;
   defaults.DesiredAccess = PRINTER_ACCESS_ADMINISTER | PRINTER_ACCESS_USE;

IntPtr hPrinter = IntPtr.Zero;

//打开打印机
   if (OpenPrinter(PrinterName, out hPrinter, ref defaults))
   {
    try
    {
     DeleteForm(hPrinter, PaperName);
     ClosePrinter(hPrinter);
    }
    catch
    {

}
   }
  }
  #endregion 删除已经存在的自定义纸张
  #region 指定的打印机设置以mm为单位的自定义纸张(Form)
  /**/
  /// <summary>
  /// 指定的打印机设置以mm为单位的自定义纸张(Form)
  /// </summary>
  /// <param name="PrinterName">打印机名称</param>
  /// <param name="PaperName">Form名称</param>
  /// <param name="WidthInMm">以mm为单位的宽度</param>
  /// <param name="HeightInMm">以mm为单位的高度</param>
  public static void AddCustomPaperSize(string PrinterName, string PaperName, float WidthInMm, float HeightInMm)
  {
   if (PlatformID.Win32NT == Environment.OSVersion.Platform)
   {
    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;

//打开打印机
    if (OpenPrinter(PrinterName, out hPrinter, ref defaults))
    {
     try
     {
      //如果Form存在删除之
      DeleteForm(hPrinter, PaperName);
      //创建并初始化FORM_INFO_1
      FormInfo1 formInfo = new FormInfo1();
      formInfo.Flags = 0;
      formInfo.pName = PaperName;
      formInfo.Size.width = (int)(WidthInMm * 1000.0);
      formInfo.Size.height = (int)(HeightInMm * 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("向打印机 {1} 添加自定义纸张 {0} 失败!错误代号:{2}",
        PaperName, PrinterName, GetLastError());
       throw new ApplicationException(strBuilder.ToString());
      }

//初始化
      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;

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

if (iDevModeSize < 0)
       throw new ApplicationException("无法取得DEVMODE结构的大小!");

//分配缓冲
      IntPtr hDevMode = Marshal.AllocCoTaskMem(iDevModeSize + 100);

//获取DEV_MODE指针
      int iRet = DocumentProperties(IntPtr.Zero, hPrinter, PrinterName, hDevMode, IntPtr.Zero, DM_OUT_BUFFER);

if (iRet < 0)
       throw new ApplicationException("无法获得DEVMODE结构!");

//填充DEV_MODE
      devMode = (structDevMode)Marshal.PtrToStructure(hDevMode, devMode.GetType());

devMode.dmFields = 0x10000;

//FORM名称
      devMode.dmFormName = PaperName;

Marshal.StructureToPtr(devMode, hDevMode, true);

iRet = DocumentProperties(IntPtr.Zero, hPrinter, PrinterName,
       printerInfo.pDevMode, printerInfo.pDevMode, DM_IN_BUFFER | DM_OUT_BUFFER);

if (iRet < 0)
       throw new ApplicationException("无法为打印机设定打印方向!");

GetPrinter(hPrinter, 9, IntPtr.Zero, 0, out iPrinterInfoSize);
      if (iPrinterInfoSize == 0)
       throw new ApplicationException("调用GetPrinter方法失败!");

hPrinterInfo = Marshal.AllocCoTaskMem(iPrinterInfoSize + 100);

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

if (!bSuccess)
       throw new ApplicationException("调用GetPrinter方法失败!");

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

Marshal.StructureToPtr(printerInfo, hPrinterInfo, true);

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

if (!bSuccess)
       throw new Win32Exception(Marshal.GetLastWin32Error(), "调用SetPrinter方法失败,无法进行打印机设置!");

SendMessageTimeout(
       new IntPtr(HWND_BROADCAST),
       WM_SETTINGCHANGE,
       IntPtr.Zero,
       IntPtr.Zero,
       Printer.SendMessageTimeoutFlags.SMTO_NORMAL,
       1000,
       out hDummy);
     }
     finally
     {
      ClosePrinter(hPrinter);
     }
    }
    else
    {
     StringBuilder strBuilder = new StringBuilder();
     strBuilder.AppendFormat("无法打开打印机{0}, 错误代号: {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)(WidthInMm * 1000.0);
     pDevMode.dmPaperLength = (short)(HeightInMm * 1000.0);
     ResetDC(hDC, ref pDevMode);
     DeleteDC(hDC);
    }
   }
  }
  #endregion 指定的打印机设置以mm为单位的自定义纸张(Form)
  #region 获取本地打印机列表
  /**/
  /// <summary>
  /// 获取本地打印机列表
  /// 可以通过制定参数获取网络打印机
  /// </summary>
  /// <returns>打印机列表</returns>
  public static System.Collections.ArrayList GetPrinterList()
  {
   System.Collections.ArrayList alRet = new System.Collections.ArrayList();
   PRINTER_INFO_2[] Info2 = EnumPrintersByFlag(PrinterEnumFlags.PRINTER_ENUM_LOCAL);
   for (int i = 0; i < Info2.Length; i++)
   {
    alRet.Add(Info2[i].pPrinterName);
   }
   return alRet;
  }
  #endregion 获取本地打印机列表
  #region 获取本机的默认打印机名称
  /**/
  /// <summary>
  /// 获取本机的默认打印机名称
  /// </summary>
  /// <returns>默认打印机名称</returns>
  public static string GetDeaultPrinterName()
  {
   StringBuilder dp = new StringBuilder(256);
   int size = dp.Capacity;
   if (GetDefaultPrinter(dp, ref size))
   {
    return dp.ToString();
   }
   else
   {
    return string.Empty;
   }
  }
  #endregion 获取本机的默认打印机名称
  #region 设置默认打印机
  /**/
  /// <summary>
  /// 设置默认打印机
  /// </summary>
  /// <param name="PrinterName">可用的打印机名称</param>
  public static void SetPrinterToDefault(string PrinterName)
  {
   SetDefaultPrinter(PrinterName);
  }
  #endregion 设置默认打印机
  #region 判断打印机是否在系统可用的打印机列表中
  /**/
  ///// <summary>
  ///// 判断打印机是否在系统可用的打印机列表中
  ///// </summary>
  ///// <param name="PrinterName">打印机名称</param>
  ///// <returns>是:在;否:不在</returns>
  public static bool PrinterInList(string PrinterName)
  {
   bool bolRet = false;

System.Collections.ArrayList alPrinters = GetPrinterList();

for (int i = 0; i < alPrinters.Count; i++)
   {
    if (PrinterName == alPrinters[i].ToString())
    {
     bolRet = true;
     break;
    }
   }

alPrinters.Clear();
   alPrinters = null;

return bolRet;
  }
  #endregion 判断打印机是否在系统可用的打印机列表中
  #region 判断表单是否在指定的打印机所支持的纸张列表中
  /**/
  ///// <summary>
  ///// 判断表单是否在指定的打印机所支持的纸张列表中,表单就是我们平常所说的纸张
  ///// </summary>
  ///// <param name="PrinterName">打印机名称</param>
  ///// <param name="PaperName">纸张名称</param>
  ///// <returns>是:在;否:不在</returns>
  public static bool FormInPrinter(string PrinterName, string PaperName)
  {
   bool bolRet = false;

System.Drawing.Printing.PrintDocument pd = new System.Drawing.Printing.PrintDocument();

pd.PrinterSettings.PrinterName = PrinterName;

foreach (System.Drawing.Printing.PaperSize ps in pd.PrinterSettings.PaperSizes)
   {
    if (ps.PaperName == PaperName)
    {
     bolRet = true;
     break;
    }
   }

pd.Dispose();

return bolRet;
  }
  #endregion 判断表单是否在指定的打印机所支持的纸张列表中
  #region 判断指定纸张的宽度和高度和与打印内容指定的宽度和高度是否匹配
  /**/
  /// <summary>
  /// 判断指定纸张的宽度和高度和与打印内容指定的宽度和高度是否匹配
  /// </summary>
  /// <param name="PrinterName">打印机名称</param>
  /// <param name="FormName">表单名称</param>
  /// <param name="Width">宽度</param>
  /// <param name="Height">高度</param>
  /// <returns></returns>
  public static bool FormSameSize(string PrinterName, string FormName, decimal Width, decimal Height)
  {
   bool bolRet = false;

System.Drawing.Printing.PrintDocument pd = new System.Drawing.Printing.PrintDocument();

pd.PrinterSettings.PrinterName = PrinterName;

foreach (System.Drawing.Printing.PaperSize ps in pd.PrinterSettings.PaperSizes)
   {
    if (ps.PaperName == FormName)
    {
     decimal decWidth = FromInchToCM(System.Convert.ToDecimal(ps.Width));
     decimal decHeight = FromInchToCM(System.Convert.ToDecimal(ps.Height));
     //只要整数位相同即认为是同一纸张,毕竟inch到cm的转换并不能整除
     if (Math.Round(decWidth, 0) == Math.Round(Width, 0) && Math.Round(decHeight, 0) == Math.Round(Height, 0))
      bolRet = true;
     break;
    }
   }

pd.Dispose();

return bolRet;
  }
  #endregion 判断指定纸张的宽度和高度和与打印内容指定的宽度和高度是否匹配
  #region 英寸到厘米的转换
  /**/
  /// <summary>
  /// 英寸到厘米的转换
        /// /* = = = = = = = = = = = = = = = = *\
        /// | 换算一下计量单位,将其换算成厘米  |
        /// |    厘米     像素     英寸         |
        /// |     1        38     0.395         |
        /// |   0.026       1      0.01         |
        /// |    2.54      96        1          |
        /// \* = = = = = = = = = = = = = = = = */
  /// </summary>
  /// <param name="inch">英寸数</param>
  /// <returns>厘米数,两位小数</returns>
        ///
  public static decimal FromInchToCM(decimal inch)
  {
   return Math.Round((System.Convert.ToDecimal((inch / 100)) * System.Convert.ToDecimal(2.5400)), 2);
  }
  #endregion 英寸到厘米的转换
 }

}

(0)

相关推荐

  • C#基本打印事件用法实例

    本文实例讲述了C#基本打印事件用法.分享给大家供大家参考.具体如下: using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; namespace WindowsApplication3 { public partial cla

  • C#打印出正等腰三角形实例代码

    复制代码 代码如下: using System;using System.Collections.Generic;using System.Linq;using System.Text; namespace 打印正三角{    class Program    {        static void Main(string[] args)        { Console.WriteLine("请输入要打印的行数:");            int n=Convert.ToInt3

  • C#实现打印与打印预览功能的思路及代码

    在windows应用程序中文档的打印是一项非常重要的功能,在以前一直是一个非常复杂的工作,Microsoft .Net Framework的打印功能都以组件的方式提供,为程序员提供了很大的方便,但是这几个组件的使用还是很复杂的,有必要解释一下. 打印操作通常包括以下四个功能: 1 打印设置 设置打印机的一些参数,比如更改打印机驱动程序等; 2 页面设置 设置页面大小纸张类型等 3 打印预览 类似于word中的打印预览 4 打印 实现打印功能的核心是PrintDocument类这个类属于Syste

  • C#使用前序遍历、中序遍历和后序遍历打印二叉树的方法

    本文实例讲述了C#使用前序遍历.中序遍历和后序遍历打印二叉树的方法.分享给大家供大家参考.具体实现方法如下: public class BinaryTreeNode { public BinaryTreeNode Left { get; set; } public BinaryTreeNode Right { get; set; } public int Data { get; set; } public BinaryTreeNode(int data) { this.Data = data;

  • C# 实现简单打印的实例代码

    主窗体代码如下: 复制代码 代码如下: public partial class PrintFileForm : Form    {        public PrintFileForm()        {            InitializeComponent();            PrintFile prinFile = new PrintFile();            prinFile.Print();        }    } 打印文件类如下: 复制代码 代码如下

  • c#打印预览控件中实现用鼠标移动页面功能代码分享

    该功能本来可以通过拉动水平和垂直滚动条来实现,但实际使用中,用户更趋向于直接用鼠标拖动页面来实现,很多看图类软件都有这种类似的功能.而.net的打印预览控件却很遗憾的没有提供这一功能,只来自己想办法来实现啦. 我的办法就是用代码来控制打印预览控件中的水平来垂直滚动条的位置,间接实现和用鼠标直接拖动滚动条一样的效果. 在实现这一功能的过程中,最大的困难是打印预览控件并没有让程序员直接调用的关于滚动条的方法或属性.所以只好向WinAPI求助了. 以下API函数和常量就是实现上述功能的关键了: 复制代

  • C# 获取打印机当前状态的方法

    要获得打印机的状态,应该定义一个联合. 复制代码 代码如下: enum PrinterStatus { 其他状态= 1, 未知, 空闲, 正在打印, 预热, 停止打印, 打印中, 离线} 其中的"正在打印"和"打印中"是同一个意思,至于为什么会是这样,目前还不知道. 在程序中添加System.Management的引用:using System.Management; 然后编写获取打印机状态的函数如下: 复制代码 代码如下: /// <summary> 

  • C#使用控制台列出当前所有可用的打印机列表

    本文实例讲述了C#使用控制台列出当前所有可用打印机列表的方法.分享给大家供大家参考.具体如下: // The initial C# code for the WMI query was generated by WMI Code //Generator, Version 5.00, http://www.robvanderwoude.com/wmigen.php using System; using System.Management; using System.Collections; na

  • C#打印绘图的实现方法

    本文实例讲述了C#打印绘图的实现方法.分享给大家供大家参考.具体实现方法如下: 复制代码 代码如下: String drawString = ""; Font drawFont = null; SolidBrush drawBrush = null; float x = 0F; float y = 0F; StringFormat drawFormat = new StringFormat(); string test = ""; public string Tes

  • C#中通过API实现的打印类 实例代码

    复制代码 代码如下: using System;using System.Collections;using System.Text;using System.Runtime.InteropServices; using System.Security; using System.ComponentModel; using System.Drawing.Printing; namespace PrinterAPI{ public class Printer  {   private Printe

  • Java 中jasperReport实现动态列打印的实现代码

    Java 中jasperReport实现动态列打印的实现代码 以下代码中注释说明很清楚,希望能帮助到大家,大家参考下. 示例代码: public ActionResult projectPrint() { String[] printValue = null; // 从页面中获得要查询的字段 String reqPrintValue = getRequest().getParameter("printValue"); // 没有选择则默认全打印 if (null == reqPrint

  • Android快速开发系列 10个常用工具类实例代码详解

    打开大家手上的项目,基本都会有一大批的辅助类,今天特此整理出10个基本每个项目中都会使用的工具类,用于快速开发~~在此感谢群里给我发项目中工具类的兄弟/姐妹~ 1.日志工具类L.java package com.zhy.utils; import android.util.Log; /** * Log统一管理类 * * * */ public class L { private L() { /* cannot be instantiated */ throw new UnsupportedOpe

  • C++实现String类实例代码

    C++实现String类实例代码 这是一道十分经典的面试题,可以短时间内考查学生对C++的掌握是否全面,答案要包括C++类的多数知识,保证编写的String类可以完成赋值.拷贝.定义变量等功能. #include<iostream> using namespace std; class String { public: String(const char *str=NULL); String(const String &other); ~String(void); String &am

  • Android 中TabLayout自定义选择背景滑块的实例代码

    TabLayout是Android 的Material Design包中的一个控件,可以和V4包中的ViewPager搭配产生一个联动的效果.这里我自定义了一个滑块能够跟随TabLayout进行滑动选择的SliderLayout.效果见下图(白色方框): 下面是SliderLayout的源码: import android.content.Context; import android.content.res.TypedArray; import android.graphics.drawabl

  • PHP之图片上传类实例代码(加了缩略图)

    有缩略图功能 但是 感觉不全面,而且有点问题,继续学习,将来以后修改下 <form action="<?php $_SERVER['PHP_SELF']; ?>" enctype="multipart/form-data" method="post" ><input type="text" name="name" /><input type="file&q

  • Java语言描述MD5加密工具类实例代码

    编程中经常有用到MD5加密的情况,Java语言并没有像PHP一样提供原生的MD5加密字符串的函数,需要MD5加密的时候,往往需要自己写. 代码如下: import java.security.MessageDigest; public class MD5 { //公盐 private static final String PUBLIC_SALT = "demo" ; //十六进制下数字到字符的映射数组 private final static String[] hexDigits =

  • java date类与string类实例代码分享

    Date类用来指定日期和时间,其构造函数及常用方法如下: publicDate() 从当前时间构造日期时间对象. publicStringtoString() 转换成字符串. publiclonggetTime() 返回自新世纪以来的毫秒数,可以用于时间计算. [例3.10]测试执行循环花费的时间(数量级为毫秒),具体时间情况如图3.9所示.源程序代码如下: //程序文件名为UseDate.java import java.util.Date; public class UseDate { pu

  • C语言打印正方形实例代码

    目录 题目描述 输入 输出 样例输入 样例输出 题目描述 由火柴棍组成的一个n×n的正方形,按从上到下,从左到右的顺序给火柴棍编号,从1开始,比如下图中,一共有24根火柴棍. 问去掉若干个火柴棍之后,这个图形中还存在多少个正方形? 如下图所示,n=3时,去掉12,17,23号火柴棒之后,还剩下5个正方形. 输入 第一行是一个整数T(1≤T≤1000),表示样例的个数. 每个样例的第1行是两个整数n(1≤n≤50),表示图形的宽度. 样例的第2行首先是一个整数m(0≤m≤2n(n+1),表示去掉火

  • vue中keep-alive内置组件缓存的实例代码

    需求: home 组件中有一个 name 的 data 数据.这个数据修改之后,再切换到其他的组件.再切换到 home 组件,希望 home 中 name 这个值是之前修改过的值.希望组件有缓存. keep-alive 的使用方式: 将要缓存的组件使用 keep-alive 包裹住即可. keep-alive优点的介绍: 1. 切换组件时,当前组件不会触发销毁的生命周期钩子.也就是说不会销毁了. 2. 切换回来时,也不会重新创建.(既然都没有被销毁,哪里来的重新创建呢) 3. 会多出两个生命周期

随机推荐