1. using System;
  2. using System.Text;
  3. using System.Runtime.InteropServices;
  4. using System.Security;
  5. using System.ComponentModel;
  6.  
  7. namespace SoftPOS
  8. {
  9. public class PrinterHelper
  10. {
  11. private PrinterHelper(){ }
  12. #region API声明
  13. [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
  14. internal struct structPrinterDefaults
  15. {
  16. [MarshalAs(UnmanagedType.LPTStr)]
  17. public String pDatatype;
  18. public IntPtr pDevMode;
  19. [MarshalAs(UnmanagedType.I4)]
  20. public int DesiredAccess;
  21. };
  22. [DllImport("winspool.Drv", EntryPoint = "OpenPrinter", SetLastError = true,CharSet = CharSet.Unicode, ExactSpelling = false, CallingConvention = CallingConvention.StdCall),
  23. SuppressUnmanagedCodeSecurityAttribute()]
  24. internal static extern bool OpenPrinter([MarshalAs(UnmanagedType.LPTStr)] string printerName,out IntPtr phPrinter,ref structPrinterDefaults pd);
  25.  
  26. [DllImport("winspool.Drv", EntryPoint = "ClosePrinter", SetLastError = true,CharSet = CharSet.Unicode, ExactSpelling = false,CallingConvention = CallingConvention.StdCall), SuppressUnmanagedCodeSecurityAttribute()]
  27. internal static extern bool ClosePrinter(IntPtr phPrinter);
  28.  
  29. [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
  30. internal struct structSize
  31. {
  32. public Int32 width;
  33. public Int32 height;
  34. }
  35.  
  36. [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
  37. internal struct structRect
  38. {
  39. public Int32 left;
  40. public Int32 top;
  41. public Int32 right;
  42. public Int32 bottom;
  43. }
  44.  
  45. [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Unicode)]
  46. internal struct FormInfo1
  47. {
  48. [FieldOffset(0), MarshalAs(UnmanagedType.I4)]
  49. public uint Flags;
  50. [FieldOffset(4), MarshalAs(UnmanagedType.LPWStr)]
  51. public String pName;
  52. [FieldOffset(8)]
  53. public structSize Size;
  54. [FieldOffset(16)]
  55. public structRect ImageableArea;
  56. };
  57.  
  58. [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
  59. internal struct structDevMode
  60. {
  61. [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
  62. public String
  63. dmDeviceName;
  64. [MarshalAs(UnmanagedType.U2)]
  65. public short dmSpecVersion;
  66. [MarshalAs(UnmanagedType.U2)]
  67. public short dmDriverVersion;
  68. [MarshalAs(UnmanagedType.U2)]
  69. public short dmSize;
  70. [MarshalAs(UnmanagedType.U2)]
  71. public short dmDriverExtra;
  72. [MarshalAs(UnmanagedType.U4)]
  73. public int dmFields;
  74. [MarshalAs(UnmanagedType.I2)]
  75. public short dmOrientation;
  76. [MarshalAs(UnmanagedType.I2)]
  77. public short dmPaperSize;
  78. [MarshalAs(UnmanagedType.I2)]
  79. public short dmPaperLength;
  80. [MarshalAs(UnmanagedType.I2)]
  81. public short dmPaperWidth;
  82. [MarshalAs(UnmanagedType.I2)]
  83. public short dmScale;
  84. [MarshalAs(UnmanagedType.I2)]
  85. public short dmCopies;
  86. [MarshalAs(UnmanagedType.I2)]
  87. public short dmDefaultSource;
  88. [MarshalAs(UnmanagedType.I2)]
  89. public short dmPrintQuality;
  90. [MarshalAs(UnmanagedType.I2)]
  91. public short dmColor;
  92. [MarshalAs(UnmanagedType.I2)]
  93. public short dmDuplex;
  94. [MarshalAs(UnmanagedType.I2)]
  95. public short dmYResolution;
  96. [MarshalAs(UnmanagedType.I2)]
  97. public short dmTTOption;
  98. [MarshalAs(UnmanagedType.I2)]
  99. public short dmCollate;
  100. [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
  101. public String dmFormName;
  102. [MarshalAs(UnmanagedType.U2)]
  103. public short dmLogPixels;
  104. [MarshalAs(UnmanagedType.U4)]
  105. public int dmBitsPerPel;
  106. [MarshalAs(UnmanagedType.U4)]
  107. public int dmPelsWidth;
  108. [MarshalAs(UnmanagedType.U4)]
  109. public int dmPelsHeight;
  110. [MarshalAs(UnmanagedType.U4)]
  111. public int dmNup;
  112. [MarshalAs(UnmanagedType.U4)]
  113. public int dmDisplayFrequency;
  114. [MarshalAs(UnmanagedType.U4)]
  115. public int dmICMMethod;
  116. [MarshalAs(UnmanagedType.U4)]
  117. public int dmICMIntent;
  118. [MarshalAs(UnmanagedType.U4)]
  119. public int dmMediaType;
  120. [MarshalAs(UnmanagedType.U4)]
  121. public int dmDitherType;
  122. [MarshalAs(UnmanagedType.U4)]
  123. public int dmReserved1;
  124. [MarshalAs(UnmanagedType.U4)]
  125. public int dmReserved2;
  126. }
  127.  
  128. [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
  129. internal struct PRINTER_INFO_9
  130. {
  131. public IntPtr pDevMode;
  132. }
  133.  
  134. [DllImport("winspool.Drv", EntryPoint = "AddFormW", SetLastError = true,CharSet = CharSet.Unicode, ExactSpelling = true,
  135. CallingConvention = CallingConvention.StdCall), SuppressUnmanagedCodeSecurityAttribute()]
  136. internal static extern bool AddForm(IntPtr phPrinter,[MarshalAs(UnmanagedType.I4)] int level,ref FormInfo1 form);
  137.  
  138. [DllImport("winspool.Drv", EntryPoint = "DeleteForm", SetLastError = true,CharSet = CharSet.Unicode, ExactSpelling = false, CallingConvention = CallingConvention.StdCall),
  139. SuppressUnmanagedCodeSecurityAttribute()]
  140. internal static extern bool DeleteForm(IntPtr phPrinter,[MarshalAs(UnmanagedType.LPTStr)] string pName);
  141.  
  142. [DllImport("kernel32.dll", EntryPoint = "GetLastError", SetLastError = false,ExactSpelling = true, CallingConvention = CallingConvention.StdCall),SuppressUnmanagedCodeSecurityAttribute()]
  143. internal static extern Int32 GetLastError();
  144.  
  145. [DllImport("GDI32.dll", EntryPoint = "CreateDC", SetLastError = true,CharSet = CharSet.Unicode, ExactSpelling = false,CallingConvention = CallingConvention.StdCall),SuppressUnmanagedCodeSecurityAttribute()]
  146. internal static extern IntPtr CreateDC([MarshalAs(UnmanagedType.LPTStr)] string pDrive,[MarshalAs(UnmanagedType.LPTStr)] string pName,[MarshalAs(UnmanagedType.LPTStr)] string pOutput,ref structDevMode pDevMode);
  147.  
  148. [DllImport("GDI32.dll", EntryPoint = "ResetDC", SetLastError = true,
  149. CharSet = CharSet.Unicode, ExactSpelling = false,CallingConvention = CallingConvention.StdCall),SuppressUnmanagedCodeSecurityAttribute()]
  150. internal static extern IntPtr ResetDC(IntPtr hDC,ref structDevMode pDevMode);
  151.  
  152. [DllImport("GDI32.dll", EntryPoint = "DeleteDC", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = false,
  153. CallingConvention = CallingConvention.StdCall),SuppressUnmanagedCodeSecurityAttribute()]
  154. internal static extern bool DeleteDC(IntPtr hDC);
  155.  
  156. [DllImport("winspool.Drv", EntryPoint = "SetPrinterA", SetLastError = true,
  157. CharSet = CharSet.Auto, ExactSpelling = true,CallingConvention = CallingConvention.StdCall), SuppressUnmanagedCodeSecurityAttribute()]
  158. internal static extern bool SetPrinter(IntPtr hPrinter,[MarshalAs(UnmanagedType.I4)] int level,IntPtr pPrinter,[MarshalAs(UnmanagedType.I4)] int command);
  159.  
  160. [DllImport("winspool.Drv", EntryPoint = "DocumentPropertiesA", SetLastError = true,ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
  161. internal static extern int DocumentProperties(IntPtr hwnd,IntPtr hPrinter,[MarshalAs(UnmanagedType.LPStr)] string pDeviceName,IntPtr pDevModeOutput,IntPtr pDevModeInput,int fMode);
  162.  
  163. [DllImport("winspool.Drv", EntryPoint = "GetPrinterA", SetLastError = true,ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
  164. internal static extern bool GetPrinter(IntPtr hPrinter,int dwLevel,IntPtr pPrinter,int dwBuf,out int dwNeeded);
  165.  
  166. [Flags]
  167. internal enum SendMessageTimeoutFlags : uint
  168. {
  169. SMTO_NORMAL = 0x0000,
  170. SMTO_BLOCK = 0x0001,
  171. SMTO_ABORTIFHUNG = 0x0002,
  172. SMTO_NOTIMEOUTIFNOTHUNG = 0x0008
  173. }
  174. const int WM_SETTINGCHANGE = 0x001A;
  175. const int HWND_BROADCAST = 0xffff;
  176.  
  177. [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
  178. internal static extern IntPtr SendMessageTimeout(IntPtr windowHandle,uint Msg,IntPtr wParam,IntPtr lParam,SendMessageTimeoutFlags flags,uint timeout,out IntPtr result);
  179.  
  180. //EnumPrinters用到的函数和结构体
  181. [DllImport("winspool.drv", CharSet = CharSet.Auto, SetLastError = true)]
  182. private static extern bool EnumPrinters(PrinterEnumFlags Flags, string Name, uint Level,IntPtr pPrinterEnum, uint cbBuf,ref uint pcbNeeded, ref uint pcReturned);
  183.  
  184. [StructLayout(LayoutKind.Sequential)]
  185. internal struct PRINTER_INFO_2
  186. {
  187. public string pServerName;
  188. public string pPrinterName;
  189. public string pShareName;
  190. public string pPortName;
  191. public string pDriverName;
  192. public string pComment;
  193. public string pLocation;
  194. public IntPtr pDevMode;
  195. public string pSepFile;
  196. public string pPrintProcessor;
  197. public string pDatatype;
  198. public string pParameters;
  199. public IntPtr pSecurityDescriptor;
  200. public uint Attributes;
  201. public uint Priority;
  202. public uint DefaultPriority;
  203. public uint StartTime;
  204. public uint UntilTime;
  205. public uint Status;
  206. public uint cJobs;
  207. public uint AveragePPM;
  208. }
  209.  
  210. [FlagsAttribute]
  211. internal enum PrinterEnumFlags
  212. {
  213. PRINTER_ENUM_DEFAULT = 0x00000001,
  214. PRINTER_ENUM_LOCAL = 0x00000002,
  215. PRINTER_ENUM_CONNECTIONS = 0x00000004,
  216. PRINTER_ENUM_FAVORITE = 0x00000004,
  217. PRINTER_ENUM_NAME = 0x00000008,
  218. PRINTER_ENUM_REMOTE = 0x00000010,
  219. PRINTER_ENUM_SHARED = 0x00000020,
  220. PRINTER_ENUM_NETWORK = 0x00000040,
  221. PRINTER_ENUM_EXPAND = 0x00004000,
  222. PRINTER_ENUM_CONTAINER = 0x00008000,
  223. PRINTER_ENUM_ICONMASK = 0x00ff0000,
  224. PRINTER_ENUM_ICON1 = 0x00010000,
  225. PRINTER_ENUM_ICON2 = 0x00020000,
  226. PRINTER_ENUM_ICON3 = 0x00040000,
  227. PRINTER_ENUM_ICON4 = 0x00080000,
  228. PRINTER_ENUM_ICON5 = 0x00100000,
  229. PRINTER_ENUM_ICON6 = 0x00200000,
  230. PRINTER_ENUM_ICON7 = 0x00400000,
  231. PRINTER_ENUM_ICON8 = 0x00800000,
  232. PRINTER_ENUM_HIDE = 0x01000000
  233. }
  234.  
  235. //打印机状态
  236. [FlagsAttribute]
  237. internal enum PrinterStatus
  238. {
  239. PRINTER_STATUS_BUSY = 0x00000200,
  240. PRINTER_STATUS_DOOR_OPEN = 0x00400000,
  241. PRINTER_STATUS_ERROR = 0x00000002,
  242. PRINTER_STATUS_INITIALIZING = 0x00008000,
  243. PRINTER_STATUS_IO_ACTIVE = 0x00000100,
  244. PRINTER_STATUS_MANUAL_FEED = 0x00000020,
  245. PRINTER_STATUS_NO_TONER = 0x00040000,
  246. PRINTER_STATUS_NOT_AVAILABLE = 0x00001000,
  247. PRINTER_STATUS_OFFLINE = 0x00000080,
  248. PRINTER_STATUS_OUT_OF_MEMORY = 0x00200000,
  249. PRINTER_STATUS_OUTPUT_BIN_FULL = 0x00000800,
  250. PRINTER_STATUS_PAGE_PUNT = 0x00080000,
  251. PRINTER_STATUS_PAPER_JAM = 0x00000008,
  252. PRINTER_STATUS_PAPER_OUT = 0x00000010,
  253. PRINTER_STATUS_PAPER_PROBLEM = 0x00000040,
  254. PRINTER_STATUS_PAUSED = 0x00000001,
  255. PRINTER_STATUS_PENDING_DELETION = 0x00000004,
  256. PRINTER_STATUS_PRINTING = 0x00000400,
  257. PRINTER_STATUS_PROCESSING = 0x00004000,
  258. PRINTER_STATUS_TONER_LOW = 0x00020000,
  259. PRINTER_STATUS_USER_INTERVENTION = 0x00100000,
  260. PRINTER_STATUS_WAITING = 0x20000000,
  261. PRINTER_STATUS_WARMING_UP = 0x00010000
  262. }
  263.  
  264. //GetDefaultPrinter用到的API函数说明
  265. [DllImport("winspool.drv", CharSet = CharSet.Auto, SetLastError = true)]
  266. internal static extern bool GetDefaultPrinter(StringBuilder pszBuffer, ref int size);
  267.  
  268. //SetDefaultPrinter用到的API函数声明
  269. [DllImport("winspool.drv", CharSet = CharSet.Auto, SetLastError = true)]
  270. internal static extern bool SetDefaultPrinter(string Name);
  271.  
  272. //EnumFormsA用到的函数声明,应该和EnumPrinters类似
  273. [DllImport("winspool.drv", EntryPoint = "EnumForms")]
  274. internal static extern int EnumFormsA(IntPtr hPrinter, int Level, ref byte pForm, int cbBuf, ref int pcbNeeded, ref int pcReturned);
  275.  
  276. #endregion API声明
  277. internal static int GetPrinterStatusInt(string PrinterName)
  278. {
  279. int intRet = 0;
  280. IntPtr hPrinter;
  281. structPrinterDefaults defaults = new structPrinterDefaults();
  282. if (OpenPrinter(PrinterName, out hPrinter, ref defaults))
  283. {
  284. int cbNeeded = 0;
  285. bool bolRet = GetPrinter(hPrinter, 2, IntPtr.Zero, 0, out cbNeeded);
  286. if (cbNeeded > 0)
  287. {
  288. IntPtr pAddr = Marshal.AllocHGlobal((int)cbNeeded);
  289. bolRet = GetPrinter(hPrinter, 2, pAddr, cbNeeded, out cbNeeded);
  290. if (bolRet)
  291. {
  292. PRINTER_INFO_2 Info2 = new PRINTER_INFO_2();
  293.  
  294. Info2 = (PRINTER_INFO_2)Marshal.PtrToStructure(pAddr, typeof(PRINTER_INFO_2));
  295.  
  296. intRet = System.Convert.ToInt32(Info2.Status);
  297. }
  298. Marshal.FreeHGlobal(pAddr);
  299. }
  300. ClosePrinter(hPrinter);
  301. }
  302. return intRet;
  303. }
  304. internal static PRINTER_INFO_2[] EnumPrintersByFlag(PrinterEnumFlags Flags)
  305. {
  306. uint cbNeeded = 0;
  307. uint cReturned = 0;
  308. bool ret = EnumPrinters(PrinterEnumFlags.PRINTER_ENUM_LOCAL, null, 2, IntPtr.Zero, 0, ref cbNeeded, ref cReturned);
  309. IntPtr pAddr = Marshal.AllocHGlobal((int)cbNeeded);
  310. ret = EnumPrinters(PrinterEnumFlags.PRINTER_ENUM_LOCAL, null, 2, pAddr, cbNeeded, ref cbNeeded, ref cReturned);
  311. if (ret)
  312. {
  313. PRINTER_INFO_2[] Info2 = new PRINTER_INFO_2[cReturned];
  314. int offset = pAddr.ToInt32();
  315. for (int i = 0; i < cReturned; i++)
  316. {
  317. Info2[i].pServerName = Marshal.PtrToStringAuto(Marshal.ReadIntPtr(new IntPtr(offset)));
  318. offset += 4;
  319. Info2[i].pPrinterName = Marshal.PtrToStringAuto(Marshal.ReadIntPtr(new IntPtr(offset)));
  320. offset += 4;
  321. Info2[i].pShareName = Marshal.PtrToStringAuto(Marshal.ReadIntPtr(new IntPtr(offset)));
  322. offset += 4;
  323. Info2[i].pPortName = Marshal.PtrToStringAuto(Marshal.ReadIntPtr(new IntPtr(offset)));
  324. offset += 4;
  325. Info2[i].pDriverName = Marshal.PtrToStringAuto(Marshal.ReadIntPtr(new IntPtr(offset)));
  326. offset += 4;
  327. Info2[i].pComment = Marshal.PtrToStringAuto(Marshal.ReadIntPtr(new IntPtr(offset)));
  328. offset += 4;
  329. Info2[i].pLocation = Marshal.PtrToStringAuto(Marshal.ReadIntPtr(new IntPtr(offset)));
  330. offset += 4;
  331. Info2[i].pDevMode = Marshal.ReadIntPtr(new IntPtr(offset));
  332. offset += 4;
  333. Info2[i].pSepFile = Marshal.PtrToStringAuto(Marshal.ReadIntPtr(new IntPtr(offset)));
  334. offset += 4;
  335. Info2[i].pPrintProcessor = Marshal.PtrToStringAuto(Marshal.ReadIntPtr(new IntPtr(offset)));
  336. offset += 4;
  337. Info2[i].pDatatype = Marshal.PtrToStringAuto(Marshal.ReadIntPtr(new IntPtr(offset)));
  338. offset += 4;
  339. Info2[i].pParameters = Marshal.PtrToStringAuto(Marshal.ReadIntPtr(new IntPtr(offset)));
  340. offset += 4;
  341. Info2[i].pSecurityDescriptor = Marshal.ReadIntPtr(new IntPtr(offset));
  342. offset += 4;
  343. Info2[i].Attributes = (uint)Marshal.ReadIntPtr(new IntPtr(offset));
  344. offset += 4;
  345. Info2[i].Priority = (uint)Marshal.ReadInt32(new IntPtr(offset));
  346. offset += 4;
  347. Info2[i].DefaultPriority = (uint)Marshal.ReadInt32(new IntPtr(offset));
  348. offset += 4;
  349. Info2[i].StartTime = (uint)Marshal.ReadInt32(new IntPtr(offset));
  350. offset += 4;
  351. Info2[i].UntilTime = (uint)Marshal.ReadInt32(new IntPtr(offset));
  352. offset += 4;
  353. Info2[i].Status = (uint)Marshal.ReadInt32(new IntPtr(offset));
  354. offset += 4;
  355. Info2[i].cJobs = (uint)Marshal.ReadInt32(new IntPtr(offset));
  356. offset += 4;
  357. Info2[i].AveragePPM = (uint)Marshal.ReadInt32(new IntPtr(offset));
  358. offset += 4;
  359. }
  360. Marshal.FreeHGlobal(pAddr);
  361. return Info2;
  362. }
  363. else
  364. {
  365. return new PRINTER_INFO_2[0];
  366. }
  367. }
  368. #region 获取当前指定打印机的状态
  369. /// </summary>
  370. /// 获取当前指定打印机的状态
  371. /// </summary>
  372. /// <param name="PrinterName">打印机名称</param>
  373. /// <returns>打印机状态描述</returns>
  374.  
  375. public static string GetPrinterStatus(string PrinterName)
  376. {
  377. int intValue = GetPrinterStatusInt(PrinterName);
  378. string strRet = string.Empty;
  379. switch (intValue)
  380. {
  381. case 0:
  382. strRet = "准备就绪(Ready)";
  383. break;
  384. case 0x00000200:
  385. strRet = "忙(Busy)";
  386. break;
  387. case 0x00400000:
  388. strRet = "门被打开(Printer Door Open)";
  389. break;
  390. case 0x00000002:
  391. strRet = "错误(Printer Error)";
  392. break;
  393. case 0x0008000:
  394. strRet = "正在初始化(Initializing)";
  395. break;
  396. case 0x00000100:
  397. strRet = "正在输入或输出(I/O Active)";
  398. break;
  399. case 0x00000020:
  400. strRet = "手工送纸(Manual Feed)";
  401. break;
  402. case 0x00040000:
  403. strRet = "无墨粉(No Toner)";
  404. break;
  405. case 0x00001000:
  406. strRet = "不可用(Not Available)";
  407. break;
  408. case 0x00000080:
  409. strRet = "脱机(Off Line)";
  410. break;
  411. case 0x00200000:
  412. strRet = "内存溢出(Out of Memory)";
  413. break;
  414. case 0x00000800:
  415. strRet = "输出口已满(Output Bin Full)";
  416. break;
  417. case 0x00080000:
  418. strRet = "当前页无法打印(Page Punt)";
  419. break;
  420. case 0x00000008:
  421. strRet = "塞纸(Paper Jam)";
  422. break;
  423. case 0x00000010:
  424. strRet = "打印纸用完(Paper Out)";
  425. break;
  426. case 0x00000040:
  427. strRet = "纸张问题(Page Problem)";
  428. break;
  429. case 0x00000001:
  430. strRet = "暂停(Paused)";
  431. break;
  432. case 0x00000004:
  433. strRet = "正在删除(Pending Deletion)";
  434. break;
  435. case 0x00000400:
  436. strRet = "正在打印(Printing)";
  437. break;
  438. case 0x00004000:
  439. strRet = "正在处理(Processing)";
  440. break;
  441. case 0x00020000:
  442. strRet = "墨粉不足(Toner Low)";
  443. break;
  444. case 0x00100000:
  445. strRet = "需要用户干预(User Intervention)";
  446. break;
  447. case 0x20000000:
  448. strRet = "等待(Waiting)";
  449. break;
  450. case 0x00010000:
  451. strRet = "正在准备(Warming Up)";
  452. break;
  453. default:
  454. strRet = "未知状态(Unknown Status)";
  455. break;
  456. }
  457. return strRet;
  458. }
  459. #endregion 获取当前指定打印机的状态
  460. #region 删除已经存在的自定义纸张
  461. /**/
  462. /// <summary>
  463. /// 删除已经存在的自定义纸张
  464. /// </summary>
  465. /// <param name="PrinterName">打印机名称</param>
  466. /// <param name="PaperName">纸张名称</param>
  467. public static void DeleteCustomPaperSize(string PrinterName, string PaperName)
  468. {
  469. const int PRINTER_ACCESS_USE = 0x00000008;
  470. const int PRINTER_ACCESS_ADMINISTER = 0x00000004;
  471.  
  472. structPrinterDefaults defaults = new structPrinterDefaults();
  473. defaults.pDatatype = null;
  474. defaults.pDevMode = IntPtr.Zero;
  475. defaults.DesiredAccess = PRINTER_ACCESS_ADMINISTER | PRINTER_ACCESS_USE;
  476.  
  477. IntPtr hPrinter = IntPtr.Zero;
  478.  
  479. //打开打印机
  480. if (OpenPrinter(PrinterName, out hPrinter, ref defaults))
  481. {
  482. try
  483. {
  484. DeleteForm(hPrinter, PaperName);
  485. ClosePrinter(hPrinter);
  486. }
  487. catch
  488. {
  489.  
  490. }
  491. }
  492. }
  493. #endregion 删除已经存在的自定义纸张
  494. #region 指定的打印机设置以mm为单位的自定义纸张(Form)
  495. /**/
  496. /// <summary>
  497. /// 指定的打印机设置以mm为单位的自定义纸张(Form)
  498. /// </summary>
  499. /// <param name="PrinterName">打印机名称</param>
  500. /// <param name="PaperName">Form名称</param>
  501. /// <param name="WidthInMm">以mm为单位的宽度</param>
  502. /// <param name="HeightInMm">以mm为单位的高度</param>
  503. public static void AddCustomPaperSize(string PrinterName, string PaperName, float WidthInMm, float HeightInMm)
  504. {
  505. if (PlatformID.Win32NT == Environment.OSVersion.Platform)
  506. {
  507. const int PRINTER_ACCESS_USE = 0x00000008;
  508. const int PRINTER_ACCESS_ADMINISTER = 0x00000004;
  509. structPrinterDefaults defaults = new structPrinterDefaults();
  510. defaults.pDatatype = null;
  511. defaults.pDevMode = IntPtr.Zero;
  512. defaults.DesiredAccess = PRINTER_ACCESS_ADMINISTER | PRINTER_ACCESS_USE;
  513. IntPtr hPrinter = IntPtr.Zero;
  514. //打开打印机
  515. if (OpenPrinter(PrinterName, out hPrinter, ref defaults))
  516. {
  517. try
  518. {
  519. //如果Form存在删除之
  520. DeleteForm(hPrinter, PaperName);
  521. //创建并初始化FORM_INFO_1
  522. FormInfo1 formInfo = new FormInfo1();
  523. formInfo.Flags = 0;
  524. formInfo.pName = PaperName;
  525. formInfo.Size.width = (int)(WidthInMm * 1000.0);
  526. formInfo.Size.height = (int)(HeightInMm * 1000.0);
  527. formInfo.ImageableArea.left = 0;
  528. formInfo.ImageableArea.right = formInfo.Size.width;
  529. formInfo.ImageableArea.top = 0;
  530. formInfo.ImageableArea.bottom = formInfo.Size.height;
  531. if (!AddForm(hPrinter, 1, ref formInfo))
  532. {
  533. StringBuilder strBuilder = new StringBuilder();
  534. strBuilder.AppendFormat("向打印机 {1} 添加自定义纸张 {0} 失败!错误代号:{2}",
  535. PaperName, PrinterName, GetLastError());
  536. throw new ApplicationException(strBuilder.ToString());
  537. }
  538.  
  539. //初始化
  540. const int DM_OUT_BUFFER = 2;
  541. const int DM_IN_BUFFER = 8;
  542. structDevMode devMode = new structDevMode();
  543. IntPtr hPrinterInfo, hDummy;
  544. PRINTER_INFO_9 printerInfo;
  545. printerInfo.pDevMode = IntPtr.Zero;
  546. int iPrinterInfoSize, iDummyInt;
  547.  
  548. int iDevModeSize = DocumentProperties(IntPtr.Zero, hPrinter, PrinterName, IntPtr.Zero, IntPtr.Zero, 0);
  549.  
  550. if (iDevModeSize < 0)
  551. throw new ApplicationException("无法取得DEVMODE结构的大小!");
  552.  
  553. //分配缓冲
  554. IntPtr hDevMode = Marshal.AllocCoTaskMem(iDevModeSize + 100);
  555.  
  556. //获取DEV_MODE指针
  557. int iRet = DocumentProperties(IntPtr.Zero, hPrinter, PrinterName, hDevMode, IntPtr.Zero, DM_OUT_BUFFER);
  558.  
  559. if (iRet < 0)
  560. throw new ApplicationException("无法获得DEVMODE结构!");
  561.  
  562. //填充DEV_MODE
  563. devMode = (structDevMode)Marshal.PtrToStructure(hDevMode, devMode.GetType());
  564.  
  565. devMode.dmFields = 0x10000;
  566.  
  567. //FORM名称
  568. devMode.dmFormName = PaperName;
  569.  
  570. Marshal.StructureToPtr(devMode, hDevMode, true);
  571.  
  572. iRet = DocumentProperties(IntPtr.Zero, hPrinter, PrinterName,
  573. printerInfo.pDevMode, printerInfo.pDevMode, DM_IN_BUFFER | DM_OUT_BUFFER);
  574.  
  575. if (iRet < 0)
  576. throw new ApplicationException("无法为打印机设定打印方向!");
  577.  
  578. GetPrinter(hPrinter, 9, IntPtr.Zero, 0, out iPrinterInfoSize);
  579. if (iPrinterInfoSize == 0)
  580. throw new ApplicationException("调用GetPrinter方法失败!");
  581.  
  582. hPrinterInfo = Marshal.AllocCoTaskMem(iPrinterInfoSize + 100);
  583.  
  584. bool bSuccess = GetPrinter(hPrinter, 9, hPrinterInfo, iPrinterInfoSize, out iDummyInt);
  585.  
  586. if (!bSuccess)
  587. throw new ApplicationException("调用GetPrinter方法失败!");
  588.  
  589. printerInfo = (PRINTER_INFO_9)Marshal.PtrToStructure(hPrinterInfo, printerInfo.GetType());
  590. printerInfo.pDevMode = hDevMode;
  591.  
  592. Marshal.StructureToPtr(printerInfo, hPrinterInfo, true);
  593.  
  594. bSuccess = SetPrinter(hPrinter, 9, hPrinterInfo, 0);
  595.  
  596. if (!bSuccess)
  597. throw new Win32Exception(Marshal.GetLastWin32Error(), "调用SetPrinter方法失败,无法进行打印机设置!");
  598.  
  599. SendMessageTimeout(
  600. new IntPtr(HWND_BROADCAST),
  601. WM_SETTINGCHANGE,
  602. IntPtr.Zero,
  603. IntPtr.Zero,
  604. PrinterHelper.SendMessageTimeoutFlags.SMTO_NORMAL,
  605. 1000,
  606. out hDummy);
  607. }
  608. finally
  609. {
  610. ClosePrinter(hPrinter);
  611. }
  612. }
  613. else
  614. {
  615. StringBuilder strBuilder = new StringBuilder();
  616. strBuilder.AppendFormat("无法打开打印机{0}, 错误代号: {1}",
  617. PrinterName, GetLastError());
  618. throw new ApplicationException(strBuilder.ToString());
  619. }
  620. }
  621. else
  622. {
  623. structDevMode pDevMode = new structDevMode();
  624. IntPtr hDC = CreateDC(null, PrinterName, null, ref pDevMode);
  625. if (hDC != IntPtr.Zero)
  626. {
  627. const long DM_PAPERSIZE = 0x00000002L;
  628. const long DM_PAPERLENGTH = 0x00000004L;
  629. const long DM_PAPERWIDTH = 0x00000008L;
  630. pDevMode.dmFields = (int)(DM_PAPERSIZE | DM_PAPERWIDTH | DM_PAPERLENGTH);
  631. pDevMode.dmPaperSize = 256;
  632. pDevMode.dmPaperWidth = (short)(WidthInMm * 1000.0);
  633. pDevMode.dmPaperLength = (short)(HeightInMm * 1000.0);
  634. ResetDC(hDC, ref pDevMode);
  635. DeleteDC(hDC);
  636. }
  637. }
  638. }
  639. #endregion 指定的打印机设置以mm为单位的自定义纸张(Form)
  640. #region 获取本地打印机列表
  641. /**/
  642. /// <summary>
  643. /// 获取本地打印机列表
  644. /// 可以通过制定参数获取网络打印机
  645. /// </summary>
  646. /// <returns>打印机列表</returns>
  647. public static System.Collections.ArrayList GetPrinterList()
  648. {
  649. System.Collections.ArrayList alRet = new System.Collections.ArrayList();
  650. PRINTER_INFO_2[] Info2 = EnumPrintersByFlag(PrinterEnumFlags.PRINTER_ENUM_LOCAL);
  651. for (int i = 0; i < Info2.Length; i++)
  652. {
  653. alRet.Add(Info2[i].pPrinterName);
  654. }
  655. return alRet;
  656. }
  657. #endregion 获取本地打印机列表
  658. #region 获取本机的默认打印机名称
  659. /**/
  660. /// <summary>
  661. /// 获取本机的默认打印机名称
  662. /// </summary>
  663. /// <returns>默认打印机名称</returns>
  664. public static string GetDeaultPrinterName()
  665. {
  666. StringBuilder dp = new StringBuilder(256);
  667. int size = dp.Capacity;
  668. if (GetDefaultPrinter(dp, ref size))
  669. {
  670. return dp.ToString();
  671. }
  672. else
  673. {
  674. return string.Empty;
  675. }
  676. }
  677. #endregion 获取本机的默认打印机名称
  678. #region 设置默认打印机
  679. /**/
  680. /// <summary>
  681. /// 设置默认打印机
  682. /// </summary>
  683. /// <param name="PrinterName">可用的打印机名称</param>
  684. public static void SetPrinterToDefault(string PrinterName)
  685. {
  686. SetDefaultPrinter(PrinterName);
  687. }
  688. #endregion 设置默认打印机
  689. #region 判断打印机是否在系统可用的打印机列表中
  690. /**/
  691. ///// <summary>
  692. ///// 判断打印机是否在系统可用的打印机列表中
  693. ///// </summary>
  694. ///// <param name="PrinterName">打印机名称</param>
  695. ///// <returns>是:在;否:不在</returns>
  696. public static bool PrinterInList(string PrinterName)
  697. {
  698. bool bolRet = false;
  699.  
  700. System.Collections.ArrayList alPrinters = GetPrinterList();
  701.  
  702. for (int i = 0; i < alPrinters.Count; i++)
  703. {
  704. if (PrinterName == alPrinters[i].ToString())
  705. {
  706. bolRet = true;
  707. break;
  708. }
  709. }
  710.  
  711. alPrinters.Clear();
  712. alPrinters = null;
  713.  
  714. return bolRet;
  715. }
  716. #endregion 判断打印机是否在系统可用的打印机列表中
  717. #region 判断表单是否在指定的打印机所支持的纸张列表中
  718. /**/
  719. ///// <summary>
  720. ///// 判断表单是否在指定的打印机所支持的纸张列表中,表单就是我们平常所说的纸张
  721. ///// </summary>
  722. ///// <param name="PrinterName">打印机名称</param>
  723. ///// <param name="PaperName">纸张名称</param>
  724. ///// <returns>是:在;否:不在</returns>
  725. public static bool FormInPrinter(string PrinterName, string PaperName)
  726. {
  727. bool bolRet = false;
  728.  
  729. System.Drawing.Printing.PrintDocument pd = new System.Drawing.Printing.PrintDocument();
  730.  
  731. pd.PrinterSettings.PrinterName = PrinterName;
  732.  
  733. foreach (System.Drawing.Printing.PaperSize ps in pd.PrinterSettings.PaperSizes)
  734. {
  735. if (ps.PaperName == PaperName)
  736. {
  737. bolRet = true;
  738. break;
  739. }
  740. }
  741.  
  742. pd.Dispose();
  743.  
  744. return bolRet;
  745. }
  746. #endregion 判断表单是否在指定的打印机所支持的纸张列表中
  747. #region 判断指定纸张的宽度和高度和与打印内容指定的宽度和高度是否匹配
  748. /**/
  749. /// <summary>
  750. /// 判断指定纸张的宽度和高度和与打印内容指定的宽度和高度是否匹配
  751. /// </summary>
  752. /// <param name="PrinterName">打印机名称</param>
  753. /// <param name="FormName">表单名称</param>
  754. /// <param name="Width">宽度</param>
  755. /// <param name="Height">高度</param>
  756. /// <returns></returns>
  757. public static bool FormSameSize(string PrinterName, string FormName, decimal Width, decimal Height)
  758. {
  759. bool bolRet = false;
  760.  
  761. System.Drawing.Printing.PrintDocument pd = new System.Drawing.Printing.PrintDocument();
  762.  
  763. pd.PrinterSettings.PrinterName = PrinterName;
  764.  
  765. foreach (System.Drawing.Printing.PaperSize ps in pd.PrinterSettings.PaperSizes)
  766. {
  767. if (ps.PaperName == FormName)
  768. {
  769. decimal decWidth = FromInchToCM(System.Convert.ToDecimal(ps.Width));
  770. decimal decHeight = FromInchToCM(System.Convert.ToDecimal(ps.Height));
  771. //只要整数位相同即认为是同一纸张,毕竟inch到cm的转换并不能整除
  772. if (Math.Round(decWidth, 0) == Math.Round(Width, 0) && Math.Round(decHeight, 0) == Math.Round(Height, 0))
  773. bolRet = true;
  774. break;
  775. }
  776. }
  777.  
  778. pd.Dispose();
  779.  
  780. return bolRet;
  781. }
  782. #endregion 判断指定纸张的宽度和高度和与打印内容指定的宽度和高度是否匹配
  783. #region 英寸到厘米的转换
  784. /**/
  785. /// <summary>
  786. /// 英寸到厘米的转换
  787. /// /* = = = = = = = = = = = = = = = = *\
  788. /// | 换算一下计量单位,将其换算成厘米 |
  789. /// | 厘米 像素 英寸 |
  790. /// | 1 38 0.395 |
  791. /// | 0.026 1 0.01 |
  792. /// | 2.54 96 1 |
  793. /// \* = = = = = = = = = = = = = = = = */
  794. /// </summary>
  795. /// <param name="inch">英寸数</param>
  796. /// <returns>厘米数,两位小数</returns>
  797. ///
  798. public static decimal FromInchToCM(decimal inch)
  799. {
  800. return Math.Round((System.Convert.ToDecimal((inch / 100)) * System.Convert.ToDecimal(2.5400)), 2);
  801. }
  802. #endregion 英寸到厘米的转换
  803. }
  804. }

  

C#调用windows api 实现打印机控制的更多相关文章

  1. C#调用windows API的一些方法

    使用C#调用windows API(从其它地方总结来的,以备查询) C#调用windows API也可以叫做C#如何直接调用非托管代码,通常有2种方法: 1.  直接调用从 DLL 导出的函数. 2. ...

  2. C#调用Windows API函数截图

    界面如下: 下面放了一个PictureBox 首先是声明函数: //这里是调用 Windows API函数来进行截图 //首先导入库文件 [System.Runtime.InteropServices ...

  3. C#中调用Windows API的要点 .

    介绍 API(Application Programming Interface),我想大家不会陌生,它是我们Windows编程的常客,虽然基于.Net平台的C#有了强大的类库,但是,我们还是不能否认 ...

  4. c#让窗体永在最前 调用windows api 将窗体设为topmost

    有时候应用程序需要将一个窗体始终位于屏幕的最前面,即使切换到其它窗体也能看到该窗体,这样的窗体就叫做TopMost窗体. 用C#制作TopMost窗体之前,首先要了解如何声明SetWindowPos函 ...

  5. VBS调用Windows API函数

    Demon's Blog 忘记了,喜欢一个人的感觉 Demon's Blog  »  程序设计  »  VBS调用Windows API函数 « 用VBS修改Windows用户密码 在VB中创建和使用 ...

  6. [windows菜鸟]C#中调用Windows API的技术要点说明

    在.Net Framework SDK文档中,关于调用Windows API的指示比较零散,并且其中稍全面一点的是针对Visual Basic .net讲述的.本文将C#中调用API的要点汇集如下,希 ...

  7. C#调用Windows API(示例:显示任务管理器里的程序名称)

    作为初学者来说,在C#中使用API确是一件令人头疼的问题. 在使用API之前你必须知道如何在C#中使用结构.类型转换.安全/不安全代码,可控/不可控代码等许多知识. 在.Net Framework S ...

  8. 【转】用C#调用Windows API向指定窗口发送

    一.调用Windows API. C#下调用Windows API方法如下: 1.引入命名空间:using System.Runtime.InteropServices; 2.引用需要使用的方法,格式 ...

  9. c# 判断窗体是否永在最前(TopMost),调用windows API

    许多程序都可以把自身的窗体设为最前显示状态,这个可以参考博客c#让窗体永在最前 调用windows api 将窗体设为topmost.那么如何判断桌面上的一个窗体是否为最前显示状态呢,不光是自己的程序 ...

随机推荐

  1. HTML,CSS学习笔记

    <p>元素,代表是一个段落,单独另起一行</p> <h1>的意思就是主标题</h1> <h1><h2><h3>... ...

  2. jsp获取parameter乱码

    String StaffName = new String(request.getParameter("StaffName").getBytes("iso-8859-1& ...

  3. drupal 开发简单站点流程

    友情推广:Uminicmf 一个基于thinkphp开发的OA框架.http://blog.csdn.net/youmypig/article/details/51727713 drupal 简单站点 ...

  4. Android OpenGL ES(八)----纹理编程框架

    1.把纹理载入进OpenGL中 我们的第一个任务就是把一个图像文件的数据载入到一个OpenGL的纹理中. 作为開始.让我们又一次舍弃第二篇的框架.又一次创建一个程序,新建一个util工具包,在该包下创 ...

  5. Struts框架的国际化

    本文将通过一个详细的实例来展示Struts框架的国际化,使用的版本号是struts1.1. 案例:在一个页面上有一个下拉框,下拉框中有3个国家的语言选项,各自是"中文简体".&qu ...

  6. centos 6.5 安装mongodb2.6

    前言: 系统版本号:Centos-6.5-x86_64 *** Centos编译安装mongodb 2.6 系统最好是64位的,才干更好发挥mongodb的性能 1.准备,下载源文件(二进制编译版) ...

  7. 让intellij idea 14 支持ES6语法

    用eclipse做前端开发,用到了webpack,结果各种依赖导致软件卡的一比,简直不能动!虽然在同事的帮忙下,修改了一下配置,但仍然卡的没脾气.改用intellij idea 14解决了卡的问题,但 ...

  8. 队列queue(2):链表实现队列

    基本概念 队列是只允许在一端进行插入操作,另一端进行删除操作的线性表. 我们规定,允许删除的叫做队首"head",允许插入的叫做队尾"tail". 基本操作 我 ...

  9. APP Store开发指南

    App Store 审核指南 iOS App打包上架超详细流程 ---2017.03 苹果对开发者提交的应用的审核之严格是出了名的,了解苹果的审核标准对于开发者防止应用被拒有着十分重要的意义.几天前苹 ...

  10. Noip2016换教室(期望+DP)

    Description 题目链接:Luogu Solution 这题结合了DP和概率与期望,其实只要稍微知道什么是期望就可以了, 状态的构造很关键,\(F[i][j][0/1]\)表示已经到第\(i\ ...