2017-03-24 8 views
0

Adobe AxAcroPDF 컨트롤에는 현재 페이지 번호를 반환하는 기능이 없습니다. 나는 개인 유틸리티를 만들고있어 공유 할 줄 ​​알았던 해킹 방법에 정착 할 수있는 사치를 느꼈다 ... 그물을 통해 조각과 조각으로 패치했다. User32.dll의 Windows 기본 함수를 사용하여 컨트롤의 자식을 열거하고 페이지 번호에 해당하는 도구 모음에서 텍스트 상자를 찾습니다. 그런 다음 SendMessage 호출을 사용하여 텍스트를 읽습니다.C에서 AxAcroPDF 개체의 현재 페이지 확인

답변

0

이 메서드는 adobe PDF 뷰어의 하위 구성 요소를 열거하고 도구 모음에서 텍스트 상자를 찾습니다. 텍스트 상자 중 하나는 페이지 번호이며, 하나는 현재 확대/축소 값입니다. 내용에 '%'가없는 텍스트 상자는 페이지 번호 텍스트 상자로 사용됩니다. SendMessage 함수를 사용하여 텍스트 상자의 내용을 검색합니다.

뷰어 구성 요소에서 SetToolbarVisible (true)을 먼저 호출하여 툴바 (및 텍스트 상자)가 표시되도록해야 할 수도 있습니다.

이것은 끔찍하고 해킹 된 솔루션이며 Adobe에서 뷰어를 업데이트 할 때 쉽게 깨질 수 있습니다. Adobe가 "getCurrentPage"메서드를 추가하여 이러한 모든 문제를 피할 수 있다면 좋을 것입니다.

//you can get the handle parameter for this method as: yourPDFControl.Handle 
    public static string GetPageNumber(IntPtr adobeViewerHandle) 
    { 
     //get a list of all windows held by parent 
     List<IntPtr> childrenWindows = new List<IntPtr>(); 
     GCHandle listHandle = GCHandle.Alloc(childrenWindows); 
     try 
     { 
      EnumWindowProc childProc = new EnumWindowProc(EnumWindow); 
      EnumChildWindows(adobeViewerHandle, childProc, GCHandle.ToIntPtr(listHandle)); 
     } 
     finally 
     { 
      if (listHandle.IsAllocated) 
       listHandle.Free(); 
     } 

     //now have a list of the children, look for text boxes with class name "Edit" 
     for (int i = 0; i < childrenWindows.Count; i++) 
     { 
      int nRet; 
      // Pre-allocate 256 characters, the maximum class name length. 
      StringBuilder ClassName = new StringBuilder(256); 
      //Get the window class name 
      nRet = GetClassName(childrenWindows.ElementAt(i), ClassName, ClassName.Capacity); 

      if (ClassName.ToString().CompareTo("Edit") == 0) 
      { 
       IntPtr resultPointer = Marshal.AllocHGlobal(200); 
       StringBuilder text = new StringBuilder(20); 
       NativeMethods.SendMessage(childrenWindows.ElementAt(i), 0x000D, text.Capacity, text); //0x000D is WM_GETTEXT message 
       if (text.ToString().Contains("%")) //we don't want the text box for the PDF scale (e.g. 66.7% zoomed etc.) 
       { 
        continue; 
       } else 
       { 
        return text.ToString(); // the only other text box is the page number box 
       } 
      } 
     } 

     //Note I return as a string because PDF supports page labels, "I", "ii", "iv" etc. or even section labels "A", "B". So you're not guaranteed a numerical page number. 
     return "0"; 

    } 

    private static bool EnumWindow(IntPtr handle, IntPtr pointer) 
    { 
     GCHandle gch = GCHandle.FromIntPtr(pointer); 
     List<IntPtr> list = gch.Target as List<IntPtr>; 
     if (list == null) 
      throw new InvalidCastException("GCHandle Target could not be cast as List<IntPtr>"); 

     list.Add(handle); 
     return true; 
    } 


     [DllImport("user32.dll")] 
     [return: MarshalAs(UnmanagedType.Bool)] 
     internal static extern bool EnumChildWindows(IntPtr window, 
                 EnumWindowProc callback, 
                 IntPtr i); 

     internal delegate bool EnumWindowProc(IntPtr hWnd, IntPtr parameter); 

     [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)] 
     internal static extern int GetWindowTextLength(IntPtr hWnd); 

     [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)] 
     internal static extern int GetWindowText(IntPtr hWnd, 
                StringBuilder lpString, 
                int nMaxCount); 

     [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)] 
     internal static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount); 

     [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)] 
     internal static extern bool SendMessage(IntPtr hWnd, uint Msg, int wParam, StringBuilder lParam);