【问题标题】:Why my bar code image does not fit the specified paper size in bar code printer settings when I try to print it?当我尝试打印时,为什么我的条形码图像不适合条形码打印机设置中指定的纸张尺寸?
【发布时间】:2020-08-04 11:54:23
【问题描述】:

我正在使用 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

【问题讨论】:

  • 确保您安装了供应商的最新驱动程序。您是连接到打印机 IP 还是使用打印驱动程序?您应该始终使用初始化打印机并配置选项的打印驱动程序。
  • @jdweng 因为我已经安装了打印驱动程序,我只需从可用打印机列表中选择我的打印机,然后在设置适当的纸张尺寸后,我点击打印对话框上的确定。
  • 驱动程序是否有适合纸张大小的选项。我会创建一个面板,然后将图片框和文本放入面板并打印面板。
  • 据我所知,没有。

标签: c# winforms barcode picturebox barcode-printing


【解决方案1】:

所以这就是问题所在。打印机的 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。这是 PDF 放大了 300%:

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

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

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

【讨论】:

  • 谢谢你详细的回答安迪。你完全配得上 50 的声望。如果我遇到任何问题,我会再次尝试与您联系。
  • @Naser.Sadeghi -- 不客气!希望你一切顺利。如果您遇到任何颠簸,我总是在您身边。祝你好运!
  • 很遗憾,我仍然无法打印此条码。质量问题已解决,但当我尝试手动设置宽度和高度时,我仍然无法以任何给定的纸张尺寸打印整张图片,但它不起作用,而是列出打印机的全部可用尺寸并选择一个。结果还是不正确。
  • 当我打印到 pdf 时没问题,但在真正的打印机上我仍然有问题。
  • @Naser.Sadeghi -- 您可能需要更改条形码的大小。不要使用50,而是尝试使用30...同时调整字体的Em 大小。
猜你喜欢
  • 2020-02-17
  • 1970-01-01
  • 1970-01-01
  • 2013-07-22
  • 2019-08-18
  • 2018-12-13
  • 2022-02-01
  • 1970-01-01
  • 2012-06-13
相关资源
最近更新 更多