0

I've searched the site to make sure my question wasn’t already answered.

My problem is I'm trying to find the total number of pages that an open PDF file contains.

I'm able to find the total number of pages if I know the file path. So that means, my problem comes down to, me not knowing how to find the file path of an open window of an (active) PDF file.

I'd like to do all this in Autohotkey and my pdf reader is Foxit PhantomPDF. I have been able to do this for Adobe Acrobat in the past, but I guess Foxit Phantom isn't as popular so I wasn't able to find a solution.

Any help would be appreciated.

Here's the code I have so far Description of code: So if I put the file in a specific place, I can find the total page numbers by pressing F1. (Half of what I need)

F1::
pdfPath := "C:\20yorkcondofin.pdf"
VarSetCapacity(GUID, 16)
DllCall("ole32\CLSIDFromString", "wstr", IID_RandomAccessStream := "{905A0FE1-BC53-11DF-8C49-001E4FC686DA}", "ptr", &GUID)
DllCall("ShCore\CreateRandomAccessStreamOnFile", "wstr", pdfPath, "uint", Read := 0, "ptr", &GUID, "ptr*", IRandomAccessStream)
CreateClass("Windows.Data.Pdf.PdfDocument", IPdfDocumentStatics := "{433A0B5F-C007-4788-90F2-08143D922599}", PdfDocumentStatics)
DllCall(NumGet(NumGet(PdfDocumentStatics+0)+8*A_PtrSize), "ptr", PdfDocumentStatics, "ptr", IRandomAccessStream, "ptr*", PdfDocument)   ; LoadFromStreamAsync
WaitForAsync(PdfDocument)
DllCall(NumGet(NumGet(PdfDocument+0)+7*A_PtrSize), "ptr", PdfDocument, "uint*", PageCount)   ; get_PageCount
ObjReleaseClose(IRandomAccessStream)
ObjReleaseClose(PdfDocumentStatics)
ObjReleaseClose(PdfDocument)
msgbox % PageCount
return

CreateClass(string, interface := "", ByRef Class := "")
{
   CreateHString(string, hString)
   if (interface = "")
      result := DllCall("Combase.dll\RoActivateInstance", "ptr", hString, "ptr*", Class, "uint")
   else
   {
      VarSetCapacity(GUID, 16)
      DllCall("ole32\CLSIDFromString", "wstr", interface, "ptr", &GUID)
      result := DllCall("Combase.dll\RoGetActivationFactory", "ptr", hString, "ptr", &GUID, "ptr*", Class, "uint")
   }
   if (result != 0)
   {
      if (result = 0x80004002)
         msgbox No such interface supported
      else if (result = 0x80040154)
         msgbox Class not registered
      else
         msgbox error: %result%
      ExitApp
   }
   DeleteHString(hString)
}

CreateHString(string, ByRef hString)
{
    DllCall("Combase.dll\WindowsCreateString", "wstr", string, "uint", StrLen(string), "ptr*", hString)
}

DeleteHString(hString)
{
   DllCall("Combase.dll\WindowsDeleteString", "ptr", hString)
}

WaitForAsync(ByRef Object)
{
   AsyncInfo := ComObjQuery(Object, IAsyncInfo := "{00000036-0000-0000-C000-000000000046}")
   loop
   {
      DllCall(NumGet(NumGet(AsyncInfo+0)+7*A_PtrSize), "ptr", AsyncInfo, "uint*", status)   ; IAsyncInfo.Status
      if (status != 0)
      {
         if (status != 1)
         {
            DllCall(NumGet(NumGet(AsyncInfo+0)+8*A_PtrSize), "ptr", AsyncInfo, "uint*", ErrorCode)   ; IAsyncInfo.ErrorCode
            msgbox AsyncInfo status error: %ErrorCode%
            ExitApp
         }
         ObjRelease(AsyncInfo)
         break
      }
      sleep 10
   }
   DllCall(NumGet(NumGet(Object+0)+8*A_PtrSize), "ptr", Object, "ptr*", ObjectResult)   ; GetResults
   ObjReleaseClose(Object)
   Object := ObjectResult
}

ObjReleaseClose(ByRef Object)
{
   if Object
   {
      if (Close := ComObjQuery(Object, IClosable := "{30D5A829-7FA4-4026-83BB-D75BAE4EA99E}"))
      {
         DllCall(NumGet(NumGet(Close+0)+6*A_PtrSize), "ptr", Close)   ; Close
         ObjRelease(Close)
      }
      ObjRelease(Object)
   }
   Object := ""
}
return
  • I know that I can see the total number of pages if I click properties in FoxIt – Shahin Kachooie Aug 15 '22 at 20:49
  • @KJ Bro! Okay, so I'm getting closer to a solution. This nearly works: ControlGetText, xedit, Edit4, A msgbox, %xedit% it's showing me the page number per total page number as you said. The issue is that the Edit4 might be Edit2 or 6 and so on, so how do I find the correct edit ClassNN to be asking for? Would I just look at values 1-10, and see which one has a slash in it? Why did you write WinGetTItle, xtitle A when ControlGetText is already getting the active window with that A at the end? Thank you so much for your help so far! You're immensely helpful! – Shahin Kachooie Aug 16 '22 at 17:02
  • @KJ With regards to the catch 22 ... I had no idea. Thanks! target the api for feedback... How could I use this with AHK? https://cdn01.foxitsoftware.com/pub/foxit/manual/phantom/en_us/APIReferenceforApplicationCommunication_11.0.pdf I can see there is a "GetNumPages Gets the number of pages in a file." – Shahin Kachooie Aug 16 '22 at 17:15

0 Answers0