如何在不使用 PrinterSettings 的情况下更改打印机的纸张尺寸?

How to change the paper size for a printer without using PrinterSettings?

我正在尝试编写将在特殊介质上打印的自定义标签打印机。

使用 600 的 DPI,打印介质尺寸大约为 2.00" x 0.244"。下面是 printLabel 函数,其传入值是位图标签。

您会看到我目前正在尝试制作自定义页面尺寸,但打印机打印出 12 个标签,但只有 1 个包含我需要的信息。

我一次只需要打印 1 个标签。 如果您需要更多信息或有任何疑问,请随时发表评论,但我不知道我在做什么需要做的。

我无法想象从 Windows 中的打印机设置页面获取页面大小的枚举集合。任何帮助将不胜感激。

PrintServer ps = null;

        if (Properties.Settings.Default.ShrinkLabelPrinter.Contains(@"\serverloc1") || Properties.Settings.Default.ShrinkLabelPrinter.Contains(@"\SERVERLOC1"))
            ps = new PrintServer(@"\serverloc1");
        else if (Properties.Settings.Default.ShrinkLabelPrinter.Contains(@"\serverloc2") || Properties.Settings.Default.ShrinkLabelPrinter.Contains(@"\SERVERLOC2"))
            ps = new PrintServer(@"\serverloc2");
        else
            ps = new PrintServer();

        System.Windows.Controls.PrintDialog pd = new System.Windows.Controls.PrintDialog();

        PrintQueue queue = ps.GetPrintQueue(@"\serverloc2\bbp33 (Copy 1)");

        List<string> lstPaperSizes = new List<string>();

        queue.CurrentJobSettings.CurrentPrintTicket.PageMediaSize = new PageMediaSize(PageMediaSizeName.Unknown, 150, 141);

        //queue.CurrentJobSettings.CurrentPrintTicket.PageMediaSize = ;

        pd.PrintQueue = queue;

        System.Drawing.Image img = label;

        //REMOVE IF LABELS ARE PORTRAIT FORMAT
        //img.RotateFlip(RotateFlipType.Rotate90FlipNone); 

        var ms = new MemoryStream();

        img.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
        ms.Position = 0;

        var bi = new BitmapImage();
        bi.BeginInit();
        bi.CacheOption = BitmapCacheOption.OnLoad;
        bi.StreamSource = ms;
        RenderOptions.SetBitmapScalingMode(bi, BitmapScalingMode.HighQuality);
        bi.EndInit();

        var vis = new DrawingVisual();
        var dc = vis.RenderOpen();

        Rect angle = new Rect
        {
            Width = Convert.ToInt32(Math.Round(bi.Width, 0)),
            Height = Convert.ToInt32(Math.Round(bi.Height, 0))
        };

        dc.DrawImage(bi, angle);
        dc.Close();
        img.Save(@"\temp\Label Creator\Resources\cable_label.png");
        pd.PrintVisual(vis, "Cable Label");

我建议你多调试,检查图片高度,检查你的页面大小是否合适等等。总之,可以做很多事情;这里有一些引起了我的注意:

  1. 您要打印的 PageMediaSize 宽 1.5625" (150px/96dpi),高 1.46875" (141px/96dpi)
  2. 而不是改变 queue.CurrentJobSettings...PageMediaSize 尝试做 pd.PrintTicket.PageMediaSize.PageMediaSize = new ...
  3. 也许PrintQueue.Commit()对你有用
  4. 设置一个断点并查看您的 PrintQueue 属性,如果我建议的没有任何效果,我有兴趣查看您的 PrintQueue.UserPrintTicket 的值(但是您可能不想要更改 UserPrintTicket).
  5. 确保您了解打印机本身及其硬件功能。它做横向和纵向吗?有它的SDK吗?
  6. 查看at/study PrintQueue.PrintCapabilities 然后断点+调试目标打印机的功能至少一次。那里有很多信息(比如兼容的媒体尺寸)。
  7. 记下您 img 的尺寸。如果您想要 2" x 0.244",您的媒体尺寸应该是 new PageMediaSize(PageMediaSizeName.Unknown, 192, 23.424);。您的图像应该具有相似的尺寸,并且不应超过这些尺寸。打印前请查看您的 pd.PrintableAreaHeight|Width
    • Windows 显示器默认为 96DPI。当您将视觉效果发送到打印机时,这是假定的。所以你通过 (size in inches / 96) = # of pixels you want to use with PageMediaSize 找到你的尺寸。转到标准打印机并通过 PrintCapabilities 查看 PageMediaSizeName.NorthAmericanLetter 的大小,您会看到高度为 816 像素 x 1056 像素。 816/96 = 8.5、1056/96 = 11 -- 8.5 x 11 介质。
  8. 您还可以在 XML 中下载打印机的功能。在 XML 中,您可能会发现打印机可以处理的其他功能(如介质尺寸),并且可能需要您在打印前进行设置。

我非常有信心研究和尝试我在粗体项目中指出的事情应该会在某个时候引导您找到解决方案。在我弄乱 System.Printing 命名空间的很多很多小时里,我发现每台打印机的行为都可能不同,微小的变化可能会产生最愚蠢的效果!

我会随时提供帮助,请在评论中 post!祝你好运。

编辑 1

不幸的是,我没有任何 custom/specialized 打印机可供测试,但我会尝试几种获得预定义尺寸的方法。

使用PrintQueue.PrintCapabilities:

这将打印出打印机报告的可用尺寸。由于 B33-126 是自定义尺寸,您可能会看到一堆带有尺寸的 PageMediaSizeName.Unknown,您必须在其中确定适合您的尺寸,然后在您的 PrintTicket 中使用相同的尺寸申请。

PrintQueue pq = GetYourPrintQueue();
PrintCapabilities pc = pq.GetPrintCapabilities();
ReadOnlyCollection<PageMediaSize> capableSizes = pc.PageMediaSizeCapability;
foreach(var pm in capableSizes) 
{ 
    Console.WriteLine(pm);
}
//Identify what PageMediaSize you need, and set your print ticket to use the exact same dimensions

使用PrintQueue.GetPrintCapabilitiesAsXml():

PrintQueue pq = GetYourPrintQueue();
MemoryStream pcXml = pq.GetPrintCapabilitiesAsXml();
Console.WriteLine(pcXml.ToString())
//At this point, set a breakpoint on Console.WriteLine and inspect the `pcXml` object to see if the XML contains custom print capabilities.  If so you'll have to identify which sizes/properties you need to make use of.

使用PrintQueue.UserPrintTicket:

UserPrintTicket是当前用户的默认打印机设置。所以,你可以做的是使用控制面板进入你的打印设备,右键单击你的目标打印机,然后转到 "Printing preferences" 并将你的 Page/Paper 尺寸更改为 B33-126 尺寸并单击 Apply/Okay 关闭 window.

现在做:

PrintQueue pq = GetYourPrintQueue();
var upt = pq.UserPrintTicket;
Console.WriteLine(upt);

并在 Console.WriteLine 上设置断点并检查 upt。这将显示 PrintTicket 中的当前设置,这些设置与我们在上述步骤中 set/applied 的设置相匹配。您应该能够 pd.PrintTicket = upt 并在那时打印。​​

使用 PrintDialog:

您可以使用 PrintDialog.ShowDialog() 设置打印机设置,然后添加一个断点以查看它们是什么并将相同的设置应用于您的解决方案。

PrintDialog pd = new PrintDialog();
pd.ShowDialog();
//Set a breakpoint on the code show below this comment.  At this point your print dialog is shown and you can select a printer.  Select the target printer and click "Preferences." When shown, set whatever settings you might normally use to print labels.  Then click "Apply," then click "OK."  
Console.WriteLine(pd.PrintTicket);

当调试器运行最后一行代码时,您刚刚通过首选项页面应用到打印机的设置将显示在 pd.PrintTicket 中。您可以采用这些设置并在您的应用程序中对 PrintTicket 使用相同的设置。

最后一个注意事项是在关闭后查看 PrintDialog 的属性。它有你的高度和宽度(可以找到边距)。您要确保要打印的图像适合这些尺寸。请记住,您可以使用 PrintDialog.CopyCount.

打印倍数