Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I'm trying to code a custom label printer that will print on a special media.

The print media size is roughly 2.00" by 0.244" using a DPI of 600. Below is the printLabel function with a passed in value of Bitmap Label.

You'll see that I currently am trying to make a custom page size, but the printer prints out 12 labels and only 1 has the info I need.

I need to print only 1 label at a time. If you need more information, or have questions, feel free to comment, but I'm lost as to what I need to do.

I can't imagine that getting an enumerated collect of Page Sizes from the printer settings page in Windows. Any help would be greatly appreciated.

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");
like image 946
Steven Avatar asked Oct 21 '25 06:10

Steven


1 Answers

I would advise you to do more debugging, checking heights of images, checking if your page sizes are right, etc. In short, it could be a lot of things; here are a few that caught my eye:

  1. The PageMediaSize you're printing to is 1.5625" (150px/96dpi) wide, 1.46875" (141px/96dpi) tall
  2. Instead of changing queue.CurrentJobSettings...PageMediaSize try to do pd.PrintTicket.PageMediaSize.PageMediaSize = new ...
  3. Maybe PrintQueue.Commit() is of use to you
  4. Set a breakpoint and look at your PrintQueue properties, if nothing is working that I suggest, I'd be interested in seeing the values of your PrintQueue.UserPrintTicket (however you likely will not want to change UserPrintTicket).
  5. Make sure you understand the printer in itself and its hardware capabilities. Does it do landscape and portrait? Is there an SDK for it?
  6. Look at/study the PrintQueue.PrintCapabilities then breakpoint+debug the targeted printer's capabilities at least once. There is a lot of information in there (like compatible media sizes).
  7. Note your img's dimensions. Your media size should be new PageMediaSize(PageMediaSizeName.Unknown, 192, 23.424); if you want 2" x 0.244". Your image should have similar dimensions and shouldn't go over those. Look at your pd.PrintableAreaHeight|Width before printing.
    • Windows displays are default 96DPI. That is assumed when you send visuals to the printer. So you find your dimensions by doing (size in inches / 96) = # of pixels you want to use with PageMediaSize. Go to a standard printer and look--via PrintCapabilities--at the size of PageMediaSizeName.NorthAmericanLetter and you'll see the height is 816 pixels x 1056 pixels. 816/96 = 8.5, 1056/96 = 11 -- 8.5 x 11 media.
  8. You are also able to download the capabilities of a printer in XML. In the XML you might find additional capabilities (like media sizes) that the printer can handle, and that might require you to set before printing.

I'm pretty confident researching and trying things I point out in the bold items should lead you to a solution at some point. In the many, many hours that I have messing with System.Printing namespace, I've found every printer can behave differently and small changes can have the most asinine effects!

I'll be around to help, just post in the comments! Good luck.

Edit 1

Unfortunately I don't have any custom/specialized printers to test with but I'll take a stab at a couple ways you can get predefined sizes.

Using PrintQueue.PrintCapabilities:

This will print out the capable sizes the printer reports. Since B33-126 is a custom size, you might see a bunch of PageMediaSizeName.Unknowns with dimensions, where you will have to identify the dimension that suites you, then use those same dimensions with the PrintTicket in your application.

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

Using 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.

Using PrintQueue.UserPrintTicket:

UserPrintTicket is the current user's default printer settings. So, what you can do is go into your printing devices using the control panel, right click on your target printer, then go to "Printing preferences" and change your Page/Paper size to the B33-126 size and click Apply/Okay to close the window.

Now do:

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

And set your breakpoint on Console.WriteLine and inspect upt. This will show the current settings in the PrintTicket that match the settings we set/applied in the steps above. You should be able to do pd.PrintTicket = upt and print at that point.

Using PrintDialog:

You could use PrintDialog.ShowDialog() to set printer settings, then add a breakpoint to view what they were and apply the same settings to your solution.

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);

When the debugger hits the last line of code, the settings you just applied to your printer through the preferences page will show up in pd.PrintTicket. You can take these settings and use the same settings for the PrintTicket in your application.

One last note is look at the properties of PrintDialog after you close it. It has your heights and widths (margins can be found) in there. You want to make sure the image you're trying to print is going to fit in those dimensions. Remember you can print multiples using PrintDialog.CopyCount.

like image 100
Kcvin Avatar answered Oct 23 '25 20:10

Kcvin