为什么当我尝试打印时,我的条码图像不适合条码打印机设置中指定的纸张尺寸?

问题描述 投票:0回答:1

我正在使用 Zen Barcode Rendering Framework 在 C# Windows 窗体应用程序中创建条形码。我有两个文本框(一个用于条形码本身,另一个用于我希望打印在条形码标签上的相关文本)。同样,我将生成的条形码图像加载到图片框中并尝试打印该图像,但每次按下打印按钮时,结果都不合适(有时打印机打印白色的空标签,有时条形码打印不完整。有趣的是,我不得不说,为了让条形码出现在标签上,即使它看起来不完整,我必须选择非常大的纸张尺寸)。这是我的代码:

我的生成条形码按钮的点击事件的代码:

private void Button1_Click(object sender, EventArgs e)
{
        string barcode = textBox1.Text;

        Zen.Barcode.Code128BarcodeDraw brcd = Zen.Barcode.BarcodeDrawFactory.Code128WithChecksum;
        var barcodeImage = brcd.Draw(barcode, 50);

        int resultImageWidth;
        if(barcodeImage.Width >= textBox2.Text.Length*8)
        {
            resultImageWidth = barcodeImage.Width;
        }
        else
        {
            resultImageWidth = textBox2.Text.Length*8;
        }

        var resultImage = new Bitmap(resultImageWidth, barcodeImage.Height + 60); // 20 is bottom padding, adjust to your text

        using (var graphics = Graphics.FromImage(resultImage))
        using (var font = new Font("IranYekan", 10))
        using (var brush = new SolidBrush(Color.Black))
        using (var format = new StringFormat()
        {
            Alignment = StringAlignment.Center, // Also, horizontally centered text, as in your example of the expected output
            LineAlignment = StringAlignment.Far
        })
        {
            graphics.Clear(Color.White);
            graphics.DrawImage(barcodeImage, (resultImageWidth - barcodeImage.Width)/2, 0);
            graphics.DrawString(textBox1.Text, font, brush, resultImage.Width / 2, resultImage.Height-30, format);
            graphics.DrawString(textBox2.Text, font, brush, resultImage.Width / 2, resultImage.Height, format);
        }

        pictureBox1.Image = resultImage;

}

我的打印按钮的点击事件的代码:

private void Button2_Click(object sender, EventArgs e)
{
    PrintDialog pd = new PrintDialog();
    PrintDocument doc = new PrintDocument();
    doc.PrintPage += Doc_PrintPage;
    pd.Document = doc;
    if (pd.ShowDialog() == DialogResult.OK)
    {
        doc.Print();
    }
}

还有我的 Doc_PrintPage() 函数:

private void Doc_PrintPage(object sender, PrintPageEventArgs e)
{
    Bitmap bm = new Bitmap(pictureBox1.Width, pictureBox1.Height);
    pictureBox1.DrawToBitmap(bm, new Rectangle(0, 0, pictureBox1.Width, pictureBox1.Height));
    e.Graphics.DrawImage(bm, 0, 0);
    bm.Dispose();
}

我的主要目标是在出现打印对话框时选择的纸张边界内完整打印条形码及其相关文本。

您可以在下图中查看我的应用程序的 UI:

这是我的打印结果,您会看到它们质量不佳,并且图像每次都不正确。我用的是兄弟QL-700

c# winforms barcode picturebox barcode-printing
1个回答
5
投票

所以这就是问题所在。打印机的 DPI(每英寸点数)比屏幕高得多。您的屏幕通常具有 96-150 DPI,而大多数打印机为 600 DPI 或更高。您正在尝试将以 96 DPI 创建的图像渲染到使用 600+ DPI 进行渲染的设备上。它看起来就像您在图像上显示的那样。

打印机上下文返回的

Graphics

 对象与为在屏幕上显示信息而创建的 
Graphics
 对象非常不同。因此,您需要做的是渲染到 
Graphics
 对象,而不是渲染到您为屏幕显示创建的 
Image

因此我们将重新排列您的代码:

private void BtnScreen_Click(object sender, EventArgs e) { // if there was a previous image in the picture box, dispose of it now PicCode.Image?.Dispose(); // create a 24 bit image that is the size of your picture box var img = new Bitmap(PicCode.Width, PicCode.Height, PixelFormat.Format24bppRgb); // wrap it in a graphics object using(var g = Graphics.FromImage(img)) { // send that graphics object to the rendering code RenderBarcodeInfoToGraphics(g, TxtCode.Text, TxtInfo.Text, new Rectangle(0, 0, PicCode.Width, PicCode.Height)); } // set the new image in the picture box PicCode.Image = img; } private void BtnPrinter_Click(object sender, EventArgs e) { // create a document that will call the same rendering code but // this time pass the graphics object the system created for that device var doc = new PrintDocument(); doc.PrintPage += (s, printArgs) => { // send that graphics object to the rendering code using the size // of the media defined in the print arguments RenderBarcodeInfoToGraphics(printArgs.Graphics, TxtCode.Text, TxtInfo.Text, printArgs.PageBounds); }; // save yourself some paper and render to a print-preview first using (var printPrvDlg = new PrintPreviewDialog { Document = doc }) { printPrvDlg.ShowDialog(); } // finally show the print dialog so the user can select a printer // and a paper size (along with other miscellaneous settings) using (var pd = new PrintDialog { Document = doc }) { if (pd.ShowDialog() == DialogResult.OK) { doc.Print(); } } } /// <summary> /// This method will draw the contents of the barcode parameters to any /// graphics object you pass in. /// </summary> /// <param name="g">The graphics object to render to</param> /// <param name="code">The barcode value</param> /// <param name="info">The information to place under the bar code</param> /// <param name="rect">The rectangle in which the design is bound to</param> private static void RenderBarcodeInfoToGraphics( Graphics g, string code, string info, Rectangle rect) { // Constants to make numbers a little less magical const int barcodeHeight = 50; const int marginTop = 20; const string codeFontFamilyName = "Courier New"; const int codeFontEmSize = 10; const int marginCodeFromCode = 10; const string infoFontFamilyName = "Arial"; const int infoFontEmSize = 12; const int marginInfoFromCode = 10; // white background g.Clear(Color.White); // We want to make sure that when it draws, the renderer doesn't compensate // for images scaling larger by blurring the image. This will leave your // bars crisp and clean no matter how high the DPI is g.InterpolationMode = InterpolationMode.NearestNeighbor; // generate barcode using (var img = BarcodeDrawFactory.Code128WithChecksum.Draw(code, barcodeHeight)) { // daw the barcode image g.DrawImage(img, new Point(rect.X + (rect.Width / 2 - img.Width / 2), rect.Y + marginTop)); } // now draw the code under the bar code using(var br = new SolidBrush(Color.Black)) { // calculate starting position of text from the top var yPos = rect.Y + marginTop + barcodeHeight + marginCodeFromCode; // align text to top center of area var sf = new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Near }; // draw the code, saving the height of the code text var codeTextHeight = 0; using (var font = new Font(codeFontFamilyName, codeFontEmSize, FontStyle.Regular)) { codeTextHeight = (int)Math.Round(g.MeasureString(code, font).Height); g.DrawString(code, font, br, new Rectangle(rect.X, yPos, rect.Width, 0), sf); } // draw the info below the code using (var font = new Font(infoFontFamilyName, infoFontEmSize, FontStyle.Regular)) { g.DrawString(info, font, br, new Rectangle(rect.X, yPos + codeTextHeight + marginInfoFromCode, rect.Width, 0), sf); } } }
那么,应用程序中的样子是这样的:

此应用程序还具有打印预览功能。我将打印预览缩放至 150%,以显示一切都保持清晰:

我没有打印机。它已经用完了黄色,因此拒绝打印(这是为什么?)所以我打印为 PDF。这是放大了 300% 的 PDF:

如您所见,在打印到 600 DPI 设备时以及在该设备上放大 300% 时,条形码保持清晰干净。

请记住,StackOverflow 在显示图像时会缩放图像,因此它们可能看起来很模糊。单击图像以原始比例查看它。

如果您有任何疑问,请告诉我。

© www.soinside.com 2019 - 2024. All rights reserved.