macosdelphiprintingfiremonkey

Trying to implment MacOS PMGetPageFormatPaper in FireMonkey


Trying to get (and eventually set) the paper selection at runtime using Delphi FireMonkey for MacOS. I've substituted what I think are the correct variables and functions into a routine that I have used successfully to get the paperrect and the pagerect, as well as the orientation. But this code gives me an access error when I release FPrintInfo. I'm sure it's something simple. Hoping a kind programmer can help.

function getPaperName: string;
var
  FPrintInfo: NSPrintInfo;
  paper: integer;
begin
  result:='';
  FPrintInfo := TNSPrintInfo.Wrap(TNSPrintInfo.OCClass.sharedPrintInfo);
  FPrintInfo.retain;
  PMGetPageFormatPaper(FPrintInfo.PMPageFormat, @paper);
  FPrintInfo.release;
  result:=IntToStr(paper);
end;

Possible hint... Here is the PMGetPageFormatPaper function in the Apple documentation:

func PMGetPageFormatPaper(
    _ format: PMPageFormat,
    _ paper: UnsafeMutablePointer<PMPaper?>
) -> OSStatus

I notice that the pointer variable <PMPaper?> includes a question mark, while the corresponding variables in the functions that I am using successfully do not. I imagine that is telling me something important, but I don't know what.

Thanks for any help.

Scott


Solution

  • The second parameter for the call to PMGetPageFormatPaper is of type PPMPaper, not an Integer. It is essentially a pointer to a handle that can be used to call the PMPaperXXX functions e.g. PMPaperGetName, PMPaperGetHeight, PMPaperGetWidth etc. The whole process is a bit more complicated, however this might do what you want:

    uses
      Macapi.PrintCore, Macapi.AppKit, Macapi.CoreFoundation, Macapi.CocoaTypes, Macapi.Helpers, Macapi.Foundation;
    
    function getPaperName: string;
    var
      LPrintInfo: NSPrintInfo;
      LPaper: PMPaper;
      LName: CFStringRef;
      LPrinter: PMPrinter;
      LSession: PMPrintSession;
    begin
      Result := '';
      if PMCreateSession(@LSession) = 0 then
      begin
        if PMSessionGetCurrentPrinter(LSession, @LPrinter) = 0 then
        begin
          LPrintInfo := TNSPrintInfo.Wrap(TNSPrintInfo.OCClass.sharedPrintInfo);
          if (PMGetPageFormatPaper(LPrintInfo.PMPageFormat, @LPaper) = 0) then
          begin
            if PMPaperCreateLocalizedName(LPaper, LPrinter, @LName) = 0 then
            try
              Result := NSStrToStr(TNSString.Wrap(LName));
            finally
              CFRelease(LName);
            end;
          end;
        end;
      end;
    end;
    

    Ultimately, the PMPaperCreateLocalizedName method needs to be called to get the paper name. PMPaperGetName appears to have been removed from later macOS SDKs without Apple updating their documentation, though they do recommend using PMPaperCreateLocalizedName anyway

    This method requires a handle to the printer (of type PMPrinter), which is obtained using PMSessionGetCurrentPrinter, and this requires a PMPrintSession, so this is obtained using PMCreateSession.

    The paperName parameter of PMPaperCreateLocalizedName is a pointer to a CFStringRef, which can just be wrapped as an NSString using TNSString.Wrapand converted into a string using NSStrToStr

    Since the method has the word Create in it, the convention in Apple APIs is that if something is created, it needs to be released, hence the call to CFRelease