C# 印表機(PrintDocument的解析度 設定) ~ 像素(Pixels)/英吋(Inches)/毫米(Millimeters) 轉換函數
C# 印表機(PrintDocument的解析度 設定) ~ 像素(Pixels)/英吋(Inches)/毫米(Millimeters) 轉換函數
資料來源:
https://blog.csdn.net/wangnaisheng/article/details/139059374
https://learn.microsoft.com/zh-tw/dotnet/api/system.drawing.graphicsunit?view=windowsdesktop-9.0&viewFallbackFrom=dotnet-plat-ext-8.0
https://radio-idea.blogspot.com/2016/09/c-printdocument.html#google_vignette
GITHUB: https://github.com/jash-git/CS_PrintDocument_ThermalPrinter
01.相關實驗取得參數規則備份
C# PrintDocument 文字大小 -> 圖形實際量測大小 紀錄 e.Graphics.PageUnit = GraphicsUnit.Pixel; "Arial", 12, FontStyle.Bold -> Width = Height = 4mm "Arial", 10 -> Width = Height = 3nm y+=X -> Height(X) = 字高+1 (mm)
02.Code:(三台熱敏印表機測試 確定印出來的圖片/文字大小都是可控且一致)
using System;
using System.Drawing;
using System.Drawing.Printing;
using ZXing;
using ZXing.Windows.Compatibility;// NET5之後CS3050(Error CS0305 Using generic type 'BarcodeWriter ' requires type 1) 解決方法 : https://github.com/micjahn/ZXing.Net/issues/458
using ZXing.Common;
using ZXing.QrCode;
using System.Runtime.Intrinsics.Arm;
class Program
{
//---
//DPI 相關函數
//https://blog.csdn.net/wangnaisheng/article/details/139059374
public static void GetScreenDpi(out float DpiX, out float DpiY)//系統DPI
{
//Dots Per Inch(每英寸點數): 意思是指每一英吋長度中,取樣或可顯示或輸出點的數目
using (Graphics g = Graphics.FromHwnd(IntPtr.Zero))
{
DpiX = g.DpiX;
DpiY = g.DpiY;
}
}
public static float PixelsToInches(int pixels, float dpi)//像素 -> 英吋
{
return pixels / dpi;
}
public static float PixelsToMillimeters(int pixels, float dpi)//像素 -> 毫米
{
float inches = PixelsToInches(pixels, dpi);
return inches * 25.4f;
}
public static int MillimetersToPixels(float millimeters, float dpi)//毫米 -> 像素
{
float inches = millimeters / 25.4f;
return (int)(inches * dpi + 0.5f); // 使用0.5f进行四舍五入处理
}
//---DPI 相關函數
static Bitmap QrCode(String StrData)
{
// Create a BarcodeWriter instance
var barcodeWriter = new BarcodeWriter();//ZXing.Windows.Compatibility
barcodeWriter.Format = BarcodeFormat.QR_CODE;
barcodeWriter.Options.Hints.Add(EncodeHintType.CHARACTER_SET, "UTF-8"); //編碼字元utf-8
barcodeWriter.Options.Hints.Add(EncodeHintType.ERROR_CORRECTION, ZXing.QrCode.Internal.ErrorCorrectionLevel.H); //錯誤校正等級
barcodeWriter.Options.Height = 300;
barcodeWriter.Options.Width = 300;
barcodeWriter.Options.Margin = 0; //外邊距
// Generate the barcode as a Bitmap
Bitmap barcodeBitmap = barcodeWriter.Write(StrData);
// Save the barcode as a BMP file
barcodeBitmap.Save("qrcode.bmp", System.Drawing.Imaging.ImageFormat.Bmp);
return barcodeBitmap;
}
static Bitmap BarCode(String StrData)
{
// Create a BarcodeWriter instance
var barcodeWriter = new BarcodeWriter();//ZXing.Windows.Compatibility
barcodeWriter.Format = BarcodeFormat.CODE_128;
barcodeWriter.Options.Height = 100;
barcodeWriter.Options.Width = 300;
// Generate the barcode as a Bitmap
Bitmap barcodeBitmap = barcodeWriter.Write(StrData);
// Save the barcode as a BMP file
barcodeBitmap.Save("barcode.bmp", System.Drawing.Imaging.ImageFormat.Bmp);
return barcodeBitmap;
}
static void Main()
{
float SysDpiX, SysDpiY;
GetScreenDpi(out SysDpiX,out SysDpiY);
Bitmap bmp1 = QrCode("相關網站: https://github.com/micjahn/ZXing.Net/issues/458");
Bitmap bmp2 = BarCode("1234567890");
string targetPrinterName = "POS-80C";//"POS80D";//"80mm Series Printer";//"80mm_TCPMode"; // 替換成你實際的熱感印表機名稱
PrintDocument printDoc = new PrintDocument();
// 指定印表機
bool found = false;
foreach (string printer in PrinterSettings.InstalledPrinters)
{
if (printer.Equals(targetPrinterName, StringComparison.OrdinalIgnoreCase))
{
printDoc.PrinterSettings.PrinterName = printer;
found = true;
break;
}
}
if (!found)
{
Console.WriteLine($"找不到印表機:{targetPrinterName}");
return;
}
// 設定邊界為 0
printDoc.DefaultPageSettings.Margins = new Margins(0, 0, 0, 0);
// 加入列印事件
printDoc.PrintPage += (sender, e) =>
{
/*
//https://learn.microsoft.com/zh-tw/dotnet/api/system.drawing.graphicsunit?view=windowsdesktop-9.0&viewFallbackFrom=dotnet-plat-ext-8.0
Display 1
指定顯示裝置的測量單位。 一般來說,視訊顯示會使用像素,而印表機會使用 1/100 英吋。
Document 5
指定文件單位 (1/300 英吋) 做為測量單位。
Inch 4
指定英吋做為測量單位。
Millimeter 6
指定公釐做為測量單位。
Pixel 2
指定裝置像素做為測量單位。
Point 3
指定印表機的點 (1/72 英吋) 做為測量單位。
World 0
指定全局座標系統的單位做為測量單位。
*/
//e.Graphics.PageUnit = GraphicsUnit.Document;//300DPI ~ https://radio-idea.blogspot.com/2016/09/c-printdocument.html#google_vignette
e.Graphics.PageUnit = GraphicsUnit.Pixel;//解析度 ~ https://radio-idea.blogspot.com/2016/09/c-printdocument.html#google_vignette
Graphics g = e.Graphics;//抓取印表機畫布
/*
Bitmap BitmapBuf = new Bitmap((int)(80 * 3.937),5000);//建立BMP記憶體空間
Graphics g = Graphics.FromImage(BitmapBuf);//從BMP記憶體自建畫布 ~ https://stackoverflow.com/questions/10868623/converting-print-page-graphics-to-bitmap-c-sharp
g.Clear(Color.White);//畫布指定底色
//*/
Font font = new Font("Arial", 10);
Brush brush = Brushes.Black;
int y = 10;
/*
熱敏印表機實驗取得數據:
78mm : 78-3*2(設備邊界) = 72mm
56mm : 56-3*2(設備邊界) = 50mm
大小紙張可列印之差: (72-50)=22mm
*/
g.DrawString("文字致中測試", new Font("Arial", 12, FontStyle.Bold), brush, MillimetersToPixels(((78-12) / 2 - (4*3)), 203), y);//紙張寬度((78-12)/2)-3個字寬(4*3)
y += MillimetersToPixels(5, 203);//5=字高+1
g.DrawString("文字致中測試", font, brush, MillimetersToPixels(((78 - 12) / 2 - (3 * 3)), 203), y);//紙張寬度((78-12)/2)-3個字寬(3*3)
y += MillimetersToPixels(4, 203);//4=字高+1
// 列印標題
g.DrawString("收據列印示範", new Font("Arial", 12, FontStyle.Bold), brush, 0, y);
y += MillimetersToPixels(5, 203);//5=字高+1
// 繪製文字
g.DrawString("商品:測試產品", font, brush, 10, y);
y += MillimetersToPixels(4, 203);//4=字高+1
g.DrawString("數量:2", font, brush, 10, y);
y += MillimetersToPixels(4, 203);//4=字高+1
g.DrawString("總價:NT$200", font, brush, 10, y);
y += MillimetersToPixels(10, 203);
// 繪製方形區塊(模擬框)
Pen pen = new Pen(Color.Black, 1);
Rectangle rect = new Rectangle(0, y, MillimetersToPixels(68, 203), MillimetersToPixels(68, 203));
g.DrawRectangle(pen, rect);
g.DrawString("感謝您的購買!", font, brush, 10, y + 15);
Rectangle printArea2 = new Rectangle(5, y+MillimetersToPixels(70, 203), MillimetersToPixels(30 * 1.1f, 203), MillimetersToPixels(15 * 1.1f, 203));//new RectangleF(0, 0, e.PageBounds.Width, e.PageBounds.Height);//
g.DrawImage(bmp2, printArea2);
Rectangle printArea1 = new Rectangle(5, y+MillimetersToPixels(70, 203) + MillimetersToPixels(17 * 1.1f, 203), MillimetersToPixels(40*1.1f, 203), MillimetersToPixels(40 * 1.1f, 203));//new RectangleF(0, 0, e.PageBounds.Width, e.PageBounds.Height);//
g.DrawImage(bmp1, printArea1);
//---
//測試大圖
/*
y = 410 + 100 + 200 + 20;
for (int i=0;i<100;i++)
{
g.DrawString(i+":", font, brush, 10, y);
y += 20;
}
*/
//---測試大圖
Font font01 = new Font("Arial", 1);
g.DrawString(" .", font01, brush, 10, 1500);//故意拉長紙張 (500-300-y)/3.937=25mm
/*
BitmapBuf.Save("printer.bmp", System.Drawing.Imaging.ImageFormat.Bmp);
e.Graphics.DrawImage(BitmapBuf, 0, 0);//由於從BMP記憶體自建畫布,所以列印時就要從BMP記憶體進行
//*/
e.HasMorePages = false;
};
// 自訂紙張大小:寬 80mm,高 100mm(1mm ≈ 3.937 尺寸單位)
int width = (int)(80 * 3.937); // 約 315
int height = 5000;//(int)(100 * 3.937); // 約 394
PaperSize paperSize = new PaperSize("Custom_80mm", width, height);
printDoc.DefaultPageSettings.PaperSize = paperSize;
try
{
printDoc.Print();
Console.WriteLine("列印工作已送出!");
}
catch (Exception ex)
{
Console.WriteLine("列印失敗:" + ex.Message);
}
}
}
One thought on “C# 印表機(PrintDocument的解析度 設定) ~ 像素(Pixels)/英吋(Inches)/毫米(Millimeters) 轉換函數”
線上工具(OnLine Tool) : https://www.presspdf.com/zh-Hant/dpi-pixel-mm-converting
=======================
libreoffice calc (Excel) 公式
像素 -> 英吋
(pixels/dpi)
像素 -> 毫米
=ROUND((pixel/dpi)*25.4,3)
毫米 -> 像素
=ROUND(((mm/25.4)*dpi+0.5),0)
———————–
libreoffice calc 四舍五入 取整數
=ROUND(數字, 0)
其中,數字 是你要四舍五入的數字,0 表示小數點後保留 0 位數,即取整數。