惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

N
Netflix TechBlog - Medium
I
Intezer
人人都是产品经理
人人都是产品经理
F
Full Disclosure
A
About on SuperTechFans
罗磊的独立博客
大猫的无限游戏
大猫的无限游戏
Google DeepMind News
Google DeepMind News
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
J
Java Code Geeks
博客园 - 三生石上(FineUI控件)
腾讯CDC
Stack Overflow Blog
Stack Overflow Blog
云风的 BLOG
云风的 BLOG
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Blog — PlanetScale
Blog — PlanetScale
Microsoft Azure Blog
Microsoft Azure Blog
I
InfoQ
博客园 - 司徒正美
P
Proofpoint News Feed
宝玉的分享
宝玉的分享
Engineering at Meta
Engineering at Meta
F
Fortinet All Blogs
The GitHub Blog
The GitHub Blog
L
LangChain Blog
Last Week in AI
Last Week in AI
B
Blog
Project Zero
Project Zero
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
S
Schneier on Security
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
U
Unit 42
B
Blog RSS Feed
Y
Y Combinator Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
P
Privacy International News Feed
N
News and Events Feed by Topic
W
WeLiveSecurity
Cloudbric
Cloudbric
G
GRAHAM CLULEY
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
C
Check Point Blog
G
Google Developers Blog
The Last Watchdog
The Last Watchdog
Latest news
Latest news
S
Secure Thoughts
Simon Willison's Weblog
Simon Willison's Weblog
Scott Helme
Scott Helme
H
Heimdal Security Blog
Application and Cybersecurity Blog
Application and Cybersecurity Blog

博客园 - 曾伟

wpf 滚屏数据显示 net core quartz调度 warp打包 nssm部署到windowsservice c# webapi 过滤器token、sign认证、访问日志 c# NPOI文件操作 c# ini文件操作 WCF多种调用方式兼容 网页打印javascript:window.print() window.showModalDialog弹出对话框刷新问题 ASP.NET] 选择文件夹的对话框 常用SQL语句书写技巧 控制同一exe程序打开多次 - 曾伟 - 博客园 IIS6 MMC检测到此管理单元发生一个错误,建议您关闭并重新启动mmc 在上传文件时限制上传文件的大小,并捕捉超过文件大小限制的 - 曾伟 - 博客园 Lucene的例子 javascript 获取标签具体位置 - 曾伟 - 博客园 JavaScript实现类,有多种方法。 Javascript实现截图功能(代码) 终端服务器超出了最大允许连接数 DBCC CHECKDB 数据库或表修复
不干胶、热敏打印
曾伟 · 2020-05-20 · via 博客园 - 曾伟

仓储物流的过程中往往少不了一些使用热敏打印机或者碳带打印机打印一些条码、信息贴在实物或者包裹上

最好的实现方式不过于直接使用热敏代码形成文本直接输出到打印机做打印

但是热敏代码也是一门需要特殊的语言,需要学习

故为了更快更方便的实现,就用到了画布绘制后形成image输出到打印机

而image也是有要求的,比如输出的格式、大小直接影响打印的质量

这里介绍下使用微软的报表布局绑定数据转image输出到打印机的方式

1、nuget上搜索Microsoft.ReportViewer.Common、Microsoft.ReportViewer.WebForms安装

2、创建rdlc报表,绘制指定打印输出的模板大小,对rdlc添加数据集,可以为对象,这里使用对象绑定(后台查询数据映射给对象)

  可以为界面每个项的属性进行设置:字体、大小、数据绑定、对齐等,也可以动态使用表达式(数据源传入指定值)

3、打印入口,为报表绑定数据

 DeviceInfo的详细说明见:

  https://docs.microsoft.com/zh-cn/sql/reporting-services/image-device-information-settings?redirectedfrom=MSDN&view=sql-server-ver15

  LocalReport.Render使用见

  https://docs.microsoft.com/zh-cn/previous-versions/dd468075(v=vs.140)

  注意:OutputFormat为EMF

      PageWidth、PageHeight为rdlc的大小

  如果需要使用到条码信息,则需要声明byte[] 接收使用BarcodeLib.Barcode相关条码类生成条码图片

  rdlc模板上添加图像控件字段指向byte[]字段,mime选择image/png,大小显示为:调整为合适大小

  测试时可以保存为图片,预览效果图

public string PrintOutPackage(string Consignee, string ContractCode,string ConsigneeAddress, int count, int cur, string printName, int type=1)
        {
            if (string.IsNullOrWhiteSpace(printName))
            {
                return "没有选择打印机";
            }

            using (LocalReport report = new LocalReport())
            {
                report.ReportPath = System.Windows.Forms.Application.StartupPath + "/Content/OutPackage.rdlc";
                report.DataSources.Clear();

                var printModel = new OutPackagePrintModel() { Consignee = Consignee, ContractCode = ContractCode, ConsigneeAddress = ConsigneeAddress, PackageCount = count, CurPackageCount = cur, ConsigneeFontSize = Consignee.Length <= 3 ? "28pt" : Consignee.Length <= 12 ? "16pt" : "12px" };

                var list = new List<OutPackagePrintModel>();
                list.Add(printModel);
                ReportDataSource ds = new ReportDataSource("OutPackage", list);//绑定数据源
                report.DataSources.Add(ds);
                report.Refresh();
                string deviceInfo =
                    "<DeviceInfo>" +
                    "  <OutputFormat>EMF</OutputFormat>" +
                     "  <PageWidth>8cm</PageWidth>" +
                     "  <PageHeight>5cm</PageHeight>" +
                      "<PrintDpiX>300</PrintDpiX>" +
                      "<PrintDpiY>300</PrintDpiY>" +
                     "  <MarginTop>0pt</MarginTop>" +
                    "  <MarginLeft>0pt</MarginLeft>" +
                    "  <MarginRight>0pt</MarginRight>" +
                    "  <MarginBottom>0pt</MarginBottom>" +
                    "</DeviceInfo>";
                Warning[] warnings;
                m_streams = new List<Stream>();
                //将报表的内容按照deviceInfo指定的格式输出到CreateStream函数提供的Stream中。
                report.Render("Image", deviceInfo, CreateStream, out warnings);
            }

            foreach (Stream stream in m_streams)
            {
                stream.Position = 0;
            }

            Image pageImage = Image.FromStream(m_streams[0]);

            if (type == 2)
            {
                //测试时保存图片
                pageImage.Save(@"d:\" + $"{cur}_{count}" + ".emf", ImageFormat.Tiff);
                return "已保存图片";
            }

            //正式时调用打印机打印
            var r = Printer.PrintImageData(pageImage, printName, "0", "0");
            if (!r.IsSuccess)
                return r.Message;
            return "";
        }

        private Stream CreateStream(string name, string fileNameExtension,
          Encoding encoding, string mimeType, bool willSeek)
        {
            //如果需要将报表输出的数据保存为文件,请使用FileStream对象。
            Stream stream = new MemoryStream();
            BillPrintSteam = stream;
            m_streams.Add(stream);
            return stream;
        }

4、生成的图片输出到打印机打印:

  将生成的image在打印机端

  可使用PrinterSettings.StringCollection listPrint = PrinterSettings.InstalledPrinters;获取所有打印机名称

public static PrintModel PrintImageData(Image pageImage,string PrinterName,string PaperSizeWidth,string PaperSizeHeight)
        {
            bool PrintIsSuccess=false;
            Exception PrintException=null;
            //声明PrintDocument对象用于数据的打印
            PrintDocument printDoc = new PrintDocument();
            printDoc.DefaultPageSettings.Margins = new Margins(0, 0, 0, 0);
            //指定需要使用的打印机的名称,使用空字符串""来指定默认打印机
            //传入打印机名称 则使用传入的,否则使用当前服务账户(登录为)的默认打印机
            if (!string.IsNullOrWhiteSpace(PrinterName))
            {
                printDoc.PrinterSettings.PrinterName = PrinterName;
            }
            //判断指定的打印机是否可用
            if (!printDoc.PrinterSettings.IsValid)
            {
                return PrintModel.CreateFailedResult("未能找到默认的打印机!");
            }

            if (!string.IsNullOrWhiteSpace(PaperSizeWidth) && PaperSizeWidth != "0" && !string.IsNullOrWhiteSpace(PaperSizeHeight) && PaperSizeHeight != "0")
            {
                var ps = new PaperSize("Your Paper Name", int.Parse(PaperSizeWidth), int.Parse(PaperSizeHeight)) { RawKind = 120 };//自定义纸张
                printDoc.DefaultPageSettings.PaperSize = ps;
            }
            printDoc.PrintPage += new PrintPageEventHandler(delegate (object sender, PrintPageEventArgs ev)
            {
                try
                {
                    ev.Graphics.PageUnit = GraphicsUnit.Document;
                    //ev.Graphics.CompositingQuality = CompositingQuality.HighQuality;
                    //ev.Graphics.PageScale = 1;
                    if (pageImage == null) return;
                    // Adjust rectangular area with printer margins.
                    Rectangle adjustedRect = new Rectangle(
                        ev.PageBounds.Left - (int)ev.PageSettings.HardMarginX,
                        ev.PageBounds.Top - (int)ev.PageSettings.HardMarginY,
                        ev.PageBounds.Width,
                        ev.PageBounds.Height);

                    Rectangle srcRect = new Rectangle(0, 0, pageImage.Width, pageImage.Height);
                    // Draw a white background for the report
                    //ev.Graphics.FillRectangle(Brushes.White, adjustedRect);
                    // Draw the report content
                    ev.Graphics.DrawImage(pageImage, srcRect);//, srcRect, GraphicsUnit.Pixel);
                    ev.HasMorePages = false;
                }
                catch (Exception ex)
                {
                    PrintException = ex;
                    PrintIsSuccess = false;
                }
            });

            try
            {
                if (pageImage == null)
                {
                    PrintIsSuccess = false;
                }
                else
                {
                    printDoc.Print();
                    PrintIsSuccess = true;
                }
            }
            catch (Exception ex)
            {
                PrintException = ex;
                PrintIsSuccess = false;
            }

            return PrintModel.Create(PrintIsSuccess, PrintIsSuccess ? "Print Success!" : "Print Fail!", PrintException);
        }
public static List<PrinterModel> GetPrinterList()
        {
            PrinterSettings ps = new PrinterSettings();
            PrinterSettings.StringCollection listPrint = PrinterSettings.InstalledPrinters;
            List<PrinterModel> pList = new List<PrinterModel>();
            for (int i = 0; i < listPrint.Count; i++)
            {
                PrinterModel pm = new PrinterModel();
                ps.PrinterName = listPrint[i];
                pm.PrinterName = ps.PrinterName;
                pm.IsDefaultPrinter = ps.IsDefaultPrinter;
                pm.OrderBy = pm.IsDefaultPrinter ? -1 : i;
                pList.Add(pm);
            }
            return pList.OrderBy(x => x.OrderBy).ToList();
        }

以上cs结构下不需要特殊权限

如果为bs结构下或者需要ajax调取打印机的(电子称重同理可借鉴):

1、可以将打印图片的方法作为接口宿主到windowsservice上开放端口,安装在需要打印的电脑上。

  接收的不是image改为图片的url,得到url后进行download后输出到打印机

  可以增加接口判断打印服务是否可用

在app.config增加

<services>
      <service behaviorConfiguration="EnableMetadataBehaviors" name="Shangpin.Logistic.WindowsService.ClientPrintService.ServiceLibrary.PrintService">
        <endpoint address="" binding="webHttpBinding" behaviorConfiguration="WebScriptBehavior" bindingConfiguration="HttpJsonpBinding" contract="Shangpin.Logistic.WindowsService.ClientPrintService.ServiceLibrary.IPrintService" />
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:41943/PrintService" />
          </baseAddresses>
        </host>
      </service>

2、形成图片的方法作为服务端接口可得到图片,接口url可匿名给打印服务获取图片

$.ajax({
    url: "http://localhost:41943/PrintService/Print?jsoncallback=?",
    dataType: 'jsonp',
    data: { url: imageUrl, printerName: $("#PrinterList").find("option:selected").val(), paperSizeWidth: paperSizeWidth, paperSizeHeight: paperSizeHeight },
    success: function (data) {
        if (!data.IsSuccess) {
            LG.showError("明细编号" + printArr[i] + "打印失败:" + data.Message, function () {
                JudgePrintAgain(printArr, i, url, paperSizeWidth, paperSizeHeight);//循环打印
            });
        } else {
            JudgePrintAgain(printArr, i, url, paperSizeWidth, paperSizeHeight);
        }
    },
    error: function (result) {
        LG.tip('发现系统错误 <br />错误码:' + result.status);
    }
});