网上流传着使用 pdg2 控件 IT_Pdg01 接口 CopyToClipBoard 方法将 .pdg 文件转换为图片的方法,不少读者在根据该方法进行实践的时候发现调用 v3.8 及以后版本控件的 CopyToClipBoard 方法是无效的。
笔者通过使用 IDA Pro 对 v3.8 控件反向工程,发现只有调用了 LocateRect 方法后,才能使 CopyToClipBoard 方法有效。由于 LocateRect 方法需读者操作鼠标选择复制范围,完全不能用于大批量转换工作。所以,笔者将要讲解跳过 LocateRect 方法的途径。
先给出 CopyToClipBoard 方法的原型声明:
void CopyToClipBoard([in] unsigned long left, [in] unsigned long top, [in] unsigned long right, [in] unsigned long bottom);
再给出 CopyToClipBoard 方法汇编代码,如下:
.text: 10004460 mov ebp, esp
.text: 10004462 sub esp, 0FCh
.text: 10004468 push ebx
.text: 10004469 push esi
.text:1000446A push edi
.text:1000446B mov edi, ecx
.text:1000446D mov [ebp + t_pdg01], edi
.text: 10004470 mov eax, [edi + 3DE8h] ; rect.right
.text: 10004476 mov esi, [edi + 3DE0h] ; rect.left
.text:1000447C mov ecx, [edi + 3DE4h] ; rect.top
.text: 10004482 mov edx, [edi + 3DECh] ; rect.bottom
.text: 10004488 mov [ebp + rect_right], eax
.text:1000448B sub eax, esi ; width
.text:1000448D mov [ebp + rect_top], ecx
.text: 10004490 mov [ebp + rect_bottom], edx
.text: 10004493 jnz short loc_1000449D
.text: 10004495 sub edx, ecx ; height
.text: 10004497 jz return_false
.text:1000449D
.text:1000449D loc_1000449D: ; CODE XREF: CopyToClipBoard + 34
.text:1000449D cmp dword ptr [edi + 3D98h], 0 ; bLocateRect ?
.text:100044A4 jz return_false
.text:100044AA mov eax, [edi + 60h]
.text:100044AD cmp dword ptr [edi + 2584h], 0
.text:100044B4 lea ebx, [edi + 60h]
.text:100044B7 mov [ebp + var_50], eax
.text:100044BA jnz short loc_100044C2
.text:100044BC push 0
.text:100044BE push 0
.text:100044C0 jmp short loc_100044D9
地址10004470 - 10004487,可知 CopyToClipBoard 方法并未使用方法参数中的 right 和 bottom,而是将 LocateRect 方法获取到的鼠标选定范围读取了出来。
地址1000449D,可知 CopyToClipBoard 方法还需判断 LocateRect 方法是否在之前被调用过。如果未调用过,则退出 CopyToClipBoard 方法。
通过对 get_PageWidth 和 get_PageHeight 方法反向工程,又知 [edi+2184h] 和 [edi+2188h] 分别存有当前页面的宽度和高度。
为使 CopyToClipBoard 方法不受限,可修改汇编代码为:
.text: 10004460 mov ebp, esp
.text: 10004462 sub esp, 0FCh
.text: 10004468 push ebx
.text: 10004469 push esi
.text:1000446A push edi
.text:1000446B mov edi, ecx
.text:1000446D mov [ebp + t_pdg01], edi
.text: 10004470 mov eax, [edi + 2184h] ; PageWidth
.text: 10004476 mov esi, [edi + 3DE0h] ; rect.left
.text:1000447C mov ecx, [edi + 3DE4h] ; rect.top
.text: 10004482 mov edx, [edi + 2188h] ; PageHeight
.text: 10004488 mov [ebp + rect_right], eax
.text:1000448B sub eax, esi ; width
.text:1000448D mov [ebp + rect_top], ecx
.text: 10004490 mov [ebp + rect_bottom], edx
.text: 10004493 jnz short loc_1000449D
.text: 10004495 sub edx, ecx ; height
.text: 10004497 jz return_false
.text:1000449D
.text:1000449D loc_1000449D: ; CODE XREF: CopyToClipBoard + 34
.text:1000449D cmp dword ptr [edi + 3D98h], 0 ; bLocateRect ?
.text:100044A4 nop
.text:100044A5 nop
.text:100044A6 nop
.text:100044A7 nop
.text:100044A8 nop
.text:100044A9 nop
.text:100044AA mov eax, [edi + 60h]
.text:100044AD cmp dword ptr [edi + 2584h], 0
.text:100044B4 lea ebx, [edi + 60h]
.text:100044B7 mov [ebp + var_50], eax
.text:100044BA jnz short loc_100044C2
.text:100044BC push 0
.text:100044BE push 0
.text:100044C0 jmp short loc_100044D9