C#打印标签后出现像素化问题,求解决方案
解决打印标签像素化问题
打印前标签显示正常,但打印完成后出现像素化现象,需求标签尺寸为100×70mm,相关代码如下:
原打印事件代码
private void Doc_PrintPage(object sender, PrintPageEventArgs e) { Bitmap bm = new Bitmap(pictureBox1.Width, pictureBox1.Height, System.Drawing.Imaging.PixelFormat.Format32bppRgb); /* float tgtWidthMM = 100; float tgtHeightMM = 70; float tgtWidthInches = tgtWidthMM / 25.4f; float tgtHeightInches = tgtHeightMM / 25.4f; float srcWidthPx = bm.Width; float srcHeightPx = bm.Height; float dpiX = srcWidthPx / tgtWidthInches; float dpiY = srcHeightPx / tgtHeightInches; bm.SetResolution(dpiX, dpiY); */ pictureBox1.DrawToBitmap(bm, pictureBox1.ClientRectangle); e.Graphics.DrawImage((Image)bm, 0, 0); bm.Dispose(); }
原绘制标签代码
private void pictureBox1_Paint(object sender, PaintEventArgs e) { using (Font myFont = new Font("Arial", 14)) { BarcodeWriter writer = new BarcodeWriter() { Format = BarcodeFormat.CODE_128 }; e.Graphics.DrawString("Miłego czytania!", myFont, Brushes.Black, new Point(118, 25)); e.Graphics.DrawImage(writer.Write(serialNumber), new Point(70, 65)); e.Graphics.DrawString("text", myFont, Brushes.Black, new Point(70, 175)); } using (Font myFont = new Font("Arial", 9)) { e.Graphics.DrawString("text", myFont, Brushes.Black, new Point(137, 205)); e.Graphics.DrawString("text", myFont, Brushes.Black, new Point(140, 220)); } }
问题原因
当前代码直接将pictureBox的屏幕分辨率图像绘制到打印画布上,而打印设备的DPI通常远高于屏幕DPI(比如300DPI),低分辨率图像被拉伸后就会出现像素化。另外注释掉的DPI设置逻辑方向错误,应该基于打印设备的DPI创建足够分辨率的图像,而非用屏幕尺寸反推DPI。
解决方案
修改代码,直接基于打印设备DPI创建高分辨率Bitmap,并在该Bitmap上绘制标签内容,确保打印清晰度:
修改后的打印事件代码
private void Doc_PrintPage(object sender, PrintPageEventArgs e) { // 目标标签尺寸(毫米) float tgtWidthMM = 100; float tgtHeightMM = 70; // 转换为英寸(1英寸=25.4毫米) float tgtWidthInches = tgtWidthMM / 25.4f; float tgtHeightInches = tgtHeightMM / 25.4f; // 获取打印设备的DPI float printDpiX = e.Graphics.DpiX; float printDpiY = e.Graphics.DpiY; // 计算Bitmap的像素尺寸(匹配打印DPI) int bmWidth = (int)Math.Round(tgtWidthInches * printDpiX); int bmHeight = (int)Math.Round(tgtHeightInches * printDpiY); // 创建高分辨率Bitmap using (Bitmap bm = new Bitmap(bmWidth, bmHeight, System.Drawing.Imaging.PixelFormat.Format32bppRgb)) { bm.SetResolution(printDpiX, printDpiY); using (Graphics g = Graphics.FromImage(bm)) { // 绘制标签内容 DrawLabelContent(g, printDpiX, printDpiY); } // 将Bitmap按实际尺寸绘制到打印画布,避免拉伸 e.Graphics.DrawImage(bm, 0, 0, tgtWidthInches, tgtHeightInches); } }
提取的标签内容绘制方法
将原Paint事件的绘制逻辑提取为独立方法,适配打印DPI:
private void DrawLabelContent(Graphics g, float dpiX, float dpiY) { // 屏幕DPI默认96,将原屏幕坐标转换为打印DPI下的坐标 float scaleX = dpiX / 96f; float scaleY = dpiY / 96f; // 开启高质量渲染,提升文字和图形清晰度 g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit; using (Font myFont = new Font("Arial", 14)) { BarcodeWriter writer = new BarcodeWriter() { Format = BarcodeFormat.CODE_128 }; Image barcodeImage = writer.Write(serialNumber); // 应用坐标缩放 g.DrawString("Miłego czytania!", myFont, Brushes.Black, new PointF(118 * scaleX, 25 * scaleY)); g.DrawImage(barcodeImage, new PointF(70 * scaleX, 65 * scaleY)); g.DrawString("text", myFont, Brushes.Black, new PointF(70 * scaleX, 175 * scaleY)); barcodeImage.Dispose(); } using (Font myFont = new Font("Arial", 9)) { g.DrawString("text", myFont, Brushes.Black, new PointF(137 * scaleX, 205 * scaleY)); g.DrawString("text", myFont, Brushes.Black, new PointF(140 * scaleX, 220 * scaleY)); } }
修改说明
- 放弃依赖
pictureBox的低分辨率图像,直接基于打印设备DPI创建高分辨率Bitmap,从根源解决像素化问题。 - 提取绘制逻辑到独立方法,既复用代码,又能灵活适配屏幕显示和打印两种场景。
- 开启高质量渲染设置,优化文字和条形码的打印效果。
- 通过坐标缩放,确保打印内容的布局和原设计完全一致。
内容的提问来源于stack exchange,提问作者Jacek Szczupak
相关产品推荐
相关产品推荐

