Так вот в чем проблема. У принтеров DPI (точек на дюйм) намного выше, чем у вашего экрана. Ваш экран обычно имеет 96–150 точек на дюйм, тогда как большинство принтеров имеют разрешение 600 точек на дюйм или выше. Вы пытаетесь визуализировать изображение, созданное с разрешением 96 точек на дюйм, на устройстве, которое использует для визуализации более 600 точек на дюйм. Он будет выглядеть примерно так, как то, что вы показываете на своих изображениях.
Объект 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);
}
}
}
Итак, в приложении это выглядит так:
This application also has print-preview. I scaled the print-preview to 150% to show that everything is staying crisp:
I don't have a printer. It's out of Yellow, so it refuses to print (why is that?) so instead I printed to PDF. This is that PDF scaled up 300%:
pdf печать
Как видите, штрих-код остается четким и чистым при печати на устройстве с разрешением 600 точек на дюйм, а также при увеличении на этом устройстве 300%.
Помните, что StackOverflow масштабирует изображения при их отображении, поэтому они могут выглядеть размытыми. Нажмите на изображение, чтобы увидеть его в исходном масштабе.
Если у вас есть вопросы, дайте мне знать.