朋友叫我帮忙写个从博易读取数据的工具,可无奈数据所在控件并不是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,收工了。

读取TDrawGrid之获取博易数据的更多相关文章

  1. 获取博客积分排名,存入数据库,读取数据进行绘图(python,selenium,matplotlib)

    该脚本的目的:获取博客的排名和积分,将抓取时间,排名,积分存入数据库,然后把最近的积分和排名信息进行绘图,查看积分或者排名的变化情况. 整个脚本的流程:是利用python3来编写,利用selnium获 ...

  2. 程序间获取ALV显示数据(读取ALV GRID上的数据)

    程序间获取ALV数据的两种方法: 方法1:通过修改SUBMIT的目标程序,把内表EXPORT到内存,SUBMIT后IMPORT ,该方法需要修改目标程序,可以任意设置目标程序的中断点: * Execu ...

  3. 以多进程读取oss符合条件的数据为例,综合使用多进程间的通信、获取多进程的数据

    import datetime import sys import oss2 from itertools import islice import pandas as pd import re im ...

  4. js进阶ajax读取json数据(ajax读取json和读取普通文本,和获取服务器返回数据(链接)都是一样的,在url处放上json文件的地址即可)

    js进阶ajax读取json数据(ajax读取json和读取普通文本,和获取服务器返回数据(链接)都是一样的,在url处放上json文件的地址即可) 一.总结 ajax读取json和读取普通文本,和获 ...

  5. OpenGL ES无法获取贴图数据原因

    最近在做一个项目,要从贴图中获取图像数据,查了很多资料,也琢磨很久,获取到的数据都是0.终于在一次偶然的机会,发现了端倪,成功了. 不得不说这"一分灵感"真的很重要 以下是在获取贴 ...

  6. 使用腾讯开发平台获取QQ用户数据资料

    <今天是七夕:祝大家七夕嗨皮,前可么么哒,后可啪啪啪> Tips:本篇博客将教你如何使用腾讯开发平台获取QQ用户资料 ----------------------------------- ...

  7. java 正则表达式的应用:读取文件,获取其中的电话号码

    1.正则表达式 正则表达式,又称正规表示法.常规表示法(英语:Regular Expression,在代码中常简写为regex.regexp或RE),计算机科学的一个概念.正则表达式使用单个字符串来描 ...

  8. ajax post data 获取不到数据,注意 content-type的设置

    ajax post  data  获取不到数据,注意 content-type的设置 .post/get关于 jQuery data 传递数据.网上各种获取不到数据,乱码之类的.好吧今天我也遇到了,网 ...

  9. jQuery获取JSON格式数据方法

    getJSON方法: jQuery.getJSON(url,data,success(data,status,xhr)) $("button").click(function(){ ...

随机推荐

  1. C#批量插入数据到Sqlserver中的四种方式

    我的新书ASP.NET MVC企业级实战预计明年2月份出版,感谢大家关注! 本篇,我将来讲解一下在Sqlserver中批量插入数据. 先创建一个用来测试的数据库和表,为了让插入数据更快,表中主键采用的 ...

  2. mysql中,sleep进程过多,如何解决?

    睡眠连接过多,会对mysql服务器造成什么影响? 严重消耗mysql服务器资源(主要是cpu, 内存),并可能导致mysql崩溃. 造成睡眠连接过多的原因? 1. 使用了太多持久连接(个人觉得,在高并 ...

  3. 【HTML5&CSS3进阶04】CSS3动画应该如何在webapp中运用

    动画在webapp的现状 webapp模式的网站追求的就是一个体验,是HTML5&CSS3浪潮下的产物,抛开体验不说,webapp模式门槛比较高: 而体验优化的一个重点便是动画,可以说动画是w ...

  4. SVG坐标系统

    SVG的画布.画布视区(viewBox).浏览器视窗的概念 画布 画布是绘制SVG内容的一块区域,理论上在所有维度上都是无限的.(也有人称为"SVG世界",但我觉得叫画布比较合适) ...

  5. Atittit.研发公司的组织架构与部门架构总结

    Atittit.研发公司的组织架构与部门架构总结 1. archi组织架构与 部门规划2 1.1. 最高五大组织机构2 1.2. 宗教事务部2 1.3. 制度与重大会议委员会2 1.4. 纠纷处理部: ...

  6. Android LocalBroadcastManager 的使用总结

    转载请标明出处:http://www.cnblogs.com/zhaoyanjun/p/6048369.html 本文出自[赵彦军的博客] 前言 在Android中,Broadcast是一种广泛运用的 ...

  7. c++宏定义命令

    在程序开始以#开头的命令,他们是预编译命令.有三类预编译命令:宏定义命令.文件包含命令.条件编译命令:今天聊聊宏定义: 宏定义命令将一个标识符定义为一个字符串,源程序中的该标识符均以指定的字符串来代替 ...

  8. JavaScript标准参考教材(alpha)--笔记

    一.导论 二.基本语法 1.严格来说var a=1与a=1效果不太一样,delete命令无法删除前者. JavaScirpt是一种动态类型语言,也就是说,变量的类型没有限制,可以赋予各种类型的值. J ...

  9. c#批量插入数据库Demo

    using System; using System.Collections.Generic; using System.Configuration; using System.Data; using ...

  10. 原创 C++应用程序在Windows下的编译、链接:第三部分 静态链接(二)

    3.5.2动态链接库的创建 3.5.2.1动态链接库的创建流程 动态链接库的创建流程如下图所示: 在系统设计阶段,主要的设计内容包括:类结构的设计以及功能类之间的关系,动态链接库的接口.在动态链接库中 ...