Printing metafile that includes clipping to PDF comes out blank

201 Views Asked by At

I have an application that prepares a drawing to an Enhanced Metafile. To produce output, this metafile is copied to a canvas; either a Paintbox (in custom preview window on screen) or a printer canvas.

All works as expected when displaying in the custom preview or printing to a physical (!) printer (any paper format). However, when printing to PDF (I have tried NitroPDF, Adobe Acrobat and Microsoft Print to PDF) whatever was drawn within a clipping region shows up as blank as shown in the screen clips below (left is the expected output, right is the PDF output).

enter image description here

Note that the clipping is applied by column (all headers and columns shown are derived from a TBaseColumn). The columns header and border are drawn after the clipping region is released:

procedure TBaseColumn.Draw(ACanvas: TMetafileCanvas);
var
  P: array [0 .. 1] of TPoint;
  LClipRegion: HRGN;
begin

  // Set temp reference to MetafileCanvas
  FCanvas := ACanvas;

  // Set clipping area
  P[0] := FDrawingRect.TopLeft;
  P[1] := FDrawingRect.BottomRight;
  LPtoDP(FCanvas.Handle, P, 2);
  LClipRegion := CreateRectRgn(P[0].X, P[0].Y, P[1].X, P[1].Y);
  SelectClipRgn(FCanvas.Handle, LClipRegion);
  try
    DrawContent; // Protected method so we can override in derived columns
  finally
    // Reset clipping
    SelectClipRgn(FCanvas.Handle, HRGN(nil));
    DeleteObject(LClipRegion);
  end;
  DrawHeader;
  DrawColumnBorder;
  FCanvas := nil;
end;

Note that I have added the LPtoDP conversion based on this StackOverflow question but unfortunately it seems to make no difference.

There is one other "strange behavior" I have noticed. In the print method of my custom preview, I have several options to draw the metafile to the printer canvas (pmPlayMetaFile is default).

procedure TMyPrintPreview.Print(const APrintTitle: string; const APrintMethod: TSD_PrintMethod);
var
  LMetaFileRect: TRect;
  LBmp: Vcl.Graphics.TBitmap;
begin
  if not assigned(FMetaFile) then
    exit;

  if APrintTitle = '' then
    Printer.Title := 'Document_' + FormatDateTime('yymmdd_hhnn', Now)
  else
    Printer.Title := APrintTitle;

  Printer.BeginDoc;
  try
    LMetaFileRect := FPreviewInfo.GetPrinterMetaFileRect(FMetaFileScaling);
    case APrintMethod of
      pmPlayMetaFile:
        begin
          PlayEnhMetaFile(Printer.Canvas.Handle, FMetaFile.Handle, LMetaFileRect);
        end;
      pmDirect:
        begin
          Printer.Canvas.StretchDraw(LMetaFileRect, FMetaFile);
        end;
      pmBitmap:
        begin
          LBmp := Vcl.Graphics.TBitmap.Create;
          try
            LBmp.Width := LMetaFileRect.Width;
            LBmp.Height := LMetaFileRect.Height;
            LBmp.Canvas.StretchDraw(Rect(0, 0, LBmp.Width, LBmp.Height), FMetaFile);
            Printer.Canvas.StretchDraw(LMetaFileRect, LBmp);
          finally
            LBmp.Free;
          end;
        end;
    end;
    Printer.EndDoc;
  except
    on E: Exception do
    begin
      Printer.Abort;
      raise;
    end;
  end;
end;

There is no notable difference using any of these methods. However (and this completely puzzles me), if use a modal dialog to allow the user to select the print method (see below) then the output to PDF is as expected.

procedure TfrmMain.btnPrintClick(Sender: TObject);
var
  dlgMethod: TdlgPrintMethod;
  LMethod: TSD_PrintMethod;
begin
  if ParamStr(1) = '/p' then
  begin
    // DEBUG PRINTING. Show modal dialog to select "print method"....
    dlgMethod := TdlgPrintMethod.Create(self);
    try
      if dlgMethod.ShowModal = mrOK then
      begin
        LMethod := TSD_PrintMethod(dlgMethod.PrintMethod);
        MyPrintPreview.Print(FFileName, LMethod);
      end;
    finally
      dlgMethod.Free;
    end;
  end
  else
    // NORMAL PRINTING. No dialog, use default method (pmPlayMetaFile)
    MyPrintPreview.Print(FFileName);
end;

I am totally puzzled as to why this only happens when printing to PDF and all other output (screen and printer) works just fine. It must be related to some "setting" but I cannot seem to find it. I have invested a lot of time in this application and printing to PDF is a must (users must be able to share drawings with user that do not have the application). Rebuilding from scratch (i.e. not using metafile) is there what I am trying to avoid. So any suggestion or direction as to what I may try to fix this is very welcome. Thanks!

0

There are 0 best solutions below