2

I am writing a new WPF application that creates some visual elements and then trying to print them on a Poloroid printer. I am successfully printing using the System.Printing classes in WPF as follows:

Dim Pd As PrintDialog = New PrintDialog()
Dim Ps = New LocalPrintServer()
Dim PrintQueue = New PrintQueue(Ps, "Poloroid Printer")
Pd.PrintQueue = PrintQueue
Pd.PrintVisual(Me.Grid1, "Print Job 1")  'this prints out perfectly

The problem is that the poloroid printer has an SDK that you can use to write to the Magstrip on the back of the card. I have a working example using the PrintPageEventArgs in System.Drawing.Printing but I cannot find any close matches for the WPF world. Here is that code:

Private Sub PrintPage(ByVal sender as Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs)
  '...

  ' Obtain the device context for this printer
  deviceContext = e.Graphics.GetHdc().ToInt32()

  '... device context is used in SDK to write to magstrip

  e.Graphics.ReleaseHdc(New IntPtr(deviceContext))
End Sub

So, my question is:

How can I print my existing markup (XAML) using System.Drawing.Printing

OR

Are there events in the System.Printing to talk to the SDK and getting the Int32 deviceContext?

and I tried to RenderTargetBitmap class to render the visual in WPF to bitmap and convert the bitmap to System.Drawing.Bitmap

RenderTargetBitmap bitmapSource;
...
bitmapSource.Render(visual);
...
using(MemoryStream outStream = new MemoryStream())
{
 BitmapEncoder enc = new BmpBitmapEncoder();
 enc.Frames.Add(BitmapFrame.Create(bitmapSource));
 enc.Save(outStream);
 System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(outStream);
 ...
}

But printing was not clear and perfect.

Dhanya
  • 21
  • 3

2 Answers2

0

I recently answered a similar question that can be found here: https://stackoverflow.com/a/43373398/3393832. That question and answer relate more to magnetic encoding (on ID cards) than image printing, but I will try to give some insight about that here, as well.

For the card images, I actually set up two Grids within my XAML: an outer grid that houses everything (buttons, labels, combo-boxes, the inner grid) and an inner grid that is essentially the image I want to apply, in full, on the card itself. In code, I take a "snapshot" of the inner grid after all elements have been added/updated and simply send that image into the Print Job.

To continue with my previous post (the link above), I add the image print AFTER the magnetic encoding step for the first side of the card (PageCount == 0).

Below is some code that I use to get the Bitmap "snapshot" of the Grid/Full Image without any loss of clarity/resolution or any pixelation:

RenderTargetBitmap rtb = new RenderTargetBitmap(gridWidth, gridHeight, 210, 210, PixelFormats.Pbgra32);

rtb.Render(YourGrid);

// If you need to Crop Anything Out
CroppedBitmap crop = new CroppedBitmap();

crop = new CroppedBitmap(rtb, new Int32Rect(0, 0, gridWidth, gridHeight));

Bitmap bmpToPrint = BitmapSourceToBitmap(crop);

// Helper Method
public Bitmap BitmapSourceToBitmap(BitmapSource bs)
{
    Bitmap bitmap;

    using (MemoryStream ms = new MemoryStream())
    {
        BitmapEncoder enc = new BmpBitmapEncoder();
        enc.Frames.Add(BitmapFrame.Create(bs));
        enc.Save(ms);
        bitmap = new Bitmap(ms);
    }

    return bitmap;
}

For the Magnetic Encoding, I use e.Graphics.DrawString and for the Image (you guessed it) e.Graphics.DrawImage. Simply call DrawString prior to DrawImage and your Printer Driver should pick up the encode prior to the image within the PrintPage method (again, please refer to the link above for more details into the Print method I am using. This method is also not tied to a printer make or model and is not reliant on any SDK).

Though generic and in need of your particular implementation details, I hope this post helps guide you to a solution that fits your particular needs. Please don't hesitate to ask if you have any follow-up questions or need more detail into the particular elements of the print job itself.

Community
  • 1
  • 1
CodeBreaker
  • 387
  • 4
  • 12
0

Try this

      Rect bounds = VisualTreeHelper.GetDescendantBounds(FrontCanvas);
      double dpiX =e.Graphics.DpiX  , dpiY=e.Graphics.DpiY ;
      RenderTargetBitmap rtb = new RenderTargetBitmap((int)(bounds.Width * dpiX  / 96.0),
                                                      (int)(bounds.Height * dpiY   / 96.0),
                                                      dpiX,
                                                      dpiY,
                                                      PixelFormats.Pbgra32);

      DrawingVisual dv = new DrawingVisual();
      using (DrawingContext ctx = dv.RenderOpen())
      {
          VisualBrush vb = new VisualBrush(FrontCanvas);
          ctx.DrawRectangle(vb, null, new Rect(new Point(), bounds.Size));
      }

      rtb.Render(dv);

      //System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(rtb);
      //e.Graphics.DrawImage(rtb, 0, 0);

      using (MemoryStream outStream = new MemoryStream())
      {
          // Use png encoder for  data
          BitmapEncoder encoder = new PngBitmapEncoder();

          // push the rendered bitmap to it
          encoder.Frames.Add(BitmapFrame.Create(rtb));
          encoder.Save(outStream);
          System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(outStream);
          e.Graphics.DrawImage(bitmap, 0, 0);

      }
Dhanya Ullas
  • 149
  • 3
  • 10