WPF实战案例-打印
在前段时间做了一下打印,因为需要支持的格式比较多,所以wpf能打印的有限分享一下几种格式的打印(.xls .xlsx .doc .docx .png .jpg .bmp .pdf)
首先为了保证excel和word的格式问题,excel和word是调用的office进行打印的。
获取所有打印机的方法:
LocalPrintServer print = new LocalPrintServer();
var printers = print.GetPrintQueues();
foreach (var item in printers)
{
//打印机名称 item.Name;
}
Excel打印。三个参数 :1.打印机名称 2要打印的文件路径+名称 3要打印的sheet页名称(可以不写就打印全部sheet)
static Excel.Application Application { get; set; }
public static void PrintExcel(string printName, string fileName, List<string> sheetNames = null)
{
if (Application == null)
Application = new Excel.Application();
Application.Visible = false;
//Application.Calculation = Excel.XlCalculation.xlCalculationManual;
var book = Application.Workbooks.Open(fileName);
if (sheetNames == null)
{
sheetNames = new List<string>();
Excel.Sheets sheets = book.Sheets;
for (int i = ; i <= sheets.Count; i++)
{
Excel.Worksheet workSheet = sheets.Item[i];
if (workSheet.Visible != Excel.XlSheetVisibility.xlSheetHidden)
sheetNames.Add(workSheet.Name);
}
}
foreach (var item in sheetNames)
{
Excel.Worksheet workSheet = (Excel.Worksheet)book.Worksheets[item];
//------------------------打印页面相关设置--------------------------------
workSheet.PageSetup.PaperSize = Excel.XlPaperSize.xlPaperA4;//纸张大小
//workSheet.PageSetup.Orientation = Excel.XlPageOrientation.xlLandscape;//页面横向
workSheet.PageSetup.Zoom = ; //打印时页面设置,缩放比例百分之几
workSheet.PageSetup.Zoom = false; //打印时页面设置,必须设置为false,页高,页宽才有效
workSheet.PageSetup.FitToPagesWide = ; //设置页面缩放的页宽为1页宽
workSheet.PageSetup.FitToPagesTall = false; //设置页面缩放的页高自动
//workSheet.PageSetup.LeftHeader = "Nigel";//页面左上边的标志
//workSheet.PageSetup.CenterFooter = "第 &P 页,共 &N 页";//页面下标
workSheet.PageSetup.FirstPageNumber = (int)Excel.Constants.xlAutomatic;
workSheet.PageSetup.Order = Excel.XlOrder.xlDownThenOver;
workSheet.PageSetup.PrintGridlines = true; //打印单元格网线
workSheet.PageSetup.TopMargin = 1.5 / 0.035; //上边距为2cm(转换为in)
workSheet.PageSetup.BottomMargin = 1.5 / 0.035; //下边距为1.5cm
workSheet.PageSetup.LeftMargin = / 0.035; //左边距为2cm
workSheet.PageSetup.RightMargin = / 0.035; //右边距为2cm
workSheet.PageSetup.CenterHorizontally = true; //文字水平居中
//------------------------打印页面设置结束--------------------------------
workSheet.PrintOutEx(Missing.Value, Missing.Value, Missing.Value, Missing.Value, printName);
}
//book.PrintOutEx(Missing.Value, Missing.Value, Missing.Value, Missing.Value, printName); //直接打印
book.Close(false); //关闭工作空间
}
excel有时候关不干净,贡献一个强制关闭的方法,可以在excel操作完成后调用:
[DllImport("User32.dll")]
public static extern int GetWindowThreadProcessId(IntPtr hWnd, out int Processid);
public static void ExcelClose()
{
if (Application != null)
{
Application.Quit();
int iId = ;
IntPtr intptr = new IntPtr(Application.Hwnd);
System.Diagnostics.Process p = null;
try
{
GetWindowThreadProcessId(intptr, out iId);
p = System.Diagnostics.Process.GetProcessById(iId);
if (p != null)
{
p.Kill();
p.Dispose();
}
Application = null;
}
catch (Exception e)
{
throw e;
}
}
System.GC.Collect();
}
Word打印(打印机名称,要打印的文件路径+名称)
public static void PrintWord(string printName, string fileName)
{
Word.Application appword = new Word.Application();
appword.Visible = false;
appword.DisplayAlerts = Word.WdAlertLevel.wdAlertsNone;
Word.Document doc = appword.Documents.Open(fileName);
appword.ActivePrinter = printName;
doc.PrintOut(true);
doc.Close(false);
appword.Quit();
}
图片打印WPF(支持格式 png jpg bmp)
public static string PrintImage(string printName, string fileName)
{
System.Windows.Controls.PrintDialog dialog = new System.Windows.Controls.PrintDialog();//开始打印
var printers = new LocalPrintServer().GetPrintQueues(); var selectedPrinter = printers.FirstOrDefault(d => d.Name == printName);
if (selectedPrinter == null)
{
return "没有找到打印机";
}
dialog.PrintQueue = selectedPrinter;
dialog.PrintDocument(new TestDocumentPaginator(new BitmapImage(new Uri(fileName))), "Image");
return ""; }
public class TestDocumentPaginator : DocumentPaginator
{ #region 字段
private Size _pageSize;
private ImageSource image;
#endregion #region 构造
public TestDocumentPaginator(BitmapImage img)
{
image = img;
//我们使用A3纸张大小
var pageMediaSize = LocalPrintServer.GetDefaultPrintQueue()
.GetPrintCapabilities()
.PageMediaSizeCapability
.FirstOrDefault(x => x.PageMediaSizeName == PageMediaSizeName.ISOA4); if (pageMediaSize != null)
{
_pageSize = new Size((double)pageMediaSize.Width, (double)pageMediaSize.Height);
}
}
#endregion #region 重写
/// <summary>
///
/// </summary>
/// <param name="pageNumber">打印页是从0开始的</param>
/// <returns></returns>
public override DocumentPage GetPage(int pageNumber)
{
var visual = new DrawingVisual(); using (DrawingContext dc = visual.RenderOpen())
{
double imgWidth = ;
double imgHeight = ;
if (image.Height > _pageSize.Height)
{
double h = _pageSize.Height / image.Height;
imgWidth = image.Width * h;
imgHeight = image.Height * h;
}
if (image.Width > _pageSize.Width)
{
double w = _pageSize.Width / image.Width;
imgWidth = image.Width * w;
imgHeight = image.Height * w;
} if (image.Width < _pageSize.Width && image.Height < _pageSize.Height)
{
double h = _pageSize.Height / image.Height;
double w = _pageSize.Width / image.Width;
if (h > w)
{
imgWidth = image.Width * w;
imgHeight = image.Height * w;
}
else
{
imgWidth = image.Width * h;
imgHeight = image.Height * h;
} } double left = Math.Abs((_pageSize.Width - imgWidth) <= ? : (_pageSize.Width - imgWidth)) / ;
double top = Math.Abs((_pageSize.Height - imgHeight) <= ? : (_pageSize.Height - imgHeight)) / ; dc.DrawImage(image, new Rect(left, top, imgWidth, imgHeight));
} return new DocumentPage(visual, _pageSize, new Rect(_pageSize), new Rect(_pageSize));
} public override bool IsPageCountValid
{
get
{
return true;
}
} public override Size PageSize
{
get
{
return _pageSize;
}
set
{
_pageSize = value;
}
} public override IDocumentPaginatorSource Source
{
get
{
return null;
}
} public override int PageCount
{
get
{
return ;
}
}
#endregion
}
TestDocumentPaginator内部的重写方法是计算将图片全部居中显示。
关于图片打印多说一句:在之前我是使用image加载图片,然后通过PrintVisual打印控件的方式打印的,但是这种方式我发现在win7机器上打印出来的是空白纸张,还没明白是为什么,所以就用这种方式了。 PDF打印(这是调用windows api去打印,不需要乱起八糟的第三方):
// Structure and API declarions:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public class DOCINFOA
{
[MarshalAs(UnmanagedType.LPStr)]
public string pDocName;
[MarshalAs(UnmanagedType.LPStr)]
public string pOutputFile;
[MarshalAs(UnmanagedType.LPStr)]
public string pDataType;
} [DllImport("winspool.Drv", EntryPoint = "OpenPrinterA", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool OpenPrinter([MarshalAs(UnmanagedType.LPStr)] string szPrinter, out IntPtr hPrinter, IntPtr pd); [DllImport("winspool.Drv", EntryPoint = "ClosePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool ClosePrinter(IntPtr hPrinter); [DllImport("winspool.Drv", EntryPoint = "StartDocPrinterA", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool StartDocPrinter(IntPtr hPrinter, Int32 level, [In, MarshalAs(UnmanagedType.LPStruct)] DOCINFOA di); [DllImport("winspool.Drv", EntryPoint = "EndDocPrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool EndDocPrinter(IntPtr hPrinter); [DllImport("winspool.Drv", EntryPoint = "StartPagePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool StartPagePrinter(IntPtr hPrinter); [DllImport("winspool.Drv", EntryPoint = "EndPagePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool EndPagePrinter(IntPtr hPrinter); [DllImport("winspool.Drv", EntryPoint = "WritePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool WritePrinter(IntPtr hPrinter, IntPtr pBytes, Int32 dwCount, out Int32 dwWritten); // SendBytesToPrinter()
// When the function is given a printer name and an unmanaged array
// of bytes, the function sends those bytes to the print queue.
// Returns true on success, false on failure.
public static bool SendBytesToPrinter(string szPrinterName, IntPtr pBytes, Int32 dwCount)
{
Int32 dwError = , dwWritten = ;
IntPtr hPrinter = new IntPtr();
DOCINFOA di = new DOCINFOA();
bool bSuccess = false; // Assume failure unless you specifically succeed. di.pDocName = "My C#.NET RAW Document";
di.pDataType = "RAW"; // Open the printer.
if (OpenPrinter(szPrinterName.Normalize(), out hPrinter, IntPtr.Zero))
{
// Start a document.
if (StartDocPrinter(hPrinter, , di))
{
// Start a page.
if (StartPagePrinter(hPrinter))
{
// Write your bytes.
bSuccess = WritePrinter(hPrinter, pBytes, dwCount, out dwWritten);
EndPagePrinter(hPrinter);
}
EndDocPrinter(hPrinter);
}
ClosePrinter(hPrinter);
}
// If you did not succeed, GetLastError may give more information
// about why not.
if (bSuccess == false)
{
dwError = Marshal.GetLastWin32Error();
}
return bSuccess;
} public static bool SendFileToPrinter(string szPrinterName, string szFileName)
{
// Open the file.
FileStream fs = new FileStream(szFileName, FileMode.Open);
// Create a BinaryReader on the file.
BinaryReader br = new BinaryReader(fs);
// Dim an array of bytes big enough to hold the file's contents.
Byte[] bytes = new Byte[fs.Length];
bool bSuccess = false;
// Your unmanaged pointer.
IntPtr pUnmanagedBytes = new IntPtr();
int nLength; nLength = Convert.ToInt32(fs.Length);
// Read the contents of the file into the array.
bytes = br.ReadBytes(nLength);
// Allocate some unmanaged memory for those bytes.
pUnmanagedBytes = Marshal.AllocCoTaskMem(nLength);
// Copy the managed byte array into the unmanaged array.
Marshal.Copy(bytes, , pUnmanagedBytes, nLength);
// Send the unmanaged bytes to the printer.
bSuccess = SendBytesToPrinter(szPrinterName, pUnmanagedBytes, nLength);
// Free the unmanaged memory that you allocated earlier.
Marshal.FreeCoTaskMem(pUnmanagedBytes);
return bSuccess;
} public static bool SendStringToPrinter(string szPrinterName, string szString)
{
IntPtr pBytes;
Int32 dwCount;
// How many characters are in the string?
dwCount = szString.Length;
// Assume that the printer is expecting ANSI text, and then convert
// the string to ANSI text.
pBytes = Marshal.StringToCoTaskMemAnsi(szString);
// Send the converted ANSI string to the printer.
SendBytesToPrinter(szPrinterName, pBytes, dwCount);
Marshal.FreeCoTaskMem(pBytes);
return true;
}
public static void PrintPDF(string printName, string fileName)
{
SendFileToPrinter(printName, fileName);
}
以上就是wpf常用的打印,目前看起来格式还是可以达到要求的,更多技术讨论请关注页面下方的qq群。
WPF实战案例-打印的更多相关文章
- 如何从40亿整数中找到不存在的一个 webservice Asp.Net Core 轻松学-10分钟使用EFCore连接MSSQL数据库 WPF实战案例-打印 RabbitMQ与.net core(五) topic类型 与 headers类型 的Exchange
如何从40亿整数中找到不存在的一个 前言 给定一个最多包含40亿个随机排列的32位的顺序整数的顺序文件,找出一个不在文件中的32位整数.(在文件中至少确实一个这样的数-为什么?).在具有足够内存的情况 ...
- WPF实战案例-MVVM模式下在Xaml中弹出窗体
相信很多学习和开发wpf项目的同学都了解过mvvm模式,同样,在mvvm模式下会有一个不可忽视的问题,就是怎么在xaml中弹出窗体,而不破坏MVVM本身的结构. 关于弹出窗体的方式还是很多的,本文先讲 ...
- WPF实战案例-数据代理
在我们wpf开发中,很多人会有mvvm模式去做wpf的项目. 是否有人遇到这样一个场景:在一个界面上,有个tabcontrol上面有4个页签,每个页签里面都有一个datagrid,里面显示的列基本一样 ...
- WPF实战案例-在线程内同步集合数据到UI线程
有这样一个场景,在vm中,我们为了ui的体验,会异步访问后端接口,获取数据集合,如果这个集合绑定到界面,并且在线程内,怎么处理? 有人讲:this.Dispatcher.Invoke,如果在vm内呢? ...
- WPF实战案例-MVVM模式下用附加属性在Xaml中弹出窗体
嗯..最近回家去了,2个月没写过代码了,面试只能吹牛,基础都忘了,今天回顾一下,分享一篇通过附加属性去处理窗体弹出的情况. 或许老司机已经想到了,通过设置附加属性值,值变更的回调函数去处理窗体弹出,是 ...
- 3.awk数组详解及企业实战案例
awk数组详解及企业实战案例 3.打印数组: [root@nfs-server test]# awk 'BEGIN{array[1]="zhurui";array[2]=" ...
- 企业Shell面试题及企业运维实战案例(三)
1.企业Shell面试题1:批量生成随机字符文件名案例 使用for循环在/oldboy目录下批量创建10个html文件,其中每个文件需要包含10个随机小写字母加固定字符串oldboy,名称示例如下: ...
- (转)awk数组详解及企业实战案例
awk数组详解及企业实战案例 原文:http://www.cnblogs.com/hackerer/p/5365967.html#_label03.打印数组:1. [root@nfs-server t ...
- shell脚本编程——生产实战案例
生产实战案例 在日常的生产环境中,可能会遇到需要批量检查内网目前在线的主机IP地址有哪些,还可能需要检查这些在线的主机哪些端口是开放状态,因此依靠手工来检查是可以实现,但比较费时费力,所以需要 ...
随机推荐
- vb中去掉string数组的一部分
今天碰到一个问题,登陆的时候,如果不需要验证手机号为空,则不去验证手机号 因为登陆的时候所有的验证信息都存放在一个数组里 Dim CheckUserInfo() As String ={UserBir ...
- Windows 8.1 新控件和功能:
http://msdn.microsoft.com/zh-cn/library/windows/apps/bg182878.aspx#five 将 XAML 树呈现为位图: 适用于 Windows 8 ...
- 【Web】CSS实现绝对定位元素水平垂直居中
网页中常常需用让绝对定位元素水平垂直居中,下面介绍2种方法: 一 元素宽度未知 <!DOCTYPE html> <html lang="en"> <h ...
- js 分页
html代码: <div id="paging_wrap" class="paging-wrap"></div> css代码: div ...
- JS页面跳转大全
所谓的js页面跳转就是利用javesrcipt对打开的页面ULR进行跳转,如我们打开的是A页面,通过javsrcipt脚本就会跳转到B页面.目前很多垃圾站经常用js跳转将正常页面跳转到广告页面,当然也 ...
- Docker学习以及镜像制作流程
一.何为Docker Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从Apache2.0协议开源. Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级.可移植的容器中,然后 ...
- 6-具体学习git--分支冲突,rebase|| stash 临时修改
rebase很危险. https://morvanzhou.github.io/tutorials/others/git/
- Linux查看登录到服务的用户,查看用户的操作已经剔掉干坏事的用户的命令
在工作中,我们有时候会经常的切换用户,有时候会忘记切换到哪个用户了,我们就需要知道当前登录的用户时谁,可以使用: whoami 查看当前登录到系统中的用户有哪些: who 列表中显示,第一列是用户名, ...
- .net 导出Excel
CreateExcel(ExcelDs, ", f); void CreateExcel(DataSet ds, string typeid, string FileName) { Http ...
- Jersey RESTful WebService框架学习(六)接收MultivaluedMap类型参数
现在的web开发中有些工程会觉得实体bean的架构会比较重,现在的持久层的框架的特点也层出不穷,核心思想的ORM在此基础上,提供了很多便捷操作,mybatis,jfinal(内部持久层框架)之类的也诞 ...