当前位置: 移动技术网 > IT编程>开发语言>.net > WPF实战案例-打印

WPF实战案例-打印

2019年01月09日  | 移动技术网IT编程  | 我要评论

华为s860,冯一非,天猫动态评分

在前段时间做了一下打印,因为需要支持的格式比较多,所以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 = 1; 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 = 75; //打印时页面设置,缩放比例百分之几
                worksheet.pagesetup.zoom = false; //打印时页面设置,必须设置为false,页高,页宽才有效
                worksheet.pagesetup.fittopageswide = 1; //设置页面缩放的页宽为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 = 2 / 0.035; //左边距为2cm
                worksheet.pagesetup.rightmargin = 2 / 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 = 0;
                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 = 0;
                double imgheight = 0;
                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) <= 0 ? 2 : (_pagesize.width - imgwidth)) / 2;
                double top = math.abs((_pagesize.height - imgheight) <= 0 ? 2 : (_pagesize.height - imgheight)) / 2;

                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 1;
            }
        }
        #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 = 0, dwwritten = 0;
            intptr hprinter = new intptr(0);
            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, 1, 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(0);
            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, 0, 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群。

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网