|
第一课 屏幕抓字简介
第二课 相关背景知识
第三课 屏幕抓字的引擎:Tworm
免费下载:用Tworm拦截BeginPaint()的例子BeginPaint.zip 免费下载:用Tworm拦截TextOut()和ExtTextOut()的例子TextOut.zip 实现了“全屏着色”,是“全屏汉化”的基础。
第四课 IE4和IE5下的屏幕抓字
欢迎各路编程高手们使用TWROM,来信交流,指正。向软件公司以低廉优惠的价格提供屏幕抓字的原代码。我的Email: 第一课 屏幕抓字简介
“屏幕抓字”技术在电子字典中得到广泛地应用,又叫“即指即译”,“鼠标取词”,“光标字典”,“屏幕取词”等,在本文中统称为“屏幕抓字”。四通利方和金山词霸的用户都曾见识过屏幕抓字技术,鼠标指哪就翻译哪个单词,这个技术看似简单,其实在WINDOWS系统中实现却是非常复杂和有趣的。其中采用的编程技术也是很独特的,笔者偶有心得,不敢“小园香径独徘徊”,愿领您进入这个全新而奇特的编程领域,并希望能得到各位编程高手的教导和指正。
最初知道屏幕抓字, 是在购买了〖英汉通〗软件之后。 当时笔者还只是一个VISUAL BASIC 的初学者, 对 WINDOWS 系统内部的知识了解并不多, 认为在WINDOWS系统中屏幕抓字的实现应该和DOS系统中的一样,调用一个DOS 中断取屏幕上的字符或直接读显示内存的内容就可以了。 随着对WINDOWS系统的认识不断深入,才发现问题并不象想得那么简单。首先,翻阅了WINODWS应用程序接口(API)中的上千个函数,并没有发现有一个现成的类似于getWordFromPoint()的函数;根据使用经验,经过判断发现屏幕抓字采用的也不是图像识别技术;翻阅了SDK的联机文档中没有,DDK的联机文档中也没有;显示卡编程接口的资料则很难获得,有的也只是CGA到VGA显存的基本知识。回想当时坐在机子前,面对一屏屏的联机资料(如果是纸,将堆积如山),感觉就是在黑暗中的大海里航行,没有方向,没有灯光,但强烈的兴趣紧抓着我,一定要把这个谜解开。 当我经过无数次的死机,终于在WIN9X系统中,完成了在IE4,IE5,OUTLOOK 4,OUTLOOK5,WOED 97,EXCEL 97,WIN HELP,NETSCAPE等各种环境屏幕抓字的编程工作,望着用SOFT-ICE做的厚厚一本的工作笔记,望着凝结了我的艰辛劳动的字字句句,我不由感慨WIN底层编程太难了!这种艰难,习惯于快速程序开发的人可能永远体会不到。
用“鼠标钩子”或“定时器”得到鼠标的位置,如果鼠标移动了,那么在鼠标位置下放置一个很小的窗口,(在我的程序中此窗口高度为1,长度为1,小得象针尖一样)windows系统会发出WM_PAINT消息,指示IE,NETSCAPE等应用程序重绘屏幕,在IE,NETSCAPE等应用程序响应WM_PAINT时,会调用TextOut(),ExtTextOut()等API函数来绘制TEXT,如果我们在IE,NETSCAPE等应用程序的堆栈中拦截到TextOut(),ExtTextOut()的参数,就实现了“屏幕抓字”。 第二课 相关背景知识
屏幕抓字可以采取“鼠标钩子”或“定时器”来得到鼠标的位置。“鼠标钩子”响应速度比较快,但编程技术也比较麻烦,现就“鼠标钩子”做一简介。鼠标钩子函数也可叫做鼠标消息过滤器,是一种回调(CALLBACK)函数,由系统调用。如果用SetWindowsHook或SetWindowsHookEx安装了鼠标钩子函数的地址, 每当在屏幕上移动鼠标时,系统便将控制权交给鼠标钩子函数,这样便使我们能够有机会在鼠标钩子函数内部截获各种鼠标消息,在这些消息还没有送达应用程序队列之前,显示它们,改变它们或直接传给下一个缺省鼠标钩子函数。注意,鼠标钩子函数截获的是系统级消息,而不是单个应用程序队列内的窗口消息;系统发给每个应用程序队列的鼠标消息都可以用鼠标钩子函数来截获。VC的Spy和Delphi的WinSpy均安装了钩子函数用来截获各种系统级的消息,其中就包括鼠标钩子函数,键盘钩子函数,窗口钩子函数等。我们可以通过安装鼠标钩子函数来仿制一个自己的SPY,当鼠标移动时,我们立即获得系统(包括非抢先的Windows3.1和抢先Windows9x)的控制权,在鼠标钩子函数内部实时地截获鼠标消息,显示鼠标的位置和状态以及鼠标下窗口的局柄,标题栏,窗口类,窗口过程地址等。当然也可在鼠标钩子函数内调用InvalidateRect(),InvalidateRgn()来获得屏幕上鼠标下的单词。
举例如下: :BPX GDI!TEXTOUT :G :DW ss:esp 34b7:00008310 0028 01af 0004 0000 3447 0005 0010 093e :DW 3447:0000 (注释:0028是CS,01af是IP,0004是参数COUNT,0005是Y,0010是X,093E是HDC,3447:0000是我们要拦截的LPSZ)
举例如下: :BPX GDI32!TextOutA :G :DD ss:esp 017f:0067f364 00420495 0000093e 00000010 000000005 017f:0067f374 0045163f 00000004 :DD 0045163f (注释:00420495是返回地址,93e是HDC,10是X,5是Y,0045163f是我们要拦截的LPSZ,4是COUNT) 第三课 屏幕抓字的引擎:Tworm
“屏幕抓字”的关键是拦截api 函数,为了安全的考虑,我把拦截跟踪的具体细节封装成了一个类Tworm, 我叫它作蠕虫类,意思是可以钻到别的WINDOWS API的肚子中.这样就不再需要研究原代码,直接调用Tworm可以实现对Windows3.1的 API中任意函数进行拦截,跟踪,改变。我把Tworm编译成Tworm.dcu,在DELPHI中可以用Uses Tworm; 来使用. 在win 9x中,Tworm 照样可以用来拦截32-bit的函数。装了win 98之后,经过这段时间的研究,我发现win 98根本不是象微软宣传的那样是真正的32位操作系统! 拦截win 9x中32位函数的方法很简单,那就是拦截同名的win 3.1中的16位函数,调用我软件包中的TWORW 类通过拦截16位函数就能拦截32位的win 9x中的函数!你可以试一试。
用法如下:(请用DELPHI 1 编译) uses Tworm; var w1,w2:Tworm; {可以声明多个对象w1,w2,w3,对多个函数实施拦截} w1:=Tworm.create; {创建两个新对象} w2:=Tworm.create; w1.oldProc:=getProcAddress(getModuleHandle('gdi','TextOut'); w1.newProc:=getProcAddress(getModuleHandle('my_DLL','myTextOut'); w1.change; {设置拦截1} {....系统调用TextOut时被拦截进入myTextOut;} w1.restore; {解除拦截1} w2.oldProc:=getProcAddress(getModuleHandle('win_api_dll','any_win_api_fun'); w2.newProc:=getProcAddress(getModuleHandle('my_DLL',' my_trace_fun'); w2.change; {设置拦截2} ......系统调用any_win_api_fun()就会被拦截进入my_trace_fun()内部.... ......在my_trace_fun()内部,你可编程干你想干的任何事情......... {即:每一个win api函数都可能被拦截进入我的跟踪函数内部,在我的跟踪函数里,你可以恢复原来的函数,并干任何事情} w2.restore; {解除拦截2} w1.free; {释放对象1} w2.free; {释放对象2}
为了控制拦截技术的流向,考虑到计算机系统安全的原因,我不希望有朝一日,你我自己的计算机会成为采用拦截技术的黑客程序的牺牲品!!! 为此,我在供免费下载的Twrom.dcu的演示版中加入2个限制: 1 每次远行时间超过5分钟后,向您提示这是演示版,并退出。不会耽搁您的编译和调试工作,因为您可以在编译后,通过多次远行Tworm来调试程序。 2 开始运行时,有一声BEEP。
微软说w16的api只是为了兼容性才保留下来,程序员应该尽可能地调用32位的api,实际上根本就不是这样!win 98(也应该包含win 95)内部的32位api大量地调用了win 3.1中同名的16位api,估计可能超过80%的32位api经过变换调用了同名的16位api。可以说win 3.1是win9x的基石,没有win 3.1, win 9x立即就会崩溃。win 9x 的ExtTextOutA,ExtTextOutW,TextOutA,TextOutW等函数就调用了win 3.1中的EXTTEXTOUT,TEXTOUT,千真万确!那么拦截win 9x中32位函数的方法就找到了,那就是拦截同名的win 3.1中的16位函数,调用我软件包中的TWORW 类通过拦截16位函数就能拦截32位的win 9x中的函数!你可以试一试。因为win 9x本身是一种16位与32位代码混合的操作系统,并且很严重地依靠着16位代码, 所以w16 编程可算是win 9x 编程中的秘密武器了,而且将非常厉害!
如果您想购买Tworm的不带任何限制的正式版,您必须遵守:
然后,请和我联系购买不带任何限制的Tworm.dcu的正式版。 我的联系方式:mailto:请与我联系:mafeitao@371.net 第四课 IE4和IE5下的屏幕抓字
我在编写“屏幕抓字”时,在IE4,IE5中遇到的的几个特别之处: 1 在IE4编写屏幕抓字的程序,我遇到的问题是如何拦截统一编码UNICODE。 2 IE4描绘英汉混合的文字时,英语和汉语分别用1个EXTTEXTOUT()输出; 3 IE5测试版(IE 5.00.0518.10)描绘英汉混合的文字时,英语和汉语共用1个EXTTEXTOUT()输出; 4 IE5正式版 (IE 5.00.2014.0216) 描绘文字时,除了英语和汉语共用1个EXTTEXTOUT()输出;还有一个特点:当窗口比较小时,用和IE4,IE5测试版一样定位方法来决定X,Y的值,而在窗口较大时,用相对于每行基准线的定位方法来决定X,Y的值。 5 IE5测试版和正式版对系统的改变不一样,如IE5测试版中,SysListView32窗口类描绘文字用ExtTextoutW(),而在IE4和IE5正式版中用了ExtTextOutA(); 上述4个特点,在编程时少不留意,轻者或是不能拦截,或是不能定位;重者就会使IE的堆栈崩溃,造成死机。 我用了2个星期的时间解决了上述问题,终于在WIN9x系统中,完成了IE4,IE5,NETSCAPE,OUTLOOK EXPRESS4,5,OFFICE 97,等应用程序环境下的屏幕抓字。我把屏幕抓字做成了一个动态连接库,DEMO.DLL,放在 freedict.zip 中,可以供32-bit或16-bit的程序调用。 该DLL的编程原理为:在定时器中判断鼠标位置,如果鼠标移动,在鼠标下放置一个长度为1,高度为1的象针尖一样小的窗口,然后隐藏它;因为针尖窗口“弄脏”了屏幕,WIN9x系统会通知应用程序(IE,NETSCAPE,OFFICE等)重绘该点,应用程序会调用TEXTOUT,TEXTOUTA,TEXTOUTW等函数来描绘TEXT,而TEXTOUT,TEXTOUTA,TEXTOUTW等函数被我早以设好的TWorm拦截,在应用程序的堆栈中得到指向字符串的指针LPSZ,LPSZ所指向的TEXT既是要抓的字。
1:可以拦截Acrobat Reader 3,IE4,IE5测试版,IE5正式版,NETSCAPE,OUTLOOK EXPRESS,FRONTPAGE Express 2,OFFICE97等各种应用程序。 2: 防闪烁功能。重复抓字时,字典窗口的位置会自动锁定。 3:可以和RICH WIN ,XDICT共存,且互不影响。当因为先装载RICH WIN并先退出RICH WIN时,造成不能抓字后,按“reHook”按钮即可恢复抓字功能。 4:可以将抓到的字词传递给32-bit的应用程序。 5:可以抓到动态滚动的字幕中的字词。 6:不影响IE,NETSCAPE等应用程序的运行速度。 7: 在WIN9X中运行很稳定
我对比了XDICT,感到并不逊色,都可以拦截IE5,IE4,运行稳定强壮,与金山词霸和四同立方的兼容性都很好。
欢迎各路编程高手们使用TWROM,来信交流,指正。因为我个人无钱无力来制作有自己版权的英汉字典和汉英字典,所以,我愿向软件公司以低廉优惠的价格提供“屏幕抓字”的原代码。欢迎有志于制作电子字典,内码转换,汉字平台的公司与我联系合作事宜:马飞涛 |
如有关于本站点的问题或建议,请向mafeitao@371.net发邮件。 |
本文引用通告地址: http://blog.csdn.net/silver/services/trackbacks/5460.aspx