using POSV.Printer;
using System;
using System.Collections.Generic;
using System.Drawing.Printing;
using System.Linq;
using System.Text;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Drawing;
using POSV.Designer;
using QRCoder;
using BarcodeLib;
using System.IO;
using NLog;
namespace POSV.Helper
{
public class WinPrint
{
public WinPrint()
{
}
static NLog.Logger logger = null;
public static Logger Logger
{
get
{
if (logger == null)
{
logger = NLog.LogManager.GetLogger("winPrint");
return logger;
}
else
{
return logger;
}
}
set
{
Logger = value;
}
}
#region 驱动名称
private static string printName = "Fax";
///
/// 驱动名称
///
public static string PrintName { get => printName; set => printName = value; }
#endregion
#region 驱动打印组件
///
/// 打印机对象
///
private static PrintDocument m_WinPrint = new PrintDocument();
#endregion
#region 打印任务队列
public static Queue m_PrintQueue = new Queue();
private static DesignerSurface skipsurface = null;
private static JArray skipjArray = null;
#endregion
#region 正在执队列
///
/// 正在执队列
///
private static bool m_Underway = false;
#endregion
public static bool Print(string printname, DesignerSurface surface, List args)
{
//加入队列
var _data = new
{
surface,
args
};
m_PrintQueue.Enqueue(JsonConvert.SerializeObject(_data));
Initialize(printname);
if (!m_Underway)
{
m_WinPrint.Print();
}
return true;
}
///
/// 初始化打印机组件
///
///
private static void Initialize(string printname)
{
m_WinPrint.PrinterSettings.PrinterName = printname;
if (!m_WinPrint.DocumentName.Equals("巨为餐饮小票"))
{
PrinterSettings printerSettings = new PrinterSettings();
m_WinPrint.DefaultPageSettings.Landscape = true;
m_WinPrint.PrinterSettings = printerSettings;
m_WinPrint.DocumentName = "巨为餐饮小票";
m_WinPrint.PrinterSettings.PrinterName = printname;
m_WinPrint.PrintPage += M_WinPrint_PrintPage;
m_WinPrint.EndPrint += M_WinPrint_EndPrint;
m_WinPrint.PrintController = new StandardPrintController();
}
}
#region 打印事件
private static void M_WinPrint_EndPrint(object sender, PrintEventArgs e)
{
//删除队列
m_PrintQueue.Dequeue();
//判断是否还有队列
if (m_PrintQueue.Count > 0)
{
System.Threading.Tasks.Task.Factory.StartNew(() =>
{
m_WinPrint.Print();
});
}
}
private static void M_WinPrint_PrintPage(object sender, PrintPageEventArgs e)
{
try
{
if (Logger == null)
{
Logger = NLog.LogManager.GetLogger("打印");
}
Logger.Info("-------------------------------------------进入打印-------------------------------------------");
m_Underway = true;
var _json = m_PrintQueue.Peek();
JObject jObject = JObject.Parse(_json);
DesignerSurface surface = JsonConvert.DeserializeObject(jObject["surface"].ToString());
List args = JsonConvert.DeserializeObject>(jObject["args"].ToString());
if (skipsurface != null)
{
surface = skipsurface;
}
Font _font = new System.Drawing.Font("宋体", 12);
SolidBrush _brush = new SolidBrush(Color.Black);
int _y = 1;
int _skip = 0;
int _charAmount = 32;
switch (surface.Width)
{
case 80:
_charAmount = 38;
break;
case 76:
_charAmount = 32;
break;
case 58:
_charAmount = 28;
break;
}
foreach (DesignerControls ctrls in surface.DesignerControls)
{
//换页标识
_skip++;
//if (e.PageSettings.PaperSize.Height < _y)
//{
// e.HasMorePages = true;
// skipsurface = new DesignerSurface();
// skipsurface.DesignerControls = surface.DesignerControls.Skip(_skip).ToList();
// return;
//}
//else
//{
// e.HasMorePages = false;
// skipsurface = null;
//}
switch (ctrls.ControlType)
{
case ControlType.None:
break;
case ControlType.单行模版:
{
var parameter = JSON.Deserialize(ctrls.Template);
string str = "";
#region list
var _data = args.FirstOrDefault(f => f.Key == parameter.Template.Item1.DataSourceKey);
if (_data == null)
{
continue;
}
if (_data.DataType == DataType.List)
{
JArray jArray = (JArray)JsonConvert.DeserializeObject(_data.Value.ToString());
try
{
foreach (var item in jArray)
{
JObject o = (JObject)item;
//字号
_font = ToFont(parameter.FontStyle);
//前缀
str += parameter.Template.Item1.Prefix;
//变量属性
str += o[parameter.Template.Item1.Var1.Value]?.ToString();
//中间内容
str += parameter.Template.Item1.Middle;
//变量属性
str += o[parameter.Template.Item1.Var2.Value]?.ToString();
//后缀内容
str += parameter.Template.Item1.Suffix;
var _Liststrs = PrintStrAlign(str, _charAmount, parameter.AlignStyle, parameter.LineStyle, _font);
foreach (var _itemStr in _Liststrs)
{
e.Graphics.DrawString(_itemStr, _font, _brush, 0, _y);
_y = _y + (int)_font.Size + 7;
str = "";
}
}
}
catch
{
}
continue;
}
#endregion
#region 单项
if (GetDataSource(args, parameter.Template.Item1.DataSourceKey, parameter.Template.Item1.Condition.Value).ToLower().Equals("false"))
{
continue;
}
//前缀
str += parameter.Template.Item1.Prefix;
//变量属性
str += GetDataSource(args, parameter.Template.Item1.DataSourceKey, parameter.Template.Item1.Var1.Value);
//中间内容
str += parameter.Template.Item1.Middle;
//变量属性
str += GetDataSource(args, parameter.Template.Item1.DataSourceKey, parameter.Template.Item1.Var2.Value);
//后缀内容
str += parameter.Template.Item1.Suffix;
//颜色
_brush = new SolidBrush(Color.Black);
//字号
_font = ToFont(parameter.FontStyle);
var _strs = PrintStrAlign(str, _charAmount, parameter.AlignStyle, parameter.LineStyle, _font);
foreach (var item in _strs)
{
e.Graphics.DrawString(item, _font, _brush, 0, _y);
_y = _y + (int)_font.Size + 7;
}
#endregion
break;
}
case ControlType.表格模版:
{
var template = JSON.Deserialize(ctrls.Template);
//字号
_font = ToFont(template.FontStyle);
var _str = "";
if (skipjArray == null)
{
foreach (var cols in template.Template.Columns)
{
var r = template.Template.RowTemplates[cols.Index];
if (cols.Index == 0)
{
_str += PrintStrAlign(cols.Name, cols.Length, AlignStyle.居左, LineStyle.不填充, new Font("宋体", 10))[0];
}
else
{
_str += PrintStrAlign(cols.Name, cols.Length, AlignStyle.居右, LineStyle.不填充, new Font("宋体", 10))[0];
}
}
e.Graphics.DrawString(PrintStrAlign("", _charAmount, AlignStyle.居右, LineStyle.中划线, new Font("宋体", 10))[0], new Font("宋体", 10), _brush, 0, _y);
_y = _y + (int)new Font("宋体", 10).Size;
e.Graphics.DrawString(_str, new Font("宋体", 10), _brush, 0, _y);
_y = _y + (int)_font.Size;
}
var _data = args.FirstOrDefault(f => f.Key == template.Template.DataSourceKey);
if (_data == null)
{
continue;
}
_str = "";
JArray jArray = null;
if (skipjArray == null)
{
jArray = (JArray)JsonConvert.DeserializeObject(_data.Value.ToString());
e.Graphics.DrawString(PrintStrAlign("", _charAmount, AlignStyle.居右, LineStyle.中划线, new Font("宋体", 10))[0], new Font("宋体", 10), _brush, 0, _y);
_y = _y + (int)new Font("宋体", 10).Size + 5;
}
else
{
jArray = skipjArray;
skipjArray = null;
}
int skip = 0;
foreach (var item in jArray)
{
skip++;
if (e.PageSettings.PaperSize.Height < _y)
{
e.HasMorePages = true;
skipsurface = new DesignerSurface();
skipsurface.DesignerControls = surface.DesignerControls.Skip(_skip - 1).ToList();
skipjArray = JArray.Parse(JSON.Serialize(jArray.Skip(skip)));
return;
}
else
{
e.HasMorePages = false;
skipsurface = null;
skipjArray = null;
}
List _aStr = new List();
foreach (var cols in template.Template.Columns)
{
var r = template.Template.RowTemplates[cols.Index];
JObject o = (JObject)item;
var data = o[r.Content].ToString();
if (data.Equals("合计"))
{
if (Global.Instance.Worker.TenantId.Equals("771188"))
{
_str = "";
_y = _y - ((int)_font.Size + 7);
break;
}
}
//索引等于0说明是项目名称
if (cols.Index == 0)
{
_aStr = PrintStrAlign(data, cols.Length, AlignStyle.居左, LineStyle.不填充, _font).ToList();
_str += _aStr[0];
}
else
{
_str += PrintStrAlign(data, cols.Length, AlignStyle.居右, LineStyle.不填充, _font)[0];
}
}
e.Graphics.DrawString(_str, _font, _brush, 0, _y);
_y = _y + (int)_font.Size + 7;
if (!Global.Instance.GlobalConfigBoolValue(ConfigConstant.PERIPHERAL_CASHIER_CASHIER_TICKET_BEYOND_NEWLINE, false))
//项目名超出继续打印
if (_aStr.Count > 1)
{
for (int i = 1; i < _aStr.Count; i++)
{
e.Graphics.DrawString(_aStr[i], _font, _brush, 0, _y);
_y = _y + (int)_font.Size + 7;
}
}
_str = "";
}
//e.Graphics.DrawString(PrintStrAlign("", _charAmount, AlignStyle.居右, LineStyle.中划线, new Font("宋体", 10))[0], new Font("宋体", 10), _brush, 0, _y = _y + (int)_font.Size + 7);
}
break;
case ControlType.两列模版:
{
var parameter = JSON.Deserialize(ctrls.Template);
var _left = parameter.Template.Item1;
var _right = parameter.Template.Item2;
//判断是否符合打印条件
var leftCondition = ParseCondition(_left.Condition, _left.DataSourceKey, args);
var rightCondition = ParseCondition(_right.Condition, _right.DataSourceKey, args);
if (!rightCondition || !leftCondition)
{
continue;
}
//字号
_font = ToFont(parameter.FontStyle);
var _leftWi = (_charAmount * _left.Percent / 100);
string _leftStr = "";
string _rightStr = "";
_leftStr += _left.Prefix;
_leftStr += GetDataSource(args, _left.DataSourceKey, _left.Var1.Value);
_leftStr += _left.Middle;
_leftStr += GetDataSource(args, _left.DataSourceKey, _left.Var2.Value);
_leftStr += _left.Suffix;
_rightStr += _right.Prefix;
_rightStr += GetDataSource(args, _right.DataSourceKey, _right.Var1.Value);
_rightStr += _right.Middle;
_rightStr += GetDataSource(args, _right.DataSourceKey, _right.Var2.Value);
_rightStr += _right.Suffix;
_leftStr = PrintStrAlign(_leftStr, (int)_leftWi, AlignStyle.居左, parameter.LineStyle, _font)[0];
_rightStr = PrintStrAlign(_rightStr, _charAmount - (int)_leftWi, AlignStyle.居右, parameter.LineStyle, _font)[0];
e.Graphics.DrawString(_leftStr + _rightStr, _font, _brush, 0, _y);
_y = _y + (int)_font.Size + 7;
}
break;
case ControlType.条码模版:
{
var parameter = JSON.Deserialize(ctrls.Template);
if (parameter.Template.Item1.ShowLabel)
{
continue;
}
BarCodeXTemplate template = parameter.Template.Item1;
//判断是否符合打印条件
var condition = ParseCondition(template.Condition, template.DataSourceKey, args);
if (!condition)
{
continue;
}
Barcode b = new Barcode();
b.IncludeLabel = parameter.Template.Item1.ShowLabel;
if (b.IncludeLabel)
{
b.Height = 20;
}
else
{
b.Height = 40;
}
b.Width = m_WinPrint.PrinterSettings.DefaultPageSettings.PaperSize.Width - 6;
b.Alignment = AlignmentPositions.CENTER;
var Encodestr = GetDataSource(args, parameter.Template.Item1.DataSourceKey, parameter.Template.Item1.Var1.Value);
if (string.IsNullOrEmpty(Encodestr))
{
return;
}
var _Image = b.Encode(TYPE.CODE128, Encodestr);
int x = m_WinPrint.PrinterSettings.DefaultPageSettings.PaperSize.Width;//打印机默认纸张大小
e.Graphics.DrawImage(_Image, 0, _y + 15);
_y = _y + _Image.Height + 10;
}
break;
case ControlType.二维码模版:
{
var parameter = JSON.Deserialize(ctrls.Template);
var _str = GetDataSource(args, parameter.Template.Item1.DataSourceKey, parameter.Template.Item1.Var1.Value);
var condition = ParseCondition(parameter.Template.Item1.Condition, parameter.Template.Item1.DataSourceKey, args);
if (!condition)
{
continue;
}
try
{
Bitmap bitmap = null;
QRCodeGenerator.ECCLevel eccLevel = QRCodeGenerator.ECCLevel.Q;
using (QRCodeGenerator qrGenerator = new QRCodeGenerator())
{
using (QRCodeData qrCodeData = qrGenerator.CreateQrCode(_str, eccLevel))
{
using (QRCode qrCode = new QRCode(qrCodeData))
{
bitmap = qrCode.GetGraphic(6, Color.Black, Color.White, false);
}
}
}
if (bitmap != null)
{
int x = m_WinPrint.PrinterSettings.DefaultPageSettings.PaperSize.Width;//打印机默认纸张大小
//bitmap.Width =
// e.Graphics.DrawString(_leftStr + _rightStr, _font, _brush, 0, _y = _y + (int)_font.Size + 5);
var _width = x - bitmap.Width;
e.Graphics.DrawImage(bitmap, (_width / 2) - 20, _y + 15);
_y = _y + bitmap.Height + 10;
}
}
catch (Exception)
{
}
}
break;
case ControlType.位图模版:
{
var parameter = JSON.Deserialize(ctrls.Template);
var condition = ParseCondition(parameter.Template.Item1.Condition, parameter.Template.Item1.Condition.Value, args);
if (!condition)
{
continue;
}
var _str = GetDataSource(args, parameter.Template.Item1.DataSourceKey, parameter.Template.Item1.Var1.Value);
if (!File.Exists(_str))
{
continue;
}
int x = m_WinPrint.PrinterSettings.DefaultPageSettings.PaperSize.Width;//打印机默认纸张大小
Image img = Image.FromFile(_str);
e.Graphics.DrawImage(img, 0, img.Height + 15);
_y = _y + img.Height + 15;
}
break;
default:
break;
}
}
m_Underway = false;
}
catch (Exception ex)
{
Logger.Info("-------------------------------------------" + ex.Message + "-------------------------------------------");
Logger.Error(ex);
m_Underway = false;
}
}
#endregion
private static bool ParseCondition(VariableItem var, string dataSourceKey, List args)
{
bool result = true;
//数据源参数,无论单行还是列表,数据源采用List方式,兼容单行选择集合数据源,重复行打印
var data = new List>();
//包含数据源参数,重置
if (args.Exists(x => x.Key == dataSourceKey))
{
//当前数据源
var vars = args.FindLast(x => x.Key == dataSourceKey);
//List集合数据
if (vars.DataType == DataType.List)
{
data = JSON.Deserialize>>(vars.Value.ToString());
foreach (var item in data)
{
if (item.Values.FirstOrDefault(f => f == "false") != null)
{
return false;
}
}
}
else
{
var row = JSON.Deserialize>(vars.Value.ToString());
data.Add(row);
}
}
//参数中是否包含条件参数,如果包含,取值,如果不包含,忽略,继续打印
if (var != null && data.Exists(x => x.ContainsKey(var.Value)))
{
//取第一个值
var _value = data[0][var.Value];
if ("false".Equals(_value.ToLower()))
{
result = false;
}
}
return result;
}
///
/// 字符对齐
///
/// 位置
/// 字符串
/// 字符总数
///
public static string[] PrintStrAlign(string str, int intLen, AlignStyle alignStyle, LineStyle lineStyle, Font font)
{
int fontSize = 0;
switch (font.Size)
{
case 12:
intLen = (int)(intLen / 1.1);
break;
case 14:
intLen = (int)(intLen / 1.4);
break;
case 16:
intLen = (int)(intLen / 1.5);
break;
default:
break;
}
int tempLen = 0;
int intStrLen = Encoding.Default.GetByteCount(str) + fontSize;
int intOriLen = str.Length;
List strs = new List();
switch (alignStyle)
{
case AlignStyle.居左:
{
if (intStrLen <= intLen)
{
tempLen = intLen - intStrLen + intOriLen;
str = str.PadRight(tempLen < 0 ? 0 : tempLen, Convert.ToChar(DesignerUtils.GetPaddingCharByLineStyle(lineStyle)));
}
else
{
//截断标识
int truncation = 0;
for (int i = 0; i < intStrLen / (intLen - fontSize); i++)
{
string _Bytestr = SubstringByte(str, (i * intLen) - truncation, intLen);
while (_Bytestr.Contains('?'))
{
if (_Bytestr.Substring(_Bytestr.Length - 1, 1).Equals("?"))
{
_Bytestr = SubstringByte(str, (i * intLen), intLen - truncation);
truncation++;
continue;
}
if (_Bytestr.Contains('?'))
{
_Bytestr = _Bytestr.Replace('?',' ');
}
}
strs.Add(_Bytestr);
}
strs.Add(str.Substring(strs.Sum(f => f.Length), str.Length - strs.Sum(f => f.Length)).PadRight(tempLen < 0 ? 0 : tempLen, Convert.ToChar(DesignerUtils.GetPaddingCharByLineStyle(lineStyle))));
if (intLen - Encoding.Default.GetByteCount(strs[0]) > 0)
{
strs[0] = strs[0].PadRight(strs[0].Length + (intLen - Encoding.Default.GetByteCount(strs[0])), ' ');
}
return strs.ToArray();
}
}
break;
case AlignStyle.居中:
{
var diff = intLen - intStrLen;
if (diff < 0)
{
//截断标识
int truncation = 0;
for (int i = 0; i < intStrLen / intLen; i++)
{
string _Bytestr = SubstringByte(str, (i * intLen) - truncation, intLen);
int q = 0;
while (_Bytestr.Contains('?'))
{
if (_Bytestr.Substring(_Bytestr.Length - 1, 1).Equals("?"))
{
_Bytestr = SubstringByte(str, (i * intLen), intLen - truncation);
truncation++;
continue;
}
if (_Bytestr.Contains('?'))
{
_Bytestr = _Bytestr.Replace('?', ' ');
}
// _Bytestr = SubstringByte(str, i * intLen, intLen - (Encoding.Default.GetByteCount(_Bytestr) - 1));
}
strs.Add(_Bytestr);
}
string endstr = str.Substring(strs.Sum(f => f.Length), str.Length - strs.Sum(f => f.Length));
strs.Add(string.Format("{0}{1}{2}", "".PadRight((intLen - Encoding.Default.GetByteCount(endstr)) / 2, Convert.ToChar(DesignerUtils.GetPaddingCharByLineStyle(lineStyle))), endstr, "".PadRight((intLen - Encoding.Default.GetByteCount(endstr)) / 2, Convert.ToChar(DesignerUtils.GetPaddingCharByLineStyle(lineStyle)))));
return strs.ToArray();
}
else
{
str = string.Format("{0}{1}{2}", "".PadRight((diff / 2), Convert.ToChar(DesignerUtils.GetPaddingCharByLineStyle(lineStyle))), str, "".PadRight(diff / 2, Convert.ToChar(DesignerUtils.GetPaddingCharByLineStyle(lineStyle))));
}
}
break;
case AlignStyle.居右:
{
if (intStrLen <= intLen)
{
tempLen = intLen - intStrLen + intOriLen;
str = str.PadLeft(tempLen < 0 ? 0 : tempLen, ToLineStyle(lineStyle));
}
else
{
//截断标识
int truncation = 0;
for (int i = 0; i < intStrLen / intLen; i++)
{
string _Bytestr = SubstringByte(str, (i * intLen) - truncation, intLen);
while (_Bytestr.Contains('?'))
{
if (_Bytestr.Substring(_Bytestr.Length - 1, 1).Equals("?"))
{
_Bytestr = SubstringByte(str, (i * intLen), intLen - truncation);
truncation++;
continue;
}
if (_Bytestr.Contains('?'))
{
_Bytestr = _Bytestr.Replace('?', ' ');
}
}
strs.Add(_Bytestr);
}
strs.Add(str.Substring(strs.Sum(f => f.Length), str.Length - strs.Sum(f => f.Length)).PadLeft(tempLen < 0 ? 0 : tempLen, ToLineStyle(lineStyle)));
return strs.ToArray();
}
}
break;
default:
break;
}
strs.Add(str);
return strs.ToArray();
}
///
/// 获取空字符串
///
///
public static string GetEmptyChar(int count)
{
string strTemp = string.Empty;
for (int i = 0; i < count; i++)
{
strTemp += " ";
}
return strTemp;
}
public static char ToLineStyle(LineStyle lineStyle)
{
switch (lineStyle)
{
case LineStyle.不填充:
return ' ';
case LineStyle.中划线:
return '-';
case LineStyle.双划线:
return '=';
case LineStyle.星号线:
return '*';
case LineStyle.井号线:
return '#';
case LineStyle.加号线:
return '+';
case LineStyle.下划线:
return '_';
default:
return ' ';
}
}
public static Font ToFont(Printer.FontStyle _fontStyle)
{
Font _font = new Font("宋体", 10);
switch (_fontStyle)
{
case Printer.FontStyle.正常字体:
_font = new Font("宋体", 10);
break;
case Printer.FontStyle.倍宽字体:
_font = new Font("宋体", 12);
break;
case Printer.FontStyle.倍高字体:
_font = new Font("宋体", 14);
break;
case Printer.FontStyle.倍宽倍高:
_font = new Font("宋体", 16);
break;
default:
break;
}
return _font;
}
public static string GetDataSource(List args, string DataSourceKey, string Value)
{
var _data = args.FirstOrDefault(f => f.Key == DataSourceKey);
if (_data == null)
{
return "";
}
try
{
var _Source = JSON.Deserialize>(_data.Value.ToString());
var _dataSource = _Source.FirstOrDefault(f => f.Key == Value);
if (_dataSource.Key == null)
{
return "";
}
return _dataSource.Value?.ToString();
}
catch
{
JArray jArray = (JArray)JsonConvert.DeserializeObject(_data.Value.ToString());
foreach (var item in jArray)
{
JObject o = (JObject)item;
return o[Value]?.ToString();
}
return "";
}
finally
{
}
}
public static string GetListDataSource(List args, string DataSourceKey, string Value)
{
var _data = args.FirstOrDefault(f => f.Key == DataSourceKey);
if (_data == null)
{
return "";
}
JArray jArray = JArray.Parse(_data.Value.ToString());
var _Source = JSON.Deserialize>(_data.Value.ToString());
var _dataSource = _Source.FirstOrDefault(f => f.Key == Value);
if (_dataSource.Key == null)
{
return "";
}
return _dataSource.Value.ToString();
}
private static Encoding _encoding = System.Text.Encoding.GetEncoding("GB2312");
//第一种方法
private static string SubstringByte(string text, int startIndex, int length)
{
byte[] bytes = _encoding.GetBytes(text);
return _encoding.GetString(bytes, startIndex, length);
}
/// 转全角的函数(SBC case)
///
///任意字符串
///全角字符串
///
///全角空格为12288,半角空格为32
///其他字符半角(33-126)与全角(65281-65374)的对应关系是:均相差65248
///
public static string ToSBC(string input)
{
// 半角转全角:
char[] c = input.ToCharArray();
for (int i = 0; i < c.Length; i++)
{
if (c[i] == 32)
{
c[i] = (char)12288;
continue;
}
if (c[i] < 127)
c[i] = (char)(c[i] + 65248);
}
return new String(c);
}
///
/// 转半角的函数(DBC case)
///
///任意字符串
///半角字符串
///
///全角空格为12288,半角空格为32
///其他字符半角(33-126)与全角(65281-65374)的对应关系是:均相差65248
///
public static string ToDBC(String input)
{
char[] c = input.ToCharArray();
for (int i = 0; i < c.Length; i++)
{
if (c[i] == 12288)
{
c[i] = (char)32;
continue;
}
if (c[i] > 65280 && c[i] < 65375)
c[i] = (char)(c[i] - 65248);
}
return new String(c);
}
}
}