using System; using System.Drawing; using System.Drawing.Printing; using System.Text; using Newtonsoft.Json; namespace RecticelPrintService { public class LabelPrinter { private PrintData _labelData; // Label dimensions in millimeters (80x110mm) private const float LABEL_WIDTH_MM = 80f; private const float LABEL_HEIGHT_MM = 110f; // Convert mm to hundredths of an inch (used by .NET printing) private float MmToHundredthsOfInch(float mm) { return mm * 3.937f; // 1mm = 0.03937 inches, * 100 for hundredths } public bool PrintLabel(string printerName, string jsonData) { try { // Parse JSON data _labelData = JsonConvert.DeserializeObject(jsonData); if (_labelData == null) { Console.WriteLine("Failed to parse JSON data"); return false; } // Set up print document PrintDocument printDoc = new PrintDocument(); printDoc.PrinterSettings.PrinterName = printerName; // Check if printer exists if (!printDoc.PrinterSettings.IsValid) { Console.WriteLine($"Printer '{printerName}' not found or not available"); Console.WriteLine("Available printers:"); foreach (string printer in PrinterSettings.InstalledPrinters) { Console.WriteLine($" - {printer}"); } return false; } // Set paper size for 80x110mm labels PaperSize labelSize = new PaperSize("Label 80x110mm", (int)MmToHundredthsOfInch(LABEL_WIDTH_MM), (int)MmToHundredthsOfInch(LABEL_HEIGHT_MM)); printDoc.DefaultPageSettings.PaperSize = labelSize; printDoc.DefaultPageSettings.Margins = new Margins(0, 0, 0, 0); // Set print event handler printDoc.PrintPage += PrintDoc_PrintPage; // Print the document printDoc.Print(); return true; } catch (Exception ex) { Console.WriteLine($"Error printing label: {ex.Message}"); return false; } } private void PrintDoc_PrintPage(object sender, PrintPageEventArgs e) { try { Graphics g = e.Graphics; // Define fonts Font companyFont = new Font("Arial", 10, FontStyle.Bold); Font headerFont = new Font("Arial", 8, FontStyle.Bold); Font dataFont = new Font("Arial", 9, FontStyle.Bold); Font labelFont = new Font("Arial", 7); Font barcodeFont = new Font("Courier New", 6, FontStyle.Bold); // Define brushes and pens Brush textBrush = Brushes.Black; Pen borderPen = new Pen(Color.Black, 2); Pen dividerPen = new Pen(Color.Gray, 1); // Calculate positions (in pixels, 300 DPI assumed) float dpiX = e.Graphics.DpiX; float dpiY = e.Graphics.DpiY; // Convert mm to pixels float labelWidth = (LABEL_WIDTH_MM / 25.4f) * dpiX; float labelHeight = (LABEL_HEIGHT_MM / 25.4f) * dpiY; // Content area (similar to your HTML preview) float contentX = (3f / 25.4f) * dpiX; // 3mm margin float contentY = (15f / 25.4f) * dpiY; // 15mm from bottom float contentWidth = (60f / 25.4f) * dpiX; // 60mm width float contentHeight = (85f / 25.4f) * dpiY; // 85mm height // Draw main content border g.DrawRectangle(borderPen, contentX, contentY, contentWidth, contentHeight); // Calculate row height float rowHeight = contentHeight / 10f; // 9 rows + spacing float currentY = contentY; // Row 1: Company Header string companyText = "INNOFA RROMANIA SRL"; SizeF companySize = g.MeasureString(companyText, companyFont); float companyX = contentX + (contentWidth - companySize.Width) / 2; g.DrawString(companyText, companyFont, textBrush, companyX, currentY + rowHeight/3); currentY += rowHeight; // Horizontal divider after company g.DrawLine(dividerPen, contentX, currentY, contentX + contentWidth, currentY); // Row 2: Customer Name string customerName = _labelData.CustomerName ?? "N/A"; SizeF customerSize = g.MeasureString(customerName, headerFont); float customerX = contentX + (contentWidth - customerSize.Width) / 2; g.DrawString(customerName, headerFont, textBrush, customerX, currentY + rowHeight/3); currentY += rowHeight; // Horizontal divider after customer g.DrawLine(dividerPen, contentX, currentY, contentX + contentWidth, currentY); // Vertical divider (40% from left) float verticalDividerX = contentX + contentWidth * 0.4f; g.DrawLine(dividerPen, verticalDividerX, currentY, verticalDividerX, contentY + contentHeight); // Row 3: Quantity g.DrawString("Quantity ordered", labelFont, textBrush, contentX + 5, currentY + rowHeight/4); string quantity = _labelData.Cantitate.ToString(); SizeF qtySize = g.MeasureString(quantity, dataFont); float qtyX = verticalDividerX + (contentWidth * 0.6f - qtySize.Width) / 2; g.DrawString(quantity, dataFont, textBrush, qtyX, currentY + rowHeight/4); currentY += rowHeight; // Horizontal divider g.DrawLine(dividerPen, contentX, currentY, contentX + contentWidth, currentY); // Row 4: Customer Order g.DrawString("Customer order", labelFont, textBrush, contentX + 5, currentY + rowHeight/4); string customerOrder = $"{_labelData.ComAchizClient}-{_labelData.NrLinieComClient}"; if (string.IsNullOrEmpty(_labelData.ComAchizClient)) customerOrder = "N/A"; SizeF orderSize = g.MeasureString(customerOrder, dataFont); float orderX = verticalDividerX + (contentWidth * 0.6f - orderSize.Width) / 2; g.DrawString(customerOrder, dataFont, textBrush, orderX, currentY + rowHeight/4); currentY += rowHeight; // Horizontal divider g.DrawLine(dividerPen, contentX, currentY, contentX + contentWidth, currentY); // Row 5: Delivery Date g.DrawString("Delivery date", labelFont, textBrush, contentX + 5, currentY + rowHeight/4); string deliveryDate = _labelData.DataLivrare ?? "N/A"; if (!string.IsNullOrEmpty(deliveryDate) && deliveryDate != "N/A") { try { DateTime dt = DateTime.Parse(deliveryDate); deliveryDate = dt.ToString("dd/MM/yyyy"); } catch { } } SizeF dateSize = g.MeasureString(deliveryDate, dataFont); float dateX = verticalDividerX + (contentWidth * 0.6f - dateSize.Width) / 2; g.DrawString(deliveryDate, dataFont, textBrush, dateX, currentY + rowHeight/4); currentY += rowHeight; // Horizontal divider g.DrawLine(dividerPen, contentX, currentY, contentX + contentWidth, currentY); // Row 6: Description (double height) g.DrawString("Description", labelFont, textBrush, contentX + 5, currentY + rowHeight/4); string description = _labelData.DescrComProd ?? "N/A"; // Word wrap description if needed RectangleF descRect = new RectangleF(verticalDividerX + 5, currentY + 5, contentWidth * 0.6f - 10, rowHeight * 2 - 10); g.DrawString(description, dataFont, textBrush, descRect); currentY += rowHeight * 2; // Horizontal divider g.DrawLine(dividerPen, contentX, currentY, contentX + contentWidth, currentY); // Row 7: Size g.DrawString("Size", labelFont, textBrush, contentX + 5, currentY + rowHeight/4); string size = _labelData.Dimensiune ?? "N/A"; SizeF sizeSize = g.MeasureString(size, dataFont); float sizeX = verticalDividerX + (contentWidth * 0.6f - sizeSize.Width) / 2; g.DrawString(size, dataFont, textBrush, sizeX, currentY + rowHeight/4); currentY += rowHeight; // Horizontal divider g.DrawLine(dividerPen, contentX, currentY, contentX + contentWidth, currentY); // Row 8: Article Code g.DrawString("Article Code", labelFont, textBrush, contentX + 5, currentY + rowHeight/4); string articleCode = _labelData.CustomerArticleNumber ?? "N/A"; SizeF artSize = g.MeasureString(articleCode, dataFont); float artX = verticalDividerX + (contentWidth * 0.6f - artSize.Width) / 2; g.DrawString(articleCode, dataFont, textBrush, artX, currentY + rowHeight/4); currentY += rowHeight; // Horizontal divider g.DrawLine(dividerPen, contentX, currentY, contentX + contentWidth, currentY); // Row 9: Prod Order g.DrawString("Prod Order", labelFont, textBrush, contentX + 5, currentY + rowHeight/4); string prodOrder = _labelData.SequentialNumber ?? $"{_labelData.ComandaProductie}-{_labelData.Cantitate}"; SizeF prodSize = g.MeasureString(prodOrder, dataFont); float prodX = verticalDividerX + (contentWidth * 0.6f - prodSize.Width) / 2; g.DrawString(prodOrder, dataFont, textBrush, prodX, currentY + rowHeight/4); // Bottom barcode area float barcodeY = contentY + contentHeight + (5f / 25.4f) * dpiY; // 5mm below content float barcodeWidth = contentWidth; float barcodeHeight = (10f / 25.4f) * dpiY; // 10mm height // Draw barcode representation (simple lines) DrawSimpleBarcode(g, contentX, barcodeY, barcodeWidth, barcodeHeight, prodOrder); // Barcode text SizeF barcodeTextSize = g.MeasureString(prodOrder, barcodeFont); float barcodeTextX = contentX + (contentWidth - barcodeTextSize.Width) / 2; g.DrawString(prodOrder, barcodeFont, textBrush, barcodeTextX, barcodeY + barcodeHeight + 5); // Vertical barcode on the right side float verticalBarcodeX = contentX + contentWidth + (5f / 25.4f) * dpiX; // 5mm to the right float verticalBarcodeWidth = (8f / 25.4f) * dpiX; // 8mm width DrawSimpleVerticalBarcode(g, verticalBarcodeX, contentY + rowHeight * 2, verticalBarcodeWidth, contentHeight - rowHeight * 2, customerOrder); // Dispose resources companyFont.Dispose(); headerFont.Dispose(); dataFont.Dispose(); labelFont.Dispose(); barcodeFont.Dispose(); borderPen.Dispose(); dividerPen.Dispose(); } catch (Exception ex) { Console.WriteLine($"Error in PrintPage event: {ex.Message}"); } } private void DrawSimpleBarcode(Graphics g, float x, float y, float width, float height, string data) { // Simple barcode representation using alternating lines float barWidth = 2f; bool drawBar = true; for (float currentX = x; currentX < x + width; currentX += barWidth) { if (drawBar) { g.FillRectangle(Brushes.Black, currentX, y, barWidth, height * 0.8f); } drawBar = !drawBar; } } private void DrawSimpleVerticalBarcode(Graphics g, float x, float y, float width, float height, string data) { // Simple vertical barcode representation float barHeight = 2f; bool drawBar = true; for (float currentY = y; currentY < y + height; currentY += barHeight) { if (drawBar) { g.FillRectangle(Brushes.Black, x, currentY, width * 0.8f, barHeight); } drawBar = !drawBar; } } } }