最近需要按顺序打印word、excel、图片,其中有的需要单面打印,有的双面。网上查了很多方法。主要集中在几个方式解决

1、word的print和excel的printout里设置单双面

2、printdocument里的printsettings的duplex设置单双面

试过之后效果都不好,昨天终于在MSDN上找到个直接设置打印机单双面的代码,非常管用。

using System.Runtime.InteropServices;
using System;namespace MyDuplexSettings
{
class DuplexSettings
{
#region Win32 API Declaration[DllImport("kernel32.dll", EntryPoint = "GetLastError", SetLastError = false, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern Int32 GetLastError();[DllImport("winspool.Drv", EntryPoint = "ClosePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool ClosePrinter(IntPtr hPrinter);[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 pDeviceNameg, 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, Int32 dwLevel, IntPtr pPrinter, Int32 dwBuf, ref Int32 dwNeeded);[DllImport("winspool.drv", CharSet = CharSet.Auto, SetLastError = true)]
static extern int OpenPrinter(string pPrinterName, out IntPtr phPrinter, ref PRINTER_DEFAULTS pDefault);[DllImport("winspool.Drv", EntryPoint = "SetPrinterA", ExactSpelling = true, SetLastError = true)]
public static extern bool SetPrinter(IntPtr hPrinter, int Level, IntPtr pPrinter, int Command);[StructLayout(LayoutKind.Sequential)]
public struct PRINTER_DEFAULTS
{public IntPtr pDatatype;public IntPtr pDevMode;public int DesiredAccess;
}[StructLayout(LayoutKind.Sequential)]
public struct PRINTER_INFO_9
{public IntPtr pDevMode;// Pointer to SECURITY_DESCRIPTORpublic int pSecurityDescriptor;
}public const short CCDEVICENAME = 32;public const short CCFORMNAME = 32;[StructLayout(LayoutKind.Sequential)]
public struct DEVMODE
{[MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCDEVICENAME)]public string dmDeviceName;public short dmSpecVersion;public short dmDriverVersion;public short dmSize;public short dmDriverExtra;public int dmFields;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 short dmColor;public short dmDuplex;public short dmYResolution;public short dmTTOption;public short dmCollate;[MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCFORMNAME)]public string dmFormName;public short dmUnusedPadding;public short dmBitsPerPel;public int dmPelsWidth;public int dmPelsHeight;public int dmDisplayFlags;public int dmDisplayFrequency;
}public const Int64    DM_DUPLEX = 0x1000L;
public const Int64 DM_ORIENTATION = 0x1L;
public const Int64 DM_SCALE = 0x10L;
public const Int64 DMORIENT_PORTRAIT = 0x1L;
public const Int64 DMORIENT_LANDSCAPE = 0x2L;
public const Int32  DM_MODIFY = 8;
public const Int32 DM_COPY = 2;
public const Int32 DM_IN_BUFFER = 8;
public const Int32 DM_OUT_BUFFER = 2;
public const Int32 PRINTER_ACCESS_ADMINISTER = 0x4;
public const Int32 PRINTER_ACCESS_USE = 0x8;
public const Int32 STANDARD_RIGHTS_REQUIRED = 0xf0000;
public const int PRINTER_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED | PRINTER_ACCESS_ADMINISTER | PRINTER_ACCESS_USE);//added this
public const int CCHDEVICENAME = 32;//added this
public const int CCHFORMNAME = 32;#endregion#region Public Methods/// <summary>
/// Method Name : GetPrinterDuplex
/// Programmatically get the Duplex flag for the specified printer
/// driver's default properties.
/// </summary>
/// <param name="sPrinterName"> The name of the printer to be used. </param>
/// <param name="errorMessage"> this will contain error messsage if any. </param>
/// <returns>
/// nDuplexSetting - One of the following standard settings:
/// 0 = Error
/// 1 = None (Simplex)
/// 2 = Duplex on long edge (book)
/// 3 = Duplex on short edge (legal)
/// </returns>
/// <remarks>
/// </remarks>
public short GetPrinterDuplex(string sPrinterName, out string errorMessage)
{errorMessage = string.Empty;short functionReturnValue = 0;IntPtr hPrinter = default(IntPtr);PRINTER_DEFAULTS pd = default(PRINTER_DEFAULTS);DEVMODE dm = new DEVMODE();int nRet = 0;pd.DesiredAccess = PRINTER_ACCESS_USE;nRet = OpenPrinter(sPrinterName, out hPrinter, ref pd);if ((nRet == 0) | (hPrinter.ToInt32() == 0)) {if (GetLastError() == 5) {errorMessage = "Access denied -- See the article for more info.";} else {errorMessage = "Cannot open the printer specified " + "(make sure the printer name is correct).";}return functionReturnValue;}nRet = DocumentProperties(IntPtr.Zero, hPrinter, sPrinterName, IntPtr.Zero, IntPtr.Zero, 0);if ((nRet < 0)) {errorMessage = "Cannot get the size of the DEVMODE structure.";goto cleanup;}IntPtr iparg = Marshal.AllocCoTaskMem(nRet + 100);nRet = DocumentProperties(IntPtr.Zero, hPrinter, sPrinterName, iparg, IntPtr.Zero, DM_OUT_BUFFER);if ((nRet < 0)) {errorMessage = "Cannot get the DEVMODE structure.";goto cleanup;}dm = (DEVMODE)Marshal.PtrToStructure(iparg, dm.GetType());if (!Convert.ToBoolean(dm.dmFields & DM_DUPLEX)) {errorMessage = "You cannot modify the duplex flag for this printer " + "because it does not support duplex or the driver " + "does not support setting it from the Windows API.";goto cleanup;}functionReturnValue = dm.dmDuplex;cleanup:if ((hPrinter.ToInt32() != 0))ClosePrinter(hPrinter);    return functionReturnValue;
}/// <summary>
/// Method Name : SetPrinterDuplex
/// Programmatically set the Duplex flag for the specified printer driver's default properties.
/// </summary>
/// <param name="sPrinterName"> sPrinterName - The name of the printer to be used. </param>
/// <param name="nDuplexSetting">
/// nDuplexSetting - One of the following standard settings:
/// 1 = None
/// 2 = Duplex on long edge (book)
/// 3 = Duplex on short edge (legal)
/// </param>
///  <param name="errorMessage"> this will contain error messsage if any. </param>
/// <returns>
/// Returns: True on success, False on error.
/// </returns>
/// <remarks>
///
/// </remarks>
public bool SetPrinterDuplex(string sPrinterName, int nDuplexSetting, out string errorMessage)
{errorMessage = string.Empty;bool functionReturnValue = false;IntPtr hPrinter = default(IntPtr);PRINTER_DEFAULTS pd = default(PRINTER_DEFAULTS);PRINTER_INFO_9 pinfo = new PRINTER_INFO_9();DEVMODE dm = new DEVMODE();IntPtr ptrPrinterInfo = default(IntPtr);int nBytesNeeded = 0;int nRet = 0;Int32 nJunk = default(Int32);if ((nDuplexSetting < 1) | (nDuplexSetting > 3)) {errorMessage = "Error: dwDuplexSetting is incorrect.";return functionReturnValue;}pd.DesiredAccess = PRINTER_ACCESS_USE;nRet = OpenPrinter(sPrinterName, out hPrinter, ref pd);if ((nRet == 0) | (hPrinter.ToInt32() == 0)) {if (GetLastError() == 5) {errorMessage = "Access denied -- See the article for more info." ;} else {errorMessage = "Cannot open the printer specified " + "(make sure the printer name is correct).";}return functionReturnValue;}nRet = DocumentProperties(IntPtr.Zero, hPrinter, sPrinterName, IntPtr.Zero, IntPtr.Zero, 0);if ((nRet < 0)) {errorMessage = "Cannot get the size of the DEVMODE structure.";goto cleanup;}IntPtr iparg = Marshal.AllocCoTaskMem(nRet + 100);nRet = DocumentProperties(IntPtr.Zero, hPrinter, sPrinterName, iparg, IntPtr.Zero, DM_OUT_BUFFER);if ((nRet < 0)) {errorMessage = "Cannot get the DEVMODE structure.";goto cleanup;}dm = (DEVMODE)Marshal.PtrToStructure(iparg, dm.GetType());if (!Convert.ToBoolean(dm.dmFields & DM_DUPLEX)) {errorMessage = "You cannot modify the duplex flag for this printer " + "because it does not support duplex or the driver " + "does not support setting it from the Windows API.";goto cleanup;}dm.dmDuplex = (short) nDuplexSetting;Marshal.StructureToPtr(dm, iparg, true);nRet = DocumentProperties(IntPtr.Zero, hPrinter, sPrinterName, pinfo.pDevMode, pinfo.pDevMode, DM_IN_BUFFER | DM_OUT_BUFFER);if ((nRet < 0)) {errorMessage = "Unable to set duplex setting to this printer.";goto cleanup;}GetPrinter(hPrinter, 9, IntPtr.Zero, 0, ref nBytesNeeded);if ((nBytesNeeded == 0)) {errorMessage = "GetPrinter failed.";goto cleanup;}ptrPrinterInfo = Marshal.AllocCoTaskMem(nBytesNeeded + 100);nRet = GetPrinter(hPrinter, 9, ptrPrinterInfo, nBytesNeeded, ref nJunk)?1:0;if ((nRet == 0)) {errorMessage = "Unable to get shared printer settings.";goto cleanup;}pinfo = (PRINTER_INFO_9)Marshal.PtrToStructure(ptrPrinterInfo, pinfo.GetType());pinfo.pDevMode = iparg;pinfo.pSecurityDescriptor = 0;Marshal.StructureToPtr(pinfo, ptrPrinterInfo, true);nRet = SetPrinter(hPrinter, 9, ptrPrinterInfo, 0)?1:0;if ((nRet == 0)) {errorMessage = "Unable to set shared printer settings.";}functionReturnValue = Convert.ToBoolean(nRet);cleanup:if ((hPrinter.ToInt32() != 0))ClosePrinter(hPrinter);return functionReturnValue;
}
#endregion}
}

使用方法,以word为例:

public static void PrintWord(string FileName, PrintDocument pd){//0 check if there are any winword process exist//if is,kill itProcess[] wordProcess = Process.GetProcessesByName("WINWORD");for (int i = 0; i < wordProcess.Length; i++){wordProcess[i].Kill();}object missing = System.Reflection.Missing.Value;object objFileName = FileName;object objPrintName = pd.PrinterSettings.PrinterName;WORD.Application objApp = new WORD.Application();WORD.Document objDoc = null;try{objDoc = FrameWork.WordTool.OpenWord(objApp, FileName);objDoc.Activate();object copies = "1";object pages = "";object range = WORD.WdPrintOutRange.wdPrintAllDocument;object items = WORD.WdPrintOutItem.wdPrintDocumentContent;object pageType = WORD.WdPrintOutPages.wdPrintAllPages;object oTrue = true;object oFalse = false;objApp.Options.PrintOddPagesInAscendingOrder = true;objApp.Options.PrintEvenPagesInAscendingOrder = true;objDoc.PrintOut(ref oTrue, ref oFalse, ref range, ref missing, ref missing, ref missing,ref items, ref copies, ref pages, ref pageType, ref oFalse, ref oTrue,ref missing, ref oFalse, ref missing, ref missing, ref missing, ref missing);}catch (Exception ex){throw ex;}finally{if (objDoc != null){Marshal.ReleaseComObject(objDoc);Marshal.FinalReleaseComObject(objDoc);objDoc = null;}if (objApp != null){objApp.Quit(ref missing, ref missing, ref missing);Marshal.ReleaseComObject(objApp);Marshal.FinalReleaseComObject(objApp);objApp = null;}}}

使用方法,以excel为例,我这有两种表格,把打印页数固定了打印:

public static void PrintExcel(string excelFileName, PrintDocument pd, int iFlag){//0 check if there are any winword process exist//if is,kill itProcess[] wordProcess = Process.GetProcessesByName("EXCEL");for (int i = 0; i < wordProcess.Length; i++){wordProcess[i].Kill();}object Missing = System.Reflection.Missing.Value;object objExcel = null;object objWorkbooks = null;try{objExcel = ExcelTool.OpenExcel(excelFileName);if (iFlag == 1){objWorkbooks = ExcelTool.GetWorkSheets(objExcel);object[] parameters = null;try{parameters = new object[8];parameters[0] = 1;parameters[1] = 4;parameters[2] = 1;parameters[3] = Missing;parameters[4] = pd.PrinterSettings.PrinterName;parameters[5] = Missing;parameters[6] = true;parameters[7] = Missing;objWorkbooks.GetType().InvokeMember("PrintOut", System.Reflection.BindingFlags.InvokeMethod, null, objWorkbooks, parameters);}catch (Exception ex){throw ex;}}else{objWorkbooks = ExcelTool.GetWorkSheets(objExcel);object[] parameters = null;try{parameters = new object[8];parameters[0] = 5;parameters[1] = 5;parameters[2] = 1;parameters[3] = Missing;parameters[4] = pd.PrinterSettings.PrinterName;parameters[5] = Missing;parameters[6] = true;parameters[7] = Missing;objWorkbooks.GetType().InvokeMember("PrintOut", System.Reflection.BindingFlags.InvokeMethod, null, objWorkbooks, parameters);}catch (Exception ex){throw ex;}}}catch (Exception ex){throw ex;}finally{if (objWorkbooks != null){ExcelTool.ReleaseComObj(objWorkbooks);}if (objExcel != null){ExcelTool.ReleaseComObj(objExcel);}System.GC.Collect();}}

最后再说说图片打印A4纸的设置,这里省略其它代码,如果纠结这问题的人一下就看出来问题出哪里了。

如果要适应纸张尺寸的话:

 pd.PrintPage += (_, e) =>{var img = System.Drawing.Image.FromFile(FileName[i]);e.Graphics.DrawImage(img, 20, 20, e.PageSettings.PrintableArea.Width, e.PageSettings.PrintableArea.Height);if (i == FileName.Length - 1){e.HasMorePages = false;}else{e.HasMorePages = true;}i++;};

如果是固定大小的话:

pd.PrintPage += (_, e) =>{var img = System.Drawing.Image.FromFile(FileName[i]);int iWidth = 520;double hFactor = iWidth / (double)img.Width;int iHeight = Convert.ToInt32(img.Height * hFactor);Rectangle Rect = new Rectangle(170, 330, iWidth, iHeight);e.Graphics.DrawImage(img, Rect);if (i == FileName.Length - 1){e.HasMorePages = false;}else{e.HasMorePages = true;}i++;};

我辛苦了几天累的代码,分享给有用之人:)

自己在做独立开发,希望广结英豪,尤其是像我一样脑子短路不用react硬拼anroid、ios原生想干点什么的朋友。

App独立开发群533838427

微信公众号『懒文』-->lanwenapp<--

转载于:https://www.cnblogs.com/matoo/p/3680117.html

C#双面打印解决方法(打印word\excel\图片)相关推荐

  1. win打印显示打印服务器错误,由于打印机的当前设置有问题,windos无法打印_由于打印机设置word无法打印解决方法...

    朋友们在日常办公时可能会遇到需要打印word文档的情况,但是有可能会出现一些错误,导致我们无法正常打印,例如由于打印机的当前设置有问题,windos无法打印的错误提示,那么为什么会出现这种情况呢?其实 ...

  2. 一个简单的解决方法:word文档打不开,错误提示mso.dll模块错误。

    一个简单的解决方法:word文档打不开,错误提示mso.dll模块错误. 参考文章: (1)一个简单的解决方法:word文档打不开,错误提示mso.dll模块错误. (2)https://www.cn ...

  3. Win11打印机无法打印怎么办?Win11打印机无法打印解决方法

    Win11打印机无法打印怎么办?在我们平常的办公中经常会需要的使用打印机打印文件,但如果打印机无法正常打印的话,那么将是一个令人头疼的问题. 还有更简单的重装系统方法在这里 解决方法如下: 1.首先, ...

  4. 打印机打印的时候会打印计算机用户,共享打印机无法打印怎么办 共享打印机无法打印解决方法【图文】...

    用户在使用电脑时可能会经常碰到 共享 打印机 和电脑连接不上的情况,表现为主机启动后 打印机 不联机,或者在打印文件时主机死锁或者打印机无响应.大多数情况下,这些并不是打印机发生了硬件故障,那么 共享 ...

  5. SAP假脱机打印解决方法

    使用的标准的打印机格式,没有添加一些其他格式. 使用客户端为SAP 740 问题情况是:1.假脱机请求已完成,但是没有打印出来. 解决方法是:su3 2. 点击打印跳出窗口显示SAP用户名以及gui ...

  6. 打印机无法打印解决方法

    检测环境 若使用网络连接,查看网络连接是否正常,是否能ping通: 查看打印机是否正忙碌或空闲,若处理空闲待机状态,按下打印机上的OK按钮,激活打印机:忙碌则等待. 驱动异常 在控制面板中找到打印机设 ...

  7. linux web打印,曲折的 web 打印解决方法

    最近做一个项目,是关于报告之类的,涉及到报告打印这个功能,真是坑了个爹啊.在网上找了很多方法,web打印有很多控件,如:杰表打印,lodop,等等.因为业务上的报表表格都是一些word文档,其内容也非 ...

  8. 打印机显示已暂停不能打印解决方法

    点击菜单,打印机->暂停打印    即可解决.

  9. 【解决方法】Word在使用方向键时,光标有较大延迟。

    内容来源 外网[Lagging cursor in Word while using arrow keys],Microsoft论坛帖子的翻译和整理. 原贴地址: link 本文作者:kiri_m 季 ...

最新文章

  1. 什么是shell,shell基础由浅入深,常用的shell命令、用法、技巧
  2. 网页设计千千万,网站建设万万千
  3. 页面导航的基础与深入
  4. Windows 下 MySQL-python 的安装
  5. smokeping自动检测系统
  6. LeetCode 426. 将二叉搜索树转化为排序的双向链表(BST中序循环遍历)
  7. 你不知道的接口测试之简单的开始
  8. 大数据分析常用的方法有哪些
  9. 易用宝项目记录day8-Excel的导入导出
  10. 超分算法之SRCNN
  11. 如何设置内网打印机端口网络穿透到公网
  12. 迅投QMT量化交易系统介绍
  13. 星空华文通过聆讯:吃《中国好声音》老本 华人文化是股东
  14. 有什么小号音准测试软件,小号演奏家对小号初学者的一些建议 | 悦趣音乐中心...
  15. 计算机和计算机之间如何传送文件,两台电脑实现互传文件:多种方法可选择
  16. 服务器怎么显示我的电脑图标没了,我的电脑图标没了怎么办?在这里可以将它显示出来...
  17. 厦门大学“网宿杯“17届程序设计竞赛决赛(同步赛) #题解 #题目都超有趣呀
  18. 用单片机c51电子秤的c语言,基于51单片机的电子秤系统设计
  19. kodi树莓派_树莓派Raspberry Pi 安装XBMC(Kodi)方法及使用教程
  20. 基于java+jsp+mysql的酒店预订系统

热门文章

  1. python常用变量名_python基础知识整理
  2. spring定时每天早上八点_Spring Boot教程(13) – 简单定时任务
  3. java文件锁定_如何使用java锁定文件(如果可能的话)
  4. linux cat 查看文件内容 不带#号的,Linux下如何不用cat命令读取文件内容
  5. python的切片和索引是什么_NumPy 切片和索引
  6. java 判断页面刷新_如何判断一个网页是刷新还是关闭的方法
  7. 能量平衡_500kA 铝电解槽的能量平衡分析
  8. bootstrap跟vue冲突吗_知道微服务,但你知道微前端吗?
  9. linux dev controlC0,关于Linux的alsa音频问题解决
  10. 力扣(LeetCode)刷题,简单+中等题(第35期)