读取TDrawGrid之获取博易数据

朋友叫我帮忙写个从博易读取数据的工具,可无奈数据所在控件并不是Windows标准控件,也就是说没办法通过发送系统消息来获取

相关数据,于是乎试了一下从内存直接读取,可最后并不能达到预期目的,原因是笔者并不能从内存中找出和TDrawGrid对应的关系。

(如果有网友知道的可以赐教。)

最后实在没办法了,直接用上了Hook API,有的网友可能想到了,Hook Gdi32.dll中相应的文本输出函数,没错,我选择的是TextOutA。

思路如下:

1. 编写一个Dll,用于注入博易并Hook TextOutA。

TextOutA原型如下:  
BOOL TextOut(
HDC hdc, // 设备描述表句柄
int nXStart, // 字符串的开始位置 x坐标
int nYStart, // 字符串的开始位置 y坐标
LPCTSTR lpString, // 字符串
int cbString // 字符串中字符的个数
);

我们可以通过WindowFromDC来获取hdc相应的窗口的hWnd,并通过GetClassName来获取窗口的类,从而来判断当前所绘画的文本是不是输入TDrawGrid。
获取完数据后,通过WM_COPYDATA消息来发送相应的lpString到目标处理工具。

2. 编写用于接收数据的客户端。

 

部分代码如下:

__TextOutA proc hdc:DWORD,nXStart:DWORD,nYStart:DWORD,lpString:DWORD,cbString
	local cds:COPYDATASTRUCT
	local hwnd:DWORD
	
	invoke RestoreApi,hid_TextOutA,1
	invoke WindowFromDC,hdc
	mov hwnd,eax
	invoke GetClassName,hwnd,offset szClassName,255
	mov eax,offset szClassName
	mov eax,[eax]
	.if eax==061724454h
		invoke IsWindowVisible,hwnd
		.if eax
			invoke FindWindow,0,offset szMainRecv
			.if eax
				push esi
				push eax
				
				mov esi,offset sBuffer
				invoke RtlZeroMemory,esi,255
				
				mov eax,nXStart
				mov [esi],eax
				mov eax,nYStart
				mov [esi+4],eax
				
				mov eax,esi
				add eax,8
				
				invoke RtlMoveMemory,eax,lpString,cbString
				
				mov eax,cbString
				add eax,8
				mov cds.cbData,eax
				mov cds.lpData,esi
				mov cds.dwData,0
				invoke GetPixel,hdc,1,1
				mov cds.dwData,eax
				
				pop eax
				push ebx
				mov ebx,eax
				invoke SendMessage,ebx,WM_COPYDATA,0,addr cds
				pop ebx
				
				pop esi
			.endif
		.endif
	.endif
	
	invoke TextOut,hdc,nXStart,nYStart,lpString,cbString
	invoke RestoreApi,hid_TextOutA,0
	ret
__TextOutA endp
Public Function InterceptedCallBack(ByVal hwnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
        If uMsg = WM_COPYDATA Then
                Dim cbs As COPYDATASTRUCT
                Dim md As MyData
                
                CopyMemory ByVal VarPtr(cbs), ByVal lParam, Len(cbs)
                CopyMemory ByVal VarPtr(md), ByVal cbs.lpData, cbs.cbData
                Debug.Print Hex(cbs.dwData), md.x, md.y, StrConv(md.d, vbUnicode)
         End If
        InterceptedCallBack = CallWindowProc(PrevWndProc, hwnd, uMsg, wParam, lParam)
End Function

VB+Asm代码,比较粗糙,见谅。

然而,TextOutA对于屏幕能看到的才画出来,那么整个TDrawGrid那么多行,要怎么获取所有的数据呢?
笔者通过SendMessage,发送相关滚动条的事件,来达到刷新整个TDrawGrid的目的,这样就OK了。
当然,这样获取到的数据是十分零散的,如下:

 12            355          07-01 09:24                     
 122           355          48860                           
 204           355          48860                           
 286           355          48860                           
 368           355          48860                           
 462           355                 0                        
 535           355              3058                        
 12            380          07-01 09:25                     
 122           380          48860                           
 204           380          48860                           
 286           380          48860                           
 368           380          48860                           
 462           380                 0                        
 535           380              3058                        
 12            405          07-01 09:26                     
 122           405          48860                           
 204           405          48860                           
 286           405          48860                           
 368           405          48860                           
 462           405                 0                        
 535           405              3058                        
 12            355          07-01 09:26                     
 122           355          48860                           
 204           355          48860                           
 286           355          48860                           
 368           355          48860                           
 462           355                 0                        
 535           355              3058            

.......
.......
.......

但实际上只要稍微观察,还是能找出规律,很容易地就能整理数据了。

下面是获取、整理并转换为excel文档的效果图:

 

OK,收工了。

posted @ 2013-07-05 23:20  mez  阅读(1887)  评论(0编辑  收藏  举报