|
|
@@ -1,9 +1,13 @@
|
|
|
using Newtonsoft.Json;
|
|
|
+using NPOI.Util;
|
|
|
+using Seagull.BarTender.Print;
|
|
|
using System;
|
|
|
using System.Collections.Generic;
|
|
|
using System.ComponentModel;
|
|
|
using System.Data;
|
|
|
using System.Drawing;
|
|
|
+using System.Drawing.Printing;
|
|
|
+using System.IO;
|
|
|
using System.Linq;
|
|
|
using System.Net;
|
|
|
using System.Net.Sockets;
|
|
|
@@ -28,6 +32,8 @@ namespace UAS_MES_NEW.Make
|
|
|
private SocketServer _server;
|
|
|
private int currCount = 0;
|
|
|
|
|
|
+ private LabelPrinter _printer;
|
|
|
+
|
|
|
private void Make_ServerListen_Load(object sender, EventArgs e)
|
|
|
{
|
|
|
dh = SystemInf.dh;
|
|
|
@@ -36,6 +42,12 @@ namespace UAS_MES_NEW.Make
|
|
|
_server.ReceivedDatas += SocketServer_ReceivedDatas;
|
|
|
_server.ReceivedMsg += SocketServer_ReceivedMsg;
|
|
|
|
|
|
+ var printers = LabelPrinter.GetLocalPrinters();
|
|
|
+ foreach (var printerName in printers)
|
|
|
+ {
|
|
|
+ PrintList.Items.Add(printerName);
|
|
|
+ }
|
|
|
+
|
|
|
try
|
|
|
{
|
|
|
IPHostEntry hostEntry = Dns.GetHostEntry(Dns.GetHostName());
|
|
|
@@ -103,6 +115,80 @@ namespace UAS_MES_NEW.Make
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ private void confirmPrint_Click(object sender,EventArgs e)
|
|
|
+ {
|
|
|
+ /*if (Start.Text == "开启监听")
|
|
|
+ {
|
|
|
+ Start.Focus();
|
|
|
+ ShowMsg(0, "请开启监听服务");
|
|
|
+ return;
|
|
|
+ }*/
|
|
|
+
|
|
|
+ if (PrintList.SelectedIndex == -1)
|
|
|
+ {
|
|
|
+ PrintList.Focus();
|
|
|
+ PrintList.SelectAll();
|
|
|
+ ShowMsg(0, "请选择打印列表");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (confirmPrint.Text == "确认打印机")
|
|
|
+ {
|
|
|
+ confirmPrint.Text = "取消打印机";
|
|
|
+ PrintList.Enabled = false;
|
|
|
+
|
|
|
+ _printer = new LabelPrinter(Application.StartupPath + "\\机身标 (1).btw");
|
|
|
+ _printer.SetPrinter(PrintList.Text);
|
|
|
+ _printer.PrintError += (s, args) =>
|
|
|
+ {
|
|
|
+ ShowMsg(0, $"打印错误: {args.ErrorMessage}");
|
|
|
+ };
|
|
|
+ ShowMsg(1, "已加载打印机资源");
|
|
|
+
|
|
|
+ /*using (_printer = new LabelPrinter(Application.StartupPath + "\\机身标 (1).btw"))
|
|
|
+ {
|
|
|
+ _printer.SetPrinter(PrintList.Text);
|
|
|
+ _printer.PrintError += (s, args) =>
|
|
|
+ {
|
|
|
+ ShowMsg(0, $"打印错误: {args.ErrorMessage}");
|
|
|
+ };
|
|
|
+ }*/
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ confirmPrint.Text = "确认打印机";
|
|
|
+ PrintList.Enabled = true;
|
|
|
+
|
|
|
+ if (_printer != null)
|
|
|
+ {
|
|
|
+ _printer.Dispose();
|
|
|
+ _printer = null;
|
|
|
+ ShowMsg(1, "打印机资源已释放");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void TestPrint_Click(object sender, EventArgs e)
|
|
|
+ {
|
|
|
+ if (PrintList.SelectedIndex == -1)
|
|
|
+ {
|
|
|
+ PrintList.Focus();
|
|
|
+ PrintList.SelectAll();
|
|
|
+ ShowMsg(0, "请选择打印列表");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ string testResult = LabelPrinter.TestPrinterConnection(PrintList.Text);
|
|
|
+ if (testResult.StartsWith("OK"))
|
|
|
+ {
|
|
|
+ ShowMsg(1, testResult);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ ShowMsg(0, testResult);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
private void SocketServer_ReceivedDatas(object sender, ReceivedDatasEventArgs e)
|
|
|
{
|
|
|
this.Invoke(new Action(() =>
|
|
|
@@ -110,6 +196,22 @@ namespace UAS_MES_NEW.Make
|
|
|
currCount += 1;
|
|
|
ShowMsg(1, $"第{currCount}次接收,收到来自 {e.ClientId} 的消息: {e.Message}");
|
|
|
|
|
|
+ var parameters = new Dictionary<string, string>()
|
|
|
+ {
|
|
|
+ {"SN", e.Message}
|
|
|
+ };
|
|
|
+
|
|
|
+ bool success = _printer.PrintLabel(parameters);
|
|
|
+
|
|
|
+ /*var batchParameters = new List<Dictionary<string, string>>();
|
|
|
+ for (int i = 1; i <= 10; i++)
|
|
|
+ {
|
|
|
+ batchParameters.Add(parameters);
|
|
|
+ }
|
|
|
+ int printedCount = _printer.PrintLabels(batchParameters,(current, total) =>
|
|
|
+ { Console.WriteLine($"进度: {current}/{total}");
|
|
|
+ });*/
|
|
|
+
|
|
|
/*VerifyResultMessage message = new VerifyResultMessage
|
|
|
{
|
|
|
Name = "VerifyResult",
|
|
|
@@ -572,5 +674,346 @@ namespace UAS_MES_NEW.Make
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ public class PrintingEventArgs : EventArgs
|
|
|
+ {
|
|
|
+ public string TemplateName { get; set; }
|
|
|
+
|
|
|
+ public Dictionary<string, string> Parameters { get; set; }
|
|
|
+
|
|
|
+ public string PrinterName { get; set; }
|
|
|
+
|
|
|
+ public int Copies { get; set; }
|
|
|
+
|
|
|
+ public bool Cancel { get; set; }
|
|
|
+ }
|
|
|
+
|
|
|
+ public class PrintingErrorEventArgs : EventArgs
|
|
|
+ {
|
|
|
+ public string ErrorMessage { get; }
|
|
|
+
|
|
|
+ public Exception Exception { get; }
|
|
|
+
|
|
|
+ public PrintingErrorEventArgs(string message, Exception exception = null)
|
|
|
+ {
|
|
|
+ ErrorMessage = message;
|
|
|
+ Exception = exception;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public class LabelPrinter : IDisposable
|
|
|
+ {
|
|
|
+ private Engine _engine;
|
|
|
+ private bool _engineStarted = false;
|
|
|
+ private string _templateFolder;
|
|
|
+ private Dictionary<string, LabelFormatDocument> _cachedTemplates;
|
|
|
+
|
|
|
+ public string CurrentPrinterName { get; private set; }
|
|
|
+
|
|
|
+ public string TemplateFolder
|
|
|
+ {
|
|
|
+ get { return _templateFolder; }
|
|
|
+ set
|
|
|
+ {
|
|
|
+ if (!File.Exists(value)) throw new DirectoryNotFoundException($"模板文件夹不存在: {value}");
|
|
|
+ _templateFolder = value;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public bool EnableTemplateCache { get; set; } = true;
|
|
|
+
|
|
|
+ public event EventHandler<PrintingEventArgs> BeforePrint;
|
|
|
+
|
|
|
+ public event EventHandler<PrintingEventArgs> AfterPrint;
|
|
|
+
|
|
|
+ public event EventHandler<PrintingErrorEventArgs> PrintError;
|
|
|
+
|
|
|
+ public static List<string> GetLocalPrinters()
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ return PrinterSettings.InstalledPrinters.Cast<string>().ToList();
|
|
|
+ }
|
|
|
+ catch (Exception)
|
|
|
+ {
|
|
|
+ return new List<string>();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public static string TestPrinterConnection(string printerName)
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ using (var pd = new PrintDocument())
|
|
|
+ {
|
|
|
+ pd.PrinterSettings.PrinterName = printerName;
|
|
|
+ return $"OK,打印机 '{printerName}' 连接正常";
|
|
|
+ }
|
|
|
+ }
|
|
|
+ catch (Exception ex)
|
|
|
+ {
|
|
|
+ return $"NG,打印机 '{printerName}' 连接失败: {ex.Message}";
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public LabelPrinter(string templateFolder = null)
|
|
|
+ {
|
|
|
+ _cachedTemplates = new Dictionary<string, LabelFormatDocument>();
|
|
|
+
|
|
|
+ if (!string.IsNullOrEmpty(templateFolder)) TemplateFolder = templateFolder;
|
|
|
+
|
|
|
+ InitializeEngine();
|
|
|
+ }
|
|
|
+
|
|
|
+ private void InitializeEngine()
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ _engine = new Engine(true);
|
|
|
+ _engine.Start();
|
|
|
+ _engineStarted = true;
|
|
|
+ }
|
|
|
+ catch (Exception ex)
|
|
|
+ {
|
|
|
+ throw new InvalidOperationException("无法启动BarTender引擎: " + ex.Message, ex);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void SetPrinter(string printerName)
|
|
|
+ {
|
|
|
+ if (string.IsNullOrEmpty(printerName))
|
|
|
+ throw new ArgumentNullException(nameof(printerName));
|
|
|
+
|
|
|
+ if (!PrinterExists(printerName))
|
|
|
+ throw new InvalidOperationException($"打印机不存在: {printerName}");
|
|
|
+
|
|
|
+ CurrentPrinterName = printerName;
|
|
|
+ }
|
|
|
+
|
|
|
+ public static bool PrinterExists(string printerName)
|
|
|
+ {
|
|
|
+ return GetLocalPrinters().Any(p => p.Equals(printerName, StringComparison.OrdinalIgnoreCase));
|
|
|
+ }
|
|
|
+
|
|
|
+ public bool PrintLabel(Dictionary<string, string> parameters, int copies = 1)
|
|
|
+ {
|
|
|
+ return PrintLabelInternal(parameters, copies, null);
|
|
|
+ }
|
|
|
+
|
|
|
+ public int PrintLabels(List<Dictionary<string, string>> parametersList,Action<int, int> progressCallback = null)
|
|
|
+ {
|
|
|
+ int successCount = 0;
|
|
|
+ int total = parametersList.Count;
|
|
|
+
|
|
|
+ for (int i = 0; i < total; i++)
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ if (PrintLabelInternal(parametersList[i], 1, null)) successCount++;
|
|
|
+ }
|
|
|
+ catch (Exception ex)
|
|
|
+ {
|
|
|
+ OnPrintError(new PrintingErrorEventArgs($"打印第 {i + 1} 个标签时出错", ex));
|
|
|
+ }
|
|
|
+ progressCallback?.Invoke(i + 1, total);
|
|
|
+ }
|
|
|
+ return successCount;
|
|
|
+ }
|
|
|
+
|
|
|
+ private bool PrintLabelInternal(Dictionary<string, string> parameters,int copies, string specificPrinter)
|
|
|
+ {
|
|
|
+ if (!_engineStarted)
|
|
|
+ throw new InvalidOperationException("打印引擎未启动");
|
|
|
+
|
|
|
+ if (string.IsNullOrEmpty(CurrentPrinterName) && string.IsNullOrEmpty(specificPrinter))
|
|
|
+ throw new InvalidOperationException("未设置打印机");
|
|
|
+
|
|
|
+ LabelFormatDocument format = null;
|
|
|
+ bool isCached = false;
|
|
|
+
|
|
|
+ try
|
|
|
+ {
|
|
|
+ format = GetTemplateDocument(TemplateFolder);
|
|
|
+ isCached = EnableTemplateCache && _cachedTemplates.ContainsValue(format);
|
|
|
+
|
|
|
+ format.PrintSetup.PrinterName = string.IsNullOrEmpty(specificPrinter) ? CurrentPrinterName : specificPrinter;
|
|
|
+ format.PrintSetup.IdenticalCopiesOfLabel = copies;
|
|
|
+
|
|
|
+ if (parameters != null && parameters.Count > 0)
|
|
|
+ {
|
|
|
+ foreach (var param in parameters)
|
|
|
+ {
|
|
|
+ foreach (SubString subString in format.SubStrings)
|
|
|
+ {
|
|
|
+ if (subString.Name.Equals(param.Key, StringComparison.OrdinalIgnoreCase))
|
|
|
+ {
|
|
|
+ subString.Value = param.Value;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ var args = new PrintingEventArgs
|
|
|
+ {
|
|
|
+ TemplateName = TemplateFolder,
|
|
|
+ Parameters = parameters,
|
|
|
+ PrinterName = format.PrintSetup.PrinterName,
|
|
|
+ Copies = copies
|
|
|
+ };
|
|
|
+ OnBeforePrint(args);
|
|
|
+
|
|
|
+ if (args.Cancel)
|
|
|
+ {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ Result result = format.Print();
|
|
|
+
|
|
|
+ if (result != Result.Success)
|
|
|
+ {
|
|
|
+ throw new InvalidOperationException($"打印失败: {result}");
|
|
|
+ }
|
|
|
+
|
|
|
+ OnAfterPrint(args);
|
|
|
+
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ catch (Exception ex)
|
|
|
+ {
|
|
|
+ OnPrintError(new PrintingErrorEventArgs($"打印标签 '{TemplateFolder}' 时出错", ex));
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ finally
|
|
|
+ {
|
|
|
+ if (format != null && !isCached)
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ format.Close(SaveOptions.DoNotSaveChanges);
|
|
|
+ }
|
|
|
+ catch { /* 忽略关闭错误 */ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private LabelFormatDocument GetTemplateDocument(string templateName)
|
|
|
+ {
|
|
|
+ if (string.IsNullOrEmpty(templateName))
|
|
|
+ throw new ArgumentNullException(nameof(templateName));
|
|
|
+
|
|
|
+ string templatePath = GetTemplatePath(templateName);
|
|
|
+
|
|
|
+ if (EnableTemplateCache && _cachedTemplates.ContainsKey(templatePath))
|
|
|
+ {
|
|
|
+ return _cachedTemplates[templatePath];
|
|
|
+ }
|
|
|
+
|
|
|
+ var document = _engine.Documents.Open(templatePath);
|
|
|
+ if (document == null)
|
|
|
+ throw new FileNotFoundException($"无法打开模板文件: {templatePath}");
|
|
|
+
|
|
|
+ if (EnableTemplateCache)
|
|
|
+ {
|
|
|
+ _cachedTemplates[templatePath] = document;
|
|
|
+ }
|
|
|
+
|
|
|
+ return document;
|
|
|
+ }
|
|
|
+
|
|
|
+ private string GetTemplatePath(string templateName)
|
|
|
+ {
|
|
|
+ if (!templateName.EndsWith(".btw", StringComparison.OrdinalIgnoreCase)) templateName += ".btw";
|
|
|
+
|
|
|
+ return Path.Combine(TemplateFolder, templateName);
|
|
|
+ }
|
|
|
+
|
|
|
+ protected virtual void OnBeforePrint(PrintingEventArgs e)
|
|
|
+ {
|
|
|
+ BeforePrint?.Invoke(this, e);
|
|
|
+ }
|
|
|
+ protected virtual void OnAfterPrint(PrintingEventArgs e)
|
|
|
+ {
|
|
|
+ AfterPrint?.Invoke(this, e);
|
|
|
+ }
|
|
|
+
|
|
|
+ protected virtual void OnPrintError(PrintingErrorEventArgs e)
|
|
|
+ {
|
|
|
+ PrintError?.Invoke(this, e);
|
|
|
+ }
|
|
|
+
|
|
|
+ public static string ShowPrinterSettingsDialog(IWin32Window owner, string printerName = null)
|
|
|
+ {
|
|
|
+ using (var dialog = new PrintDialog())
|
|
|
+ {
|
|
|
+ if (!string.IsNullOrEmpty(printerName))
|
|
|
+ dialog.PrinterSettings.PrinterName = printerName;
|
|
|
+
|
|
|
+ if (dialog.ShowDialog(owner) == DialogResult.OK)
|
|
|
+ {
|
|
|
+ return dialog.PrinterSettings.PrinterName;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ private bool _disposed = false;
|
|
|
+
|
|
|
+ public void Dispose()
|
|
|
+ {
|
|
|
+ Dispose(true);
|
|
|
+ GC.SuppressFinalize(this);
|
|
|
+ }
|
|
|
+
|
|
|
+ protected virtual void Dispose(bool disposing)
|
|
|
+ {
|
|
|
+ if (!_disposed)
|
|
|
+ {
|
|
|
+ if (disposing)
|
|
|
+ {
|
|
|
+ ClearCache();
|
|
|
+ StopEngine();
|
|
|
+
|
|
|
+ if (_engine != null)
|
|
|
+ {
|
|
|
+ _engine.Dispose();
|
|
|
+ _engine = null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ _disposed = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void ClearCache()
|
|
|
+ {
|
|
|
+ foreach (var document in _cachedTemplates.Values)
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ document.Close(SaveOptions.DoNotSaveChanges);
|
|
|
+ }
|
|
|
+ catch { /* 忽略关闭错误 */ }
|
|
|
+ }
|
|
|
+ _cachedTemplates.Clear();
|
|
|
+ }
|
|
|
+
|
|
|
+ private void StopEngine()
|
|
|
+ {
|
|
|
+ if (_engine != null && _engineStarted)
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ _engine.Stop();
|
|
|
+ _engineStarted = false;
|
|
|
+ }
|
|
|
+ catch { /* 忽略停止错误 */ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ ~LabelPrinter()
|
|
|
+ {
|
|
|
+ Dispose(false);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
}
|
|
|
}
|