【问题标题】:Programatically fill PDF form fields in Browser Control在浏览器控件中以编程方式填充 PDF 表单域
【发布时间】:2012-02-26 16:13:18
【问题描述】:

基本情况是我需要以编程方式填写驻留在网络服务器上的 PDF 文本字段。这些字段将被映射并使用 CSV 中包含的数据填充。 PDF 必须在浏览器(浏览器控件或 ie/ff/chrome/etc)中打开并就地编辑。无法下载、填写、上传(必须使用里面的提交按钮填写提交;我试过编辑按钮提交路径无济于事)。

到目前为止,我已经在表单上放置了一个 Web 浏览器控件,并使其导航到网站、登录并加载 PDF 文件。如何与在 Web 浏览器控件中打开的 PDF 文件进行交互?浏览各种 PDF 库,它们似乎主要与位于硬盘驱动器上的封闭 pdf 交互,进行修改并重新保存。

编辑:我对替代解决方案非常开放。我不知道它是否可能,但如果是这样 - 我在表单上运行的机器上基于 PDF 的 javascript?如果我下载它,我可以很容易地做到这一点,但似乎无法找到在网络浏​​览器中打开 PDFJS 时使用它的方法。

【问题讨论】:

    标签: c# javascript vb.net forms pdf


    【解决方案1】:

    恐怕做自己想做的事不容易。首先,您必须找到嵌入在 WebBrowser 控件中的 PDF 阅读器的窗口句柄。以下是有关如何执行此操作的示例代码:

        Public Function GetPdfViewerHandle() As System.IntPtr
        Dim tempHandle As System.IntPtr
        '--------------------------------------
        ' get handle to pdf viewer
        '--------------------------------------
        '--------------------------------------
        ' first check for the foxit reader
        '--------------------------------------
        tempHandle = FindChildWindow(WebBrowser1.Handle, "AfxWnd42s", "Reader", 1, True)
        If IntPtr.Zero.Equals(tempHandle) = True Then
            '---------------------------------
            ' if not foxit, check for adobe
            '---------------------------------
            tempHandle = FindChildWindow(WebBrowser1.Handle, "AVL_AVVIEW", "AVPageView", 1, True)
        End If
    
        Return tempHandle
    
    End Function
    
    Public Shared Function FindChildWindow(ByVal hParent As IntPtr, ByVal P_childClass As String, ByVal P_childTitle As String, ByVal P_count As Integer, ByVal p_recursive As Boolean) As IntPtr
         Dim hChild As IntPtr
         Dim className As String
         Dim title As String
         Dim cnt As Integer
         Dim tempPtr As IntPtr
         Dim Declare Function FindWindowExA Lib "user32.dll" (ByVal hWnd1 As IntPtr, ByVal hWnd2 As Int32, ByVal lpsz1 As String, ByVal lpsz2 As String) As IntPtr
    
         cnt = 0
    
         hChild = FindWindowExA(hParent, 0, Nothing, Nothing)
    
         While hChild.ToInt32 > 0
    
            If P_childClass Is Nothing Then
               className = GetClassName(hChild)
            Else
               className = GetClassName(hChild)
               If P_childClass.Length < className.Length Then
                  className = className.Substring(0, P_childClass.Length)
               End If
            End If
    
            If P_childTitle Is Nothing Then
               title = GetWindowText(hChild).Replace("&", "")
            Else
               title = GetWindowText(hChild).Replace("&", "")
    
               If P_childTitle.Length < title.Length Then
                  title = title.Substring(0, P_childTitle.Length)
               End If
            End If
    
    
            Debug.WriteLine("hwnd=" + Hex$(hChild.ToInt32) + ", className = " + className + ", title = " + title)
            If (String.Compare(className, P_childClass, True) = 0 And String.Compare(title, P_childTitle, True) = 0) Or (P_childClass = Nothing And String.Compare(title, P_childTitle, True) = 0) Or (String.Compare(className, P_childClass, True) = 0 And P_childTitle = Nothing) Then
               cnt += 1
               If cnt >= P_count Then
                  Return hChild
               End If
            End If
    
            If p_recursive = True Then
               tempPtr = FindChildWindow(hChild, P_childClass, P_childTitle, 1, p_recursive)
               If IntPtr.Zero.Equals(tempPtr) = False Then
                  Return tempPtr
               End If
            End If
    
            hChild = FindWindowExA(hParent, hChild.ToInt32, Nothing, Nothing)
         End While
    
         Return Nothing
    
      End Function
    

    一旦你有了窗口句柄,就有很多不同的方法可以找到表单域。如果您知道事情的顺序,您可以简单地开始向 pdf 阅读器句柄发送键命令或使用 Spy++ 找到表单字段的句柄,然后通过 Win32Api SendMessageA 函数向它们输入数据:

          Public Declare Function SendMessageA Lib "user32.dll" (ByVal hwnd As IntPtr, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer
    
                      asciiChar = CByte(Asc(data.Substring(0, 1)))
                  rc = SendMessageA(hwnd, WM_CHAR, asciiChar, 0)    
    

    祝你好运。

    【讨论】:

    • 我应该添加,表单的布局将始终相同,并且我已经有了文本字段的名称(感谢 iText#)
    • 谢谢!这正是我所需要的。
    【解决方案2】:

    如果您必须使用 PDF 上的按钮提交数据,只需检查提交的流量并查看它发送的内容,然后您可以使用 VB.NET 进行复制,甚至不必加载 PDF 文档。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-05-03
      • 1970-01-01
      • 2011-12-13
      • 2012-10-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-08
      • 1970-01-01
      相关资源
      最近更新 更多