本文由玩赚乐(www.banghui.org)– 小峰原创翻译,转载请看清文末的转载要求,欢迎加入技术翻译小组!
从.pdf文件中提取页面,并保存为bitmaps
预告源代码 – 12KB
介绍在我的一个项目中,我需要提取.pdf文件的页面。图像需要尽可能地完美,即最好是原始的分辨率(DPI)。很多软件都声称它们可以从PDF文件中提取图像,我试了几个。但是当涉及到保存原始DPI图像的时候,效果都不怎么好。有人可能会认为原始大小和Adobe Reader中的100%缩放级别视图是一样的,但往往并非如此。并且当图像被保存为,例如.jpg格式的时候,它会更加失真。所以我决定自己写一个。
背景我想找一个免费的解决方案。而Adobe Reader就是免费的,并配备了一个可以嵌入到VB6的ActiveX控件。然而,它现有的功能非常有限(相对于附带Adobe Pro的ActiveX)。所以提取页面很难,因此我不得不求助于API调用来找到(子)窗口,发送消息。还有一件事是,我想隐藏ActiveXReader窗口,因为它的选择和取消选择以及定期调整大小看上去不美观。要发送击键和鼠标点击到一个隐藏的窗口,或让它重新绘制,需要额外编码。
使用代码代码涉及多个主题:
- 通过Classname和Text找到应用程序中的处理窗口
- 找到.pdf文件的页数
- 获取.pdf文件每个页面的DPI
从一个.pdf文件提取页面的两种方法:
A. 发送鼠标点击到一个隐藏的窗口
- 用API函数keybd_event模拟Control-C输入
- 用API函数从剪贴板获取数据
B. 除原件外,获取另一DPI的两个方法
- 在另一个PictureBox中调整PictureBox.Picture大小为高品质图像
- 绘制隐藏窗口的内容到PictureBox
预告源代码查看所有这些问题的解释性注释。下面的代码片段解决了两个问题:
通过Classname
和Text找到应用程序中的处理窗口:
Private Function FindWindowHandle(ByVal hwnd As Long, _ SelectClass As String, SelectText As String, bSelect As Boolean) As Long '' A recursive function to go through all the descendant windows of window with handle hwnd '' Returns handle for window with Classname = SelectClass and Window Text '' that either contains SelectText if bSelect = True; or does not contain SelectText is bSelect = False '' (There often is more than one window with the same class name) '' SelectText may be empty ("") and then this function only searches for a Classname '' Note : hwnd has to be ByVal Dim sClass As String, sText As String Dim sLen As Long Dim ParentHwnd As Long Dim FoundHwnd As Long FoundHwnd = 0 ''Get Class name of window with handle hwnd sClass = Space(64) sLen = GetClassName(hwnd, sClass, 63) sClass = Left(sClass, sLen) If StrComp(sClass, SelectClass, 1) = 0 Then If SelectText <> "" Then ''Get Window Text of window sText = Space(256) sLen = SendMessageS(hwnd, WM_GETTEXT, 255, sText) sText = Left(sText, sLen) ''If bSelect = True : If the text matches we have found the window If bSelect = True Then If InStr(sText, SelectText) > 0 Then ''FoundHwnd is the handle for the window with the required Classname and Text FoundHwnd = hwnd End If Else ''If bSelect = False : If the text does not match we have found the window If InStr(sText, SelectText) = 0 Then FoundHwnd = hwnd End If End If Else FoundHwnd = hwnd End If End If '' If the window is found, return its handle and exit If FoundHwnd <> 0 Then FindWindowHandle = FoundHwnd Exit Function End If '' If the window is not found, look for the next child window ParentHwnd = hwnd hwnd = FindWindowX(hwnd, 0, 0, 0) Do While hwnd ''Recursion : this function calls itself to find child windows of the child windows, ''so all descendants, not just one level of child windows FoundHwnd = FindWindowHandle(hwnd, SelectClass, SelectText, bSelect) If FoundHwnd <> 0 Then Exit Do End If '' FindWindowX is called repeatedly to find the next child window hwnd = FindWindowX(ParentHwnd, hwnd, 0, 0) Loop FindWindowHandle = FoundHwnd End Function
第二个片段展示了如何发送鼠标点击到一个隐藏的窗口:
Private Sub SendLeftClick(ByVal hwnd As Long, ByVal hwnd2 As Long, x As Long, y As Long) ''Send Left mouse click to invisible window with handle hwnd and with top-level parent window hwnd2 Dim position As Long ''Set window as active window Call SetActiveWindow(hwnd) ''Calculate lParam to pass the mouses x and y position in the window, (x and y in pixels) position = x * &H10000 + y ''The required messages with their wParam and lParam were found by using Spy++ Call SendMessage(hwnd, WM_MOUSEACTIVATE, ByVal hwnd2, _ ByVal CLng(&H2010001)) ''lParam is HTCLIENT(=1, low) and WM_LBUTTONDOWN(= &H201, high) Call SendMessage(hwnd, WM_SETCURSOR, ByVal CLng(0), ByVal CLng(&H2010001)) Call SendMessage(hwnd, WM_LBUTTONDOWN, ByVal CLng(1), ByVal position) Call SendMessage(hwnd, WM_LBUTTONUP, ByVal CLng(0), ByVal position) End Sub兴趣点
这个应用程序是用VB6写的,比起.NET我更喜欢VB6。而且个人认为,只要有VB6和一些API调用,那么一切都能完成。当然,如果你喜欢其他的编程语言,也可以改写源代码,如果你熟悉API的话,这很容易的,因为API函数是这个应用程序的核心。
许可证这篇文章,以及任何相关的源代码和文件,根据 The Code Project Open License (CPOL)。
译文链接:
英文原文:PDF to BMP using Adobe Reader and API Functions
翻译作者:玩赚乐(www.banghui.org)– 小峰
[转载必须在正文中标注并保留原文链接、译文链接和译者等信息。]
I 相关 / Other
一觉起来,发现眼睛又红又肿、又痒又疼,我们的第一反应是去看医生。事实上,许多眼睛症状其实自己在家就能
每次我怀疑有内存泄漏时,我都要翻箱倒柜找这些命令。所以,这里总结一下以备后用:首先,我用下面的命令监
根据周枕琴(曾任国民政府军政部军需署长)孙子周宏涛的说法,辛亥革命之后,因为革命经费十分困难,孙中山
FE华人杰2016夏季新品以“自由行走”为主题发布会于12月7-9日隆重召开
自由行走,在时光的流转中审视当下与未来,这是华人杰的宗旨。它希望让女性在繁琐的环境中解脱,更
【多图慎点】1.钻石城的旅馆里有这么一个夹食物机好多人说这个是摆设,根本夹不出来然后我幸运 10 的角色执