Acrobat DC Image Form Fields

PDF-XChange Editor SDK for Developers

Moderators: TrackerSupp-Daniel, Tracker Support, Paul - Tracker Supp, Vasyl-Tracker Dev Team, Chris - Tracker Supp, Sean - Tracker, Ivan - Tracker Software, Tracker Supp-Stefan

Forum rules
DO NOT post your license/serial key, or your activation code - these forums, and all posts within, are public and we will be forced to immediately deactivate your license.

When experiencing some errors, use the IAUX_Inst::FormatHRESULT method to see their description and include it in your post along with the error code.
Post Reply
dkeith2
User
Posts: 46
Joined: Mon Aug 14, 2017 8:28 pm

Acrobat DC Image Form Fields

Post by dkeith2 »

In Acrobat DC (2018.009.20050) you can add an image 'field' to an acrobat form.

In PDF Exchange Editor SDK and the PDF Exchange Editor this image field type is interpreted as a button field (FFT_PushButton).

I need to drop an image into this image field, similar to what I did in this post: https://www.pdf-xchange.com/forum3 ... 14#p119614

I've been trying to typecast the field as an IUIX_Button, but of course this isn't working:

Code: Select all

  if Doc.CoreDoc.HasAcroForm and (Doc.CoreDoc.Pages.Get_Item(Pred(APageNumber),iPage) = S_OK) then
  begin
    acro := Doc.CoreDoc.AcroForm;
    cnt := acro.FieldsCount;
    for i := 0 to Pred(cnt) do
    begin
      fld := acro.Field[i];
      if (Pos(WideString('sig~image'),fld.FullName) > 0) then
        if (fld.type_ = FFT_PushButton) then
        begin
          btn := IUIX_Button(fld);
I've searched, but have not found an example where anyone else is doing this. Does this capability exist within the program?

Should I perhaps treat the field as an annotation? What's the process for interfacing with the image field properly?

Thanks.
Sasha - Tracker Dev Team
User
Posts: 5522
Joined: Fri Nov 21, 2014 8:27 am
Contact:

Re: Acrobat DC Image Form Fields

Post by Sasha - Tracker Dev Team »

Hello dkeith2,

Please check this sample
https://gist.github.com/Polaringu/f661a5af12c8fbf7e7fd
Basically what you will have to do is to change the widget's icon to the one that you need.
Note that the IPXC level is being used in the sample, so if you want to modify an opened document then the appropriate events need to be fired for the UI update.
I've been trying to typecast the field as an IUIX_Button, but of course this isn't working:
Of course it won't work, because the IUIX_Button is an element of a dialog for example, not a form field button.

Cheers,
Alex
Subscribe at:
https://www.youtube.com/channel/UC-TwAMNi1haxJ1FX3LvB4CQ
dkeith2
User
Posts: 46
Joined: Mon Aug 14, 2017 8:28 pm

Re: Acrobat DC Image Form Fields

Post by dkeith2 »

I'm working on an implementation of this now.

One thing that I noticed in the example that you provided is that the 'image' is coming from an IPXC_Page... since my image is coming from a bitmap stream, and with the other situation I supplied the image from an IIXC_Page, how do I use a bitmap stream in this case?

Thanks.
Sasha - Tracker Dev Team
User
Posts: 5522
Joined: Fri Nov 21, 2014 8:27 am
Contact:

Re: Acrobat DC Image Form Fields

Post by Sasha - Tracker Dev Team »

Hello dkeith2,

As you may also noticed that you will have to create a XForm and fill it with needed data to set it as an icon. The IPXC_Document has a CreateNewXForm method. Having that, you should create a new content creator, create an IPXC_Image from the IIXC_Page by using the AddImageFromIXCPage method, then place the IPXC_Image in the ContentCreator. After all of this, you should detach the content of the content creator into the xForm's content:

Code: Select all

 xForm.SetContent(cc.Detach());
After that you can place that XForm as an icon.

Cheers,
Alex
Subscribe at:
https://www.youtube.com/channel/UC-TwAMNi1haxJ1FX3LvB4CQ
dkeith2
User
Posts: 46
Joined: Mon Aug 14, 2017 8:28 pm

Re: Acrobat DC Image Form Fields

Post by dkeith2 »

Here's an attempt to make this work:

Code: Select all

function PlaceSignature(AnImageStream: TBytesStream; AFormField: WideString; APageNumber: Integer): Boolean;
var
  annot: IPXC_Annotation;
  iPage: IPXC_Page;
  acro: IPXC_AcroForm;
  fld: IPXC_FormField;
  widg: IPXC_AnnotData_Widget;
  annData: IPXC_AnnotData;
  xForm: IPXC_XForm;
  iInst: IPXC_Inst;
  iDoc: IPXC_Document;
  iImage: IPXC_Image;
  arect: PXC_Rect;
  urd: IPXC_UndoRedoData;
  iCC: IPXC_ContentCreator;
  iC: IPXC_Content;
  matrix: PXC_Matrix;
  icPage: IIXC_Page;
begin
  Result := False;
  if Doc.CoreDoc.HasAcroForm and (Doc.CoreDoc.Pages.Get_Item(Pred(APageNumber),iPage) = S_OK) then
  begin
    acro := Doc.CoreDoc.AcroForm;
    // obtain field reference to image field
    fld := acro.GetFieldByName(PChar(AFormField));
    if Assigned(fld) then
    begin
      // obtain annotation reference to image field
      annot := fld.Widget[0];
      // get position and dimensions from image field
      if annot.Get_Rect(arect) = S_OK then
        if annot.Get_Data(annData) = S_OK then
        begin
          widg := IPXC_AnnotData_Widget(annData);
          // create temporary IPXC_Document
          iInst := IPXC_Inst(Inst.GetExtension('PXC'));
          iDoc := iInst.NewDocument;
          xForm := iDoc.CreateNewXForm(arect);
          // add new page to temp doc with rect from image field
          if iDoc.Pages.InsertPage(0,arect,urd,iPage) = S_OK then
            if Assigned(iPage) then
            begin
              iCC := iDoc.CreateContentCreator;
              if Assigned(icc) then
              begin
                if CreateIPXCImageFromBitmap(AnImageStream,arect,icPage) then
                  if Assigned(icPage) then
                  begin
                    // add temporary image to iixc_page
                    iImage := iDoc.AddImageFromIXCPage(icPage,0);
                    if Assigned(iImage) then
                      if (icc.PlaceImage(iImage) = S_OK) then
                        if icc.Detach(iC) = S_OK then
                          if xForm.SetContent(iC,PlaceContent_Replace) = S_OK then
                            if widg.SetIcon(AAT_Normal,xForm,True) = S_OK then
                              if widg.Set_ButtonTextPosition(WidgetText_IconOnly) = S_OK then
                                if annot.Set_Data(widg) = S_OK then
                                  Result := True;
                  end;
              end;
            end;
        end;
    end;
  end;
end;
The call to SetIcon fails. No specific error is provided.

Can you see anything that I am not doing correctly?

I read this: https://www.pdf-xchange.com/forum3 ... con#p99381 . Our application has a control instance on the main application; when we open a pdf we do so in another form, which has it's own control reference. Would this issue apply to this approach?

Thanks.
Sasha - Tracker Dev Team
User
Posts: 5522
Joined: Fri Nov 21, 2014 8:27 am
Contact:

Re: Acrobat DC Image Form Fields

Post by Sasha - Tracker Dev Team »

Hello dkeith2,

Please give us a sample project that we can debug, then we can assist further.
Also, as I mentioned before - this work is done in the core level. If you are working with IPXV document then the appropriate events should be fired for correct ui update. Try using this method with the ipxc document, that you have opened on core level and then save it and open it with the editor.

Cheers,
Alex
Subscribe at:
https://www.youtube.com/channel/UC-TwAMNi1haxJ1FX3LvB4CQ
dkeith2
User
Posts: 46
Joined: Mon Aug 14, 2017 8:28 pm

Re: Acrobat DC Image Form Fields

Post by dkeith2 »

This code partially works:

Code: Select all

function PDFPlaceSignature(AnImageStream: TBytesStream; AFormField: WideString; APageNumber: Integer): Boolean;
var
  annot: IPXC_Annotation;
  iPage: IPXC_Page;
  acro: IPXC_AcroForm;
  fld: IPXC_FormField;
  widg: IPXC_AnnotData_Widget;
  annData: IPXC_AnnotData;
  xForm: IPXC_XForm;
  iImage: IPXC_Image;
  arect: PXC_Rect;
  iCC: IPXC_ContentCreator;
  iC: IPXC_Content;
  matrix: PXC_Matrix;
  icPage: IIXC_Page;
begin
  Result := False;
  if Doc.CoreDoc.HasAcroForm and (Doc.CoreDoc.Pages.Get_Item(Pred(APageNumber),iPage) = S_OK) then
  begin
    acro := Doc.CoreDoc.AcroForm;
    fld := acro.GetFieldByName(PChar(AFormField));
    if Assigned(fld) then
    begin
      annot := fld.Widget[0];
      if annot.Get_Rect(arect) = S_OK then
        if annot.Get_Data(annData) = S_OK then
        begin
          widg := IPXC_AnnotData_Widget(annData);
          if Assigned(FPXCInst) then
          begin
            xform := Doc.CoreDoc.CreateXFormFromPage(iPage,
                                                     IPF_Annots_Flatten and
                                                     IPF_Widgets_Flatten and
                                                     IPF_Bookmarks_DoNotCopy and
                                                     IPF_OCG_DoNotCopy);
            if xform.Set_BBox(@arect) = S_OK then
              if Assigned(xForm) then
              begin
                iCC := Doc.CoreDoc.CreateContentCreator;
                if Assigned(icc) then
                begin
                  if CreateIPXCImageFromBitmap(AnImageStream,arect,icPage) then
                    if Assigned(icPage) then
                    begin
                      iImage := Doc.CoreDoc.AddImageFromIXCPage(icPage,0);
                      if Assigned(iImage) then
                      begin
                        matrix.a := arect.right;
                        matrix.b := arect.bottom;
                        matrix.c := arect.left;
                        matrix.d := arect.top;
                        matrix.e := 0;
                        matrix.f := 0;
                        if icc.ConcatCS(matrix) = S_OK then
                          if (icc.PlaceImage(iImage) = S_OK) then
                            if icc.Detach(iC) = S_OK then
                              if xForm.SetContent(iC,PlaceContent_Replace) = S_OK then
                                try
                                  if widg.SetIcon(AAT_Normal,xForm,True) = S_OK then
                                    if widg.Set_ButtonTextPosition(WidgetText_IconOnly) = S_OK then
                                      if annot.Set_Data(widg) = S_OK then
                                      begin
                                        RefreshPages;
                                        Result := True;
                                      end;
                                except
                                  on E:Exception do
                                    MessageDlg('Error: Call to SetIcon failed - ' + #13#13 + E.Message,mtError,[mbOK],0);
                                end;
                      end;
                    end;
                end;
              end;
          end;
        end;
    end;
  end;
end;
By partial, I mean that I start with a mouse drawn 'A', and end up with a very skewed set of squiggly lines. Only, I don't see it in the document, even after I save it. Rather, I have to close the document after saving it, then open it in the PDF-XChange Editor, and then I can see my squiggly image in the image field.

How do I set up the matrix so that it takes my already scaled image and displays it properly? Is that the proper way to do this? Do I need to use the matrix? Can you please explain why I need to use a 3D transformation matrix to take a 2D image that is already scaled to fit the widget icon rect and place it as an icon? Is there a simpler way to do this?

Also, how do I get the image, once written to the image field, to display immediately instead of having to save the document, close the document, and reopen the document?

Thanks.
Sasha - Tracker Dev Team
User
Posts: 5522
Joined: Fri Nov 21, 2014 8:27 am
Contact:

Re: Acrobat DC Image Form Fields

Post by Sasha - Tracker Dev Team »

Hello dkeith2,
Please give us a sample project that we can debug, then we can assist further.
Also, how do I get the image, once written to the image field, to display immediately instead of having to save the document, close the document, and reopen the document?
Also, as I mentioned before - this work is done in the core level. If you are working with IPXV document then the appropriate events should be fired for correct ui update.
Cheers,
Alex
Subscribe at:
https://www.youtube.com/channel/UC-TwAMNi1haxJ1FX3LvB4CQ
dkeith2
User
Posts: 46
Joined: Mon Aug 14, 2017 8:28 pm

Re: Acrobat DC Image Form Fields

Post by dkeith2 »

How do I attach my project?
Sasha - Tracker Dev Team
User
Posts: 5522
Joined: Fri Nov 21, 2014 8:27 am
Contact:

Re: Acrobat DC Image Form Fields

Post by Sasha - Tracker Dev Team »

Hello dkeith2,

Just pack it and attach it to your post. Don't forget to remove the license key if there is any.

Cheers,
Alex
Subscribe at:
https://www.youtube.com/channel/UC-TwAMNi1haxJ1FX3LvB4CQ
dkeith2
User
Posts: 46
Joined: Mon Aug 14, 2017 8:28 pm

Re: Acrobat DC Image Form Fields

Post by dkeith2 »

Please take a look at this code and advise if anything appears to be out of place or done incorrectly:

Code: Select all


function TForm2.GetImageField(AFormFieldName: UnicodeString;
                              out AnAnnotation: IPXC_Annotation;
                              out AnImageField: IPXC_AnnotData_Widget;
                              out AnImageFldRect: PXC_Rect): Boolean;
var
  anndata: IPXC_AnnotData;
  fld: IPXC_FormField;
begin
  if Length(AFormFieldName) < 3 then
    raise Exception.Create('Error: Invalid Field Name');
  Result := False;
  if FCoreDoc.HasAcroForm then
  begin
    // obtain field reference to image field
    fld := FCoreDoc.AcroForm.GetFieldByName(PChar(AFormFieldName));
    if Assigned(fld) then
      // obtain annotation reference to image field
      if Assigned(fld.Widget[0]) then
      begin
        AnAnnotation := fld.Widget[0];
        if (AnAnnotation.Get_Data(anndata) = S_OK) and Assigned(anndata) then
          if AnAnnotation.Get_Rect(AnImageFldRect) = S_OK then
          begin
            AnImageField := IPXC_AnnotData_Widget(annData);
            Result := Assigned(AnImageField);
          end;
      end;
  end;
end;

function TForm2.CreatePXCImageFromBitmap(ABitmapFile: Unicodestring; out APXCImage: IPXC_Image): Boolean;
var
  bmp: Vcl.Graphics.TBitmap;
  icPage: IIXC_Page;
  {**for test purposes only**
  icPageTemp: IIXC_Page;
  ixcImage: IIXC_Image;
  }
begin
  if not FileExists(ABitmapFile) then
    raise Exception.Create('Error: Bitmap file ' + ABitmapFile + ' is not valid');
  Result := False;
  bmp := Vcl.Graphics.TBitmap.Create;
  try
    bmp.PixelFormat := pf24bit;
    bmp.LoadFromFile(ABitmapFile);
    if (FIXCInst.Page_CreateFromHBITMAP(bmp.Handle,0,icPage) = S_OK) and Assigned(icPage) then
    begin
      APXCImage := FCoreDoc.AddImageFromIXCPage(icPage,0);
      Result := Assigned(APXCImage);
    end;
  finally
    bmp.Free;
  end;

{
(***Okay... so the following code proves that - up to this point - all is working well!***)
  if APXCImage.CreateIXCPage(True,RI_Perceptual,icPageTemp) = S_OK then
    if icPageTemp.Set_FmtInt(FP_ID_FORMAT,FMT_BMP_ID) = S_OK then
      if FIXCInst.CreateEmptyImage(ixcImage) = S_OK then
        if ixcImage.InsertPage(icPageTemp,0) = S_OK then
          if ixcImage.Save(PChar(ExtractFileDir(Application.ExeName) + '\3.bmp'),CreationDisposition_Overwrite) = S_OK then
(***End debug/save image test code***)
}
end;

function TForm2.CreatePXCPageFromPXCImage(APXCImage: IPXC_Image; out APXCPage: IPXC_Page; ABtnIconRect: PXC_Rect): Boolean;
var
  iCC: IPXC_ContentCreator;
  ipDoc: IPXC_Document;
  arect: PXC_Rect;
  iMath: IMathHelper;
  matrix,mtx: PXC_Matrix;
  iC: IPXC_Content;
  urd: IPXC_UndoRedoData;
begin
  Result := False;
  ipDoc := FCoreDoc; // also tried ipDoc := FPXCInst.NewDocument;
  // add new page to document
  if ipDoc.Pages.AddEmptyPages(0,1,ABtnIconRect,FInst.ProgressMon,urd) = S_OK then
    // get handle to new page
    if ipDoc.Pages.Get_Item(0,APXCPage) = S_OK then
      // get bounding box of sized page
      if APXCPage.Get_Box(PBox_BBox,arect) = S_OK then
        // obtain content handle from IPXC_Page
        if APXCPage.GetContent(CAccessMode_WeakClone,iC) = S_OK then
        begin
          mtx.a := arect.right - arect.left;     // Can't determine if this section is necessary
          mtx.d := arect.top - arect.bottom;     //
          mtx.e := arect.left;                   //
          mtx.f := arect.bottom;                 //
          iMath := FAUXInst.MathHelper;
          // map rects
          if iMath.Matrix_RectToRect(ABtnIconRect,arect,matrix) = S_OK then
          begin
            iCC := ipDoc.CreateContentCreator;
            if iCC.Attach(iC) = S_OK then
              if iCC.SaveState = S_OK then            // don't know if this is necessary
                if iCC.ConcatCS(matrix) = S_OK then  // also tried iCC.ConcatCS(mtx)
                  if iCC.PlaceImage(APXCImage) = S_OK then
                    if iCC.RestoreState = S_OK then  // don't know if this is necessary
                      if iCC.Detach(iC) = S_OK then
                        if APXCPage.PlaceContent(iC,PlaceContent_Replace) = S_OK then
                          Result := True;
          end;
        end;
end;

function TForm2.PDFPlaceSignature(ABitmapFile: UnicodeString; AFormField: WideString; APageNumber: Integer): Boolean;
var
  imgFld: IPXC_AnnotData_Widget;
  iPage: IPXC_Page;
  annot: IPXC_Annotation;
  arect: PXC_Rect;
  xForm: IPXC_XForm;
  iImage: IPXC_Image;
begin
  Result := False;
  if GetImageField(AFormField,annot,imgFld,arect) and Assigned(imgFld) then
    // using the signature bitmap create an ipxc_image
    if CreatePXCImageFromBitmap(ABitmapFile,iImage) and Assigned(iImage) then
    begin
      if CreatePXCPageFromPXCImage(iImage,iPage,arect) and Assigned(iPage) then
      begin
        // save the document
        // FCoreDoc.WriteToFile(ExtractFilePath(Application.ExeName) + '\test1.pdf',nil,0);
        xform := FCoreDoc.CreateXFormFromPage(iPage,
                                              IPF_Annots_Flatten and
                                              IPF_Widgets_Flatten and
                                              IPF_Bookmarks_DoNotCopy and
                                              IPF_OCG_DoNotCopy);
        if Assigned(xForm) then
          try
            if imgFld.SetIcon(AAT_Normal,xForm,True) = S_OK then
              if imgFld.Set_ButtonTextPosition(WidgetText_IconOnly) = S_OK then
                if annot.Set_Data(imgFld) = S_OK then
                begin
                  RefreshPages;
                  Result := True;
                end;
          except
            on E:Exception do
              MessageDlg('Error: Call to SetIcon failed - ' + #13#13 + E.Message,mtError,[mbOK],0);
          end;
      end;
    end;
end;
What I have proven is that the IPXC_Image gets created successfully, and the IPXC_Page gets created and placed successfully on the image field.

The problem seems to lie in between; the code that places the IPXC_Image into the IPXC_Page doesn't work...
Sasha - Tracker Dev Team
User
Posts: 5522
Joined: Fri Nov 21, 2014 8:27 am
Contact:

Re: Acrobat DC Image Form Fields

Post by Sasha - Tracker Dev Team »

Hello dkeith2,

Are you sure that you are talking about IPXC_Page and IPXC_Image? Or should it be the IIXC_Page?

Cheers,
Alex
Subscribe at:
https://www.youtube.com/channel/UC-TwAMNi1haxJ1FX3LvB4CQ
dkeith2
User
Posts: 46
Joined: Mon Aug 14, 2017 8:28 pm

Re: Acrobat DC Image Form Fields

Post by dkeith2 »

Hi Alex!

Please read the code before responding.

I've been attempting to follow the advice that you gave me to do this; so far I can't get it to work. I did explain which parts work, and which parts don't. The instruction that you pointed me to has an IPXC_Page being converted to an IPXC_XForm, which subsequently gets placed on a widget icon.

Remember this?:

Code: Select all

 xform := FCoreDoc.CreateXFormFromPage(iPage,IPF_Annots_Flatten or IPF_Widgets_Flatten or IPF_Bookmarks_DoNotCopy or IPF_OCG_DoNotCopy);
 
...which comes from this reference that you pointed me to?:

https://gist.github.com/Polaringu/f661a5af12c8fbf7e7fd

The first parameter in the call to CreateXFormFromPage is - you guessed it! - an IPXC_Page.

Please read your documentation here:

https://sdkhelp.pdf-xchange.com/vi ... rmFromPage

To narrow it down, this is the code that is not working:

Code: Select all

function CreatePXCPageFromPXCImage(APXCImage: IPXC_Image; out APXCPage: IPXC_Page; ABtnIconRect: PXC_Rect): Boolean;
var
  iCC: IPXC_ContentCreator;
  ipDoc: IPXC_Document;
  arect: PXC_Rect;
  iMath: IMathHelper;
  matrix,mtx: PXC_Matrix;
  iC: IPXC_Content;
  urd: IPXC_UndoRedoData;
begin
  Result := False;
  if APXCImage.Get_Document(ipDoc) = S_OK then
  // add new page to document
  if ipDoc.Pages.AddEmptyPages(0,1,ABtnIconRect,FInst.ProgressMon,urd) = S_OK then
    // get handle to new page
    if ipDoc.Pages.Get_Item(0,APXCPage) = S_OK then
      // get bounding box of sized page
      if APXCPage.Get_Box(PBox_BBox,arect) = S_OK then
        // obtain content handle from IPXC_Page
        if APXCPage.GetContent(CAccessMode_WeakClone,iC) = S_OK then
        begin
          mtx.a := arect.right - arect.left;     // Can't determine if this section is necessary
          mtx.d := arect.top - arect.bottom;     //
          mtx.e := arect.left;                   //
          mtx.f := arect.bottom;                 //
          iMath := FAUXInst.MathHelper;
          // map rects
          if iMath.Matrix_RectToRect(ABtnIconRect,arect,matrix) = S_OK then
          begin
            iCC := ipDoc.CreateContentCreator;
            if iCC.Attach(iC) = S_OK then
              if iCC.SaveState = S_OK then            // don't know if this is necessary
                if iCC.ConcatCS(matrix) = S_OK then  // also tried iCC.ConcatCS(mtx)
                  if iCC.PlaceImage(APXCImage) = S_OK then
                    if iCC.RestoreState = S_OK then  // don't know if this is necessary
                      if iCC.Detach(iC) = S_OK then
                        if APXCPage.PlaceContent(iC,PlaceContent_Replace) = S_OK then
                          Result := True;
          end;
        end;
        // the following is just a test to see if the document's IPXC_Page gets the correct dimensions and gets the IPXC_Image placed upon it.
        // the IPXC_Page gets the correct dimensions, but does not get the IPXC_Image placement via the IPXC_ContentCreator/IPXC_Content interface.
        ipDoc.WriteToFile(PChar(ExtractFilePath(Application.ExeName) + '\test1.pdf'),nil,0);
end;
When I write the temporary, in memory IPXC_Document (ipDoc) to file, it has the correct dimensions. It just doesn't get the image placed on the IPXC_Page (APXCPage).

Again, my number one suspect is the matrix code.

Can you please provide an example of how the matrix should be configured?

Can you please read through the code and try to spot anything that I may be doing wrong that is preventing the IPXC_Image from getting placed on the IPXC_Page?

Could it be something other than the matrix? Like the IPXC_ContentCreator/IPXC_Content interface(s)?
Sasha - Tracker Dev Team
User
Posts: 5522
Joined: Fri Nov 21, 2014 8:27 am
Contact:

Re: Acrobat DC Image Form Fields

Post by Sasha - Tracker Dev Team »

Hello dkeith2,

Here's a working sample:

Code: Select all

PDFXEdit.IPXC_Document CreateNewDocument(out PDFXEdit.PXC_Rect rc)
{
	PDFXEdit.IPXC_Document coreDoc = pxcInst.NewDocument();
	rc.left = 0;
	rc.right = 500;
	rc.top = 800;
	rc.bottom = 0;
	PDFXEdit.IPXC_UndoRedoData urd;
	coreDoc.Pages.AddEmptyPages(0, 1, ref rc, null, out urd);
	return coreDoc;
}

private void imageAsFormFieldsIconToolStripMenuItem_Click(object sender, EventArgs e)
{
	PDFXEdit.PXC_Rect rc;
	PDFXEdit.IPXC_Document coreDoc = CreateNewDocument(out rc);
	rc = coreDoc.Pages[0].get_Box(PXC_BoxType.PBox_PageBox);
	PDFXEdit.IPXC_FormField ff = coreDoc.AcroForm.CreateField("Button1", PDFXEdit.PXC_FormFieldType.FFT_PushButton, 0, ref rc);
	PDFXEdit.IPXC_Annotation annot = ff.Widget[0];
	PDFXEdit.IPXC_AnnotData_Widget WData = (PDFXEdit.IPXC_AnnotData_Widget)annot.Data;
	//Getting IPXC_Image
	PDFXEdit.IPXC_Image img = coreDoc.AddImageFromFile("C:\\Users\\polar_000\\Pictures\\AGB_ESW.png");
	pdfCtl.OpenDocFrom(coreDoc);
	//

	float imgw = (float)img.Width;
	float imgh = (float)img.Height;

	PDFXEdit.IPXC_ContentCreator CC = coreDoc.CreateContentCreator();
	CC.SaveState();
	CC.ScaleCS(imgw, imgh);
	CC.PlaceImage(img);
	CC.RestoreState();
	PDFXEdit.IPXC_Content content = CC.Detach();
	PDFXEdit.PXC_Rect rcBBox;
	rcBBox.left = 0;
	rcBBox.top = imgh;
	rcBBox.right = imgw;
	rcBBox.bottom = 0;
	content.set_BBox(rcBBox);
	PDFXEdit.IPXC_XForm xForm = coreDoc.CreateNewXForm(ref rc);
	xForm.SetContent(content);

			
	WData.ButtonTextPosition = PDFXEdit.PXC_WidgetButtonTextPosition.WidgetText_IconOnly;
	WData.SetIcon(PDFXEdit.PXC_AnnotAppType.AAT_Normal, xForm, true);
	int nID = pdfCtl.Inst.Str2ID("op.annot.setData", false);
	PDFXEdit.IOperation Op = pdfCtl.Inst.CreateOp(nID);
	PDFXEdit.ICabNode input = Op.Params.Root["Input"];
	input.Add().v = annot;
	PDFXEdit.ICabNode options = Op.Params.Root["Options"];
	options["NewData"].v = WData;
	Op.Do();
}
Cheers,
Alex
Subscribe at:
https://www.youtube.com/channel/UC-TwAMNi1haxJ1FX3LvB4CQ
dkeith2
User
Posts: 46
Joined: Mon Aug 14, 2017 8:28 pm

Re: Acrobat DC Image Form Fields

Post by dkeith2 »

Thanks Alex. Here's how I finally solved it:

Code: Select all

function CreatePXCPageFromPXCImage(APXCImage: IPXC_Image; out APXCPage: IPXC_Page; ABtnIconRect: PXC_Rect): Boolean;
var
  iCC: IPXC_ContentCreator;
  iC: IPXC_Content;
  ipDoc: IPXC_Document;
  arect: PXC_Rect;
  urd: IPXC_UndoRedoData;
  awidth,aheight: Cardinal;
begin
  Result := False;
  if APXCImage.Get_Document(ipDoc) = S_OK then
  // add new page to document
  if ipDoc.Pages.AddEmptyPages(0,1,ABtnIconRect,PDFEdit.Inst.ProgressMon,urd) = S_OK then
    // get handle to new page
    if ipDoc.Pages.Get_Item(0,APXCPage) = S_OK then
      // obtain content handle from IPXC_Page
      if APXCPage.GetContent(CAccessMode_FullClone,iC) = S_OK then
        begin
          iCC := ipDoc.CreateContentCreator;
          arect.left := 0;
          arect.top := 0;
          if APXCImage.Get_Width(awidth) = S_OK then
            arect.right := awidth;
          if APXCImage.Get_Height(aheight) = S_OK then
            arect.bottom := aheight;
          if iCC.Attach(iC) = S_OK then
            if iCC.PlaceImageEx(APXCImage,ABtnIconRect,PlaceContent_Replace) = S_OK then
              if iCC.Detach(iC) = S_OK then
                if APXCPage.PlaceContent(iC,PlaceContent_Replace) = S_OK then
                  Result := True;
        end;
end;
This gets called from here:

Code: Select all

function PDFPlaceSignature(ABitmapFile: UnicodeString; AFormField: WideString; APageNumber: Integer): Boolean;
var
  imgFld: IPXC_AnnotData_Widget;
  iPage: IPXC_Page;
  annot: IPXC_Annotation;
  arect: PXC_Rect;
  xForm: IPXC_XForm;
  iImage: IPXC_Image;
  ipDoc: IPXC_Document;
begin
  Result := False;
  if GetImageField(AFormField,annot,imgFld,arect) and Assigned(imgFld) then
    // using the signature bitmap create an ipxc_image
    if CreatePXCImageFromBitmap(ABitmapFile,iImage) and Assigned(iImage) then
      // using the ipxc_image create an ipxc_page
      if CreatePXCPageFromPXCImage(iImage,iPage,arect) and Assigned(iPage) then
      begin
      	// using the ipxc_page create an ipxc_xform
        xform := FCoreDoc.CreateXFormFromPage(iPage,IPF_Annots_Flatten or IPF_Widgets_Flatten or IPF_Bookmarks_DoNotCopy or IPF_OCG_DoNotCopy);
        if Assigned(xForm) then
          // place xform on form field widget icon
          if imgFld.SetIcon(AAT_Normal,xForm,True) = S_OK then
            if imgFld.Set_ButtonTextPosition(WidgetText_IconOnly) = S_OK then
              if annot.Set_Data(imgFld) = S_OK then
              begin
                RefreshPages;
                Result := True;
              end;
      end;
end;
Last edited by dkeith2 on Wed Jan 10, 2018 11:11 pm, edited 2 times in total.
User avatar
Tracker Supp-Stefan
Site Admin
Posts: 17910
Joined: Mon Jan 12, 2009 8:07 am
Location: London
Contact:

Re: Acrobat DC Image Form Fields

Post by Tracker Supp-Stefan »

Hello dkeith2,

Glad to hear that you finally solved this!
And thanks for sharing your solution!
Hopefully it would be useful to others too!

Cheers,
Stefan
dkeith2
User
Posts: 46
Joined: Mon Aug 14, 2017 8:28 pm

Re: Acrobat DC Image Form Fields

Post by dkeith2 »

:D
Sasha - Tracker Dev Team
User
Posts: 5522
Joined: Fri Nov 21, 2014 8:27 am
Contact:

Re: Acrobat DC Image Form Fields

Post by Sasha - Tracker Dev Team »

Hello dkeith2,

Please use my method (that I took time to write and it works) - it's optimal for your case, because in your case, you are adding an empty page that is not correct. You should add a XForm and then modify it's content, then place it as an icon.

Cheers,
Alex
Subscribe at:
https://www.youtube.com/channel/UC-TwAMNi1haxJ1FX3LvB4CQ
Post Reply