(转载)屏幕抓字原理

ZengXi 2002-02-07 12:28:39
屏幕抓字技术揭密(转载)
整理编辑:China ASP

屏幕抓字技术揭密
----------深入WINDOWS内部探险手记

郑州 马飞涛

一 公开它!

四通利方和金山词霸的用户都曾见识过屏幕抓字技术,鼠标指哪就翻译哪个
单词,这个技术看似简单,其实在WINDOWS系统中实现却是非常复杂和有趣的。
经过半年多的艰辛探索,笔者终于破解了其中的秘密,并在今天决定公开它,这
个人人都曾见过但是却鲜有人知的秘密,这个只被几家软件公司垄断从未在公开
的报刊资料披露过只言片语的秘密!
回想这半年多的探索,其中浸润了多少笔者的苦闷与欢乐,绝望与兴奋,挫折
与收获,现在都终于有了结果:将屏幕抓字技术的秘密公开,献给孜孜不倦辛勤
工作的程序员们。如果这样做能为国产软件事业的发展效微薄之力,对笔者来说
,也是一桩快事!

二 初识屏幕抓字

最初知道屏幕抓字, 是在购买了〖英汉通〗软件之后。 当时笔者还只是一
个VISUAL BASIC 的初学者, 对 WINDOWS 系统内部的知识了解并不多, 认为在
WINDOWS系统中屏幕抓字的实现应该和DOS系统中的一样,调用一个DOS 中断取屏
幕上的字符或直接读显示内存的内容就可以了。

三 看似很简单,其实不然

随着对WINDOWS系统的认识不断深入,才发现问题并不象想得那么简单。首先,翻
阅了WINODWS应用程序接口(API)中的上千个函数,并没有发现有一个现成的类
似于getWordFromPoint()的函数;根据使用经验,经过判断发现屏幕抓字采用的
也不是图像识别技术;翻阅了SDK的联机文档中没有,DDK的联机文档中也没有;
显示卡编程接口的资料则很难获得,有的也只是CGA到VGA显存的基本知识。回想
当时坐在机子前,面对一屏屏的联机资料(如果是纸,将堆积如山),感觉就是
在黑暗中的大海里航行,没有方向,没有灯光,但强烈的兴趣紧抓着我,一定要
把这个谜解开。

四 选择合适的编程工具

突然又有了一些新的想法:
可否试着截获WINDOWS中关于字符的消息呢?
DC(设备描述表)到底是什么?
WINDOWS的TextOut函数是否将TEXT放在DC的某个单元中?
显然,用VISUAL BASIC就力不从心了。在DOS中用TURBO C编程笔者还算熟练
,因此先尝试用VISUAL C++,但是奇慢的编译速度使人难以忍受, 高度抽象的类
让人一头雾水,开发商务软件可能还行,但开发这样一个深入WINDOWS 内部的系
统软件,望着一堆缠绕不清的类和消息,真有点牛刀宰鸡、刺刀耕田的感觉。

最后选择了DELPHI,第一印象是编译速度真快,在我的祖父型386 机子上
编译一个WINDOWS程序,速度和用TURBOC的速度感觉差不多,真让人兴奋得爱不释
手。随着不断使用,发觉DELPHI真是一个好的快速开发工具,(快速并不意味着
简单粗糙,而是和WINDOWS系统有混然一体良好接口的表现)让初学者也很容易上
手。
调用各种WINDOWS 函数(包括很多未公开的函数)都非常直接迅速,用它来作
开发工具,大有刺刀见红、一剑封喉的痛快感觉。

五 山穷水尽疑无路

随着对WINDOWS系统了解的深入,我逐渐明白了在向屏幕输出文字时,WINDO
WS系统仅仅只是对某个应用程序发送WM_PAINT消息,告诉该应用程序窗口用户区
已经“无效”而需要重画。具体的“绘制”工作(选择字体,颜色,文字)由应
用程序完成。
应用程序在处理WM_PAINT消息时,调用BeginPaint和EndPaint来获得和释放
设备描述表,调用DrawText、ExtTextOut、 TextOut等函数在设备描述表中“绘
制”文字。
应用程序“绘制”文字, 就象学生(应用程序)奉命(获得 WM_PAINT消息
) 用老师(WINDOWS)提供的画笔(DrawText ExtTextOut TextOut等) 在黑板上画
画一样,虽然大家能看到画的是什么字,但是画笔作为绘图工具并不知道画的是
什么。

老师(WINDOWS)不知道学生(应用程序)到底用什么字体,颜色,画哪些文字。


   总之 ,WINDOWS并不知道应用程序“绘制”的是什么。“文字”对 WINDOW
S来说只是画笔留在黑板(屏幕)上的粉笔印,只是绘画的痕迹。“文字”只存在
于应用程序的模块中,对WINDOWS系统是“不可见”的。
到处走投无路,真想掂5000块钱,跑到“英汉通”公司买回这个秘密。仔细
一想,钱太少,就是多掂10倍,人家也不一定说。

六 柳暗花明又一村

经过再三考虑,我联想到在DOS系统中编程,会采取改变中断向量地址, 设
置新的中断向量的技术:如果系统调用这个中断,就会先进入新的中断服务程序
,然后再调用原来的中断服务程序。
那末,在WINDOWS系统中也采取这种技术,使系统如果调用某个函数, 先进
入一个跟踪函数,取得原函数的参数,再调用原来的函数。听起来是否象病毒传
染和发作?其实很多程序都采用过类似技术。大学毕业设计声卡时我就用过。至
此, 我认识到应该放弃常规的思路, 采取一些技巧, 截获 TextOut、ExtText
Out等函数,使之转向我的跟踪函数,在此查看应用程序(学生)的堆栈中传递给
画笔(TextOut、ExtTextOut等函数)的参数, 从而获得应用程序要在屏幕上写
的“文字”。

七 “ 屏幕抓字”的实现

1 用SetWindowsHookEx()安装鼠标钩子MouseProc;
2 在屏幕上移动鼠标时,系统就会调用鼠标钩子MouseProc;
3 进入MouseProc,获得鼠标的坐标(x,y),设置对TextOut()、ExtTextOut()等
的跟踪程序,
用invalidateRect()告诉系统该点(x,y)“失效”;
4 系统发出WM_PAINT消息,指示该点(x,y)处的应用程序重绘“失效”的区域。

5 负责绘制该点()的应用程序在受到 WM_PAINT 消息后, 就有机会调用
TextOut()、 ExtTextOut()等函数。
6 调用的函数被拦截进入跟踪程序:设置好了的跟踪程序截获了该次调用,从应
用程序的堆栈中取出 该点(x,y)“文字”的指针;
7 从应用程序的数据段中将“文字”指针的内容取出,即完成了一次“屏幕抓字
”;
8 退出跟踪程序,返回到鼠标钩子MouseProc;
9 在MouseProc中解除对TextOut() ExtTextOut()的跟踪;
10 退出MouseProc鼠标钩子程序,控制权交给系统。
11 在屏幕上移动鼠标,开始下一次“屏幕抓字”,返回步骤2。

八 前景展望
掌握了“屏幕抓字”的技术秘密,稍加改变,我们就可对WINDOWS 系统中
的任意一个函数调用进行动态地拦截、跟踪、修改和恢复,就可让WINDOWS 系统
中的任意一个函数按我们的设想工作,就可构造自己的外挂汉字平台,设计改变
字体的放大镜、改变颜色的变色镜,保护视力的软件视保屏等等。

九 后记

希望此文能抛砖引玉,为大家编程时能找到捷径,开拓出新的思路;
对拦截、跟踪感兴趣的朋友也请来信交流切磋,如需DLL 或“抓字”的源
代码,敬请与 mafeitao@371.net 联系;
如能得到“四通利方”、“金山词霸”、“英汉通”等公司的教导与指正
,笔者不胜感激。

...全文
103 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
zyht 2002-02-07
  • 打赏
  • 举报
回复
佩服佩服
紫郢剑侠 2002-02-07
  • 打赏
  • 举报
回复
我对这个也有兴趣。

purpleendurer@163.com
dancemaple 2002-02-07
  • 打赏
  • 举报
回复
收藏
no7beckham 2002-02-07
  • 打赏
  • 举报
回复
你有没有啊?有的话就发份给我吧!
谢谢了!bow!
no7beckham@sina.com
BraveYang 2002-02-07
  • 打赏
  • 举报
回复
多 多
多多多 多多多多
多多 多多多多 多多多
多多多 多多多 多多多
多多多 多多多 多多多
多多多多 多多多多多多多多 多多多
多多多多多多多多多多多多 多多多
多多多多 多多多 多多多
多多多多 多多多 多多多多
多 多多多多 多多多 多多多多多多
多多多多多多多 多多多 多多多多多多多多多多多多多
多多多多多多多 多多多多 多多多多多多多多多多多多多
多多多多多多 多多多 多多多多多多 多多多
多 多多 多多多多多多多 多多 多多多
多多多 多多多多多多多多多 多多多 多多多
多多多 多多多多 多多多多 多多多 多多多
多多多多多多 多多 多多 多多 多多多
多多多多多 多多 多多 多多多
多多多多多 多多多 多多 多多
多多多 多多多 多多 多多
多多多 多多多多 多多 多多
多多 多多多多多 多多
多多多多 多多多多多多多
多多多 多多多多多多
多多多多多
多多
braveyang@263.net
Liusp 2002-02-07
  • 打赏
  • 举报
回复
给我一份吧,liusp@Anyi.com.cn
aliyan 2002-02-07
  • 打赏
  • 举报
回复
我也要。。。谢谢aliyan@163.com
wdmusb 2002-02-07
  • 打赏
  • 举报
回复
能否也给我发一份源代码?不胜感激!wangshuo@eyou.com
小伍老师 2002-02-07
  • 打赏
  • 举报
回复
里还厉害
我也要 0xft0@163.com
票票飞扬 2002-02-07
  • 打赏
  • 举报
回复
能否给我发一份源代码?
genphone_ru@163.net
cobi 2002-02-07
  • 打赏
  • 举报
回复
收藏
BraveYang 2002-02-07
  • 打赏
  • 举报
回复
有一点疑问跟踪程序是如何截获TextOut()、 ExtTextOut()等函数的调用的
blackfish 2002-02-07
  • 打赏
  • 举报
回复
我也要,谢谢!
blackfish988@sohu.com

5,392

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 开发及应用
社区管理员
  • VCL组件开发及应用社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧