2017-03-24 12 views
0

Adob​​e AxAcroPDFコントロールには、現在のページ番号を返す関数はありません。私は個人的なユーティリティを作っているだけなので、私は共有しようと思っていたハック方法に訴える贅沢を持っていました...それは網全体からのビットとピースと一緒にパッチされています。 User32.dllのWindowsネイティブ関数を使用してコントロールの子を列挙し、ページ番号に対応するツールバーのテキストボックスを検索します。それからのテキストは、SendMessage呼び出しを使用して読み取られます。C#のAxAcroPDFオブジェクトの現在のページを確認する

答えて

0

このメソッドは、Adobe PDFビューアの子コンポーネントを列挙し、ツールバーのテキストボックスを探します。テキストボックスの1つはページ番号、1つは現在のズーム値です。内容に '%'が付いていないテキストボックスは、ページ番号のテキストボックスとして扱われます。テキストボックスの内容は、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); 
関連する問題