MyException - 我的异常网
当前位置:我的异常网» Delphi » (继续问有关问题):想要获取和设置没有句柄的组件TEX

(继续问有关问题):想要获取和设置没有句柄的组件TEXT内容应该如何做

www.MyException.Cn  网友分享于:2013-02-23  浏览:99次
(继续问问题):想要获取和设置没有句柄的组件TEXT内容应该怎么做?
RT~~~~~~~~~~~感谢各位大力支持,问题这几天已经解决很多了,最后就剩这个问题了,我用鼠标取当前窗口句柄,但是发现有些组件的句柄是无法获取的,有的即使取得了句柄用SendMessage也无法对其Text赋值,高手帮忙~~~~~~~~~~~~

------解决方案--------------------
这个就比较有难度,没有句柄的控件是通过DrawText()这样的API直接绘制到窗体上的
可以参考:《Hook其他程序中的StringGrid的内容》
http://www.delphibbs.com/keylife/iblog_show.asp?xid=12219
但这种方法只对同版本VCl程序有用
另外种办法就是参考屏幕取词的办法,截获API
针对指定的程序要好处理一些,可以尝试分析进程内存存储的规律得到
------解决方案--------------------
原贴见 http://www.delphibbs.com/delphibbs/dispq.asp?LID=2942729

1.根据StringGrid组件的句柄,想直接通过消息如WM_GETTEXT等来获取StringGrid的内容,显然不可行,普通的Windows消息不能直接获取到某个Cell的内容,TStringGrid并不是Windows的组件,而是Delphi自己的组件,它的Cell内容是存放在TStrings列表中的。
2.根据鼠标所在的位置,通过屏幕取词的技术,是可以Hook到鼠标下的某个Cell的内容,但在实际应用中也不可行,因为不是所有想Hook的Cell都是在显示区可见的,而ApiHook的屏幕取词技术要求Cell的文本重画,才能取得其内容。

既然上面两种方法都不可行,那么我们就要寻找新的方法。
1.思考
由于StringGrid是Delphi自写的组件,而不是Windows的控件,因此要获取StringGrid的某个Cell的内容,只能是获取到StringGrid的对象实例,才能以StringGrid.Cell[X, Y]这样的方式取得任意Cell的内容。
2.启发
在Delphi中,在自己的程序中,用FindControl,是可以根据组件对象的句柄获得对象实例的。那么我们在Hook其他程序的时候能不能采用这种方法来获取StringGrid对象的实例呢?这有个问题,即使我们能够获取到StringGrid的对象实例,但是返回的实例地址是个在其他程序进程地址空间的私有地址( <2GB),这在我们的程序中是无法进行访问的。这个问题不难解决,屏幕取词技术不也是截获到了其他程序的屏幕输出文本吗!?
3.实现
有了上面的思考和启发,那我们就能整理出一个思路来啦。
a.写一个DLL,将Hook StringGrid的代码都放在DLL中,在DLL中,还要包括GetMessage钩子的代码,目的是为了能通过全局钩子将DLL注入到目标程序,使Hook StringGrid的代码运行在目标进程中,这样就可以正确使用FindControl返回的StringGrid实例(也只有在目标进程内调用FindControl,才能够返回StringGrid实例地址)。
b.注入到目标进程的Hook功能,我们怎么进行控制呢?我们怎么让Hook代码知道我们要Hook哪个Cell的内容?怎么询问得知目标StringGrid的行数、列数,以进行正确的遍历获取Cell?... 通过内存映射进行Hook DLL和主程序的数据共享,就可以啦。不过这样实用时不是很方便,因为需要在目标进程中执行Hook代码,显然不能直接调用Hook DLL中的函数,在GetMessage钩子回调函数中来做,也不是很妥当,控制不方便。最好的方法就是在目标进程中创建一个隐形窗口,在该隐形窗口的消息处理中作文章。我们可以通过发送消息的方式通知隐形窗口,执行Hook代码。OK!
c.按照上面的思路,我编写了HookSG.dll和测试程序,不过并没有Hook得到想要的结果。是哪里出了问题呢?分析上面的流程,最大的可能就是FindControl并返回实际的StringGrid对象实例,否则,后面的StringGrid.Cells[X, Y]这样的获取Cell内容的代码是断不会有问题的,我也能够确认Hook的代码是在目标进程中执行的。查看FindControl的源代码:
function FindControl(Handle: HWnd): TWinControl;
var
OwningProcess: DWORD;
begin
Result := nil;
if (Handle <> 0) and (GetWindowThreadProcessID(Handle, OwningProcess) <> 0) and
(OwningProcess = GetCurrentProcessId) then // 都进行了判断调用进程ID是否为Handle所在进程
begin
if GlobalFindAtom(PChar(ControlAtomString)) = ControlAtom then
Result := Pointer(GetProp(Handle, MakeIntAtom(ControlAtom)))
else
Result := ObjectFromHWnd(Handle);
end;
end;
function ObjectFromHWnd(Handle: HWnd): TWinControl;
var
OwningProcess: DWORD;
begin
if (GetWindowThreadProcessID(Handle, OwningProcess) <> 0) and
(OwningProcess = GetCurrentProcessID) then
Result := Pointer(SendMessage(Handle, RM_GetObjectInstance, 0, 0))
else
Result := nil;
end;
再看InitControls中:
procedure InitControls;
var
UserHandle: HMODULE;
begin
WindowAtomString := Format( 'Delphi%.8X ',[GetCurrentProcessID]);
WindowAtom := GlobalAddAtom(PChar(WindowAtomString));
ControlAtomString := Format( 'ControlOfs%.8X%.8X ', [HInstance, GetCurrentThreadID]);
ControlAtom := GlobalAddAtom(PChar(ControlAtomString));
RM_GetObjectInstance := RegisterWindowMessage(PChar(ControlAtomString));
...
end;
问题就在这里啦。ControlAtomString是根据模块句柄(模块加载基地址)和线程ID动态生成的,目标进程的模块基地址就是EXE基地址,一般是0x00400000,但DLL的模块加载基地址就不是这个了,默认是0x10000000,而实际上可能因为这个地址已经被占用(有其他DLL被加载到这个地址)而进行重定位,所以初始化时添加的Atom和目标进程的ControlAtom就不一样,FindControl当然就不能找到StringGrid对象实例啦。
清楚了这一点,解决起来就简单了,我们自己写个FindControl函数,以目标进程基地址来动态生成ControlAtomString,添加ControlAtom不就可以啦。在DLL中取EXE的基地址,用GetModuleHandle(nil)即可。
OK。解决了这些问题,Hook其他程序的StringGrid的内容就水到渠成,没什么障碍啦。

补充:
上面提到的方法,不仅仅可以Hook其他程序的StringGrid的内容,实际上还可以获取更多的从TWinControl继承的窗口组件的内容、属性、...,拥有了对象的实例,你基本上就拥有了对对象的完全控制。

文章评论

总结2014中国互联网十大段子
总结2014中国互联网十大段子
老美怎么看待阿里赴美上市
老美怎么看待阿里赴美上市
看13位CEO、创始人和高管如何提高工作效率
看13位CEO、创始人和高管如何提高工作效率
写给自己也写给你 自己到底该何去何从
写给自己也写给你 自己到底该何去何从
如何区分一个程序员是“老手“还是“新手“?
如何区分一个程序员是“老手“还是“新手“?
10个帮程序员减压放松的网站
10个帮程序员减压放松的网站
聊聊HTTPS和SSL/TLS协议
聊聊HTTPS和SSL/TLS协议
程序员都该阅读的书
程序员都该阅读的书
10个调试和排错的小建议
10个调试和排错的小建议
我的丈夫是个程序员
我的丈夫是个程序员
如何成为一名黑客
如何成为一名黑客
程序员最害怕的5件事 你中招了吗?
程序员最害怕的5件事 你中招了吗?
程序员的鄙视链
程序员的鄙视链
程序员应该关注的一些事儿
程序员应该关注的一些事儿
旅行,写作,编程
旅行,写作,编程
“懒”出效率是程序员的美德
“懒”出效率是程序员的美德
亲爱的项目经理,我恨你
亲爱的项目经理,我恨你
代码女神横空出世
代码女神横空出世
5款最佳正则表达式编辑调试器
5款最佳正则表达式编辑调试器
十大编程算法助程序员走上高手之路
十大编程算法助程序员走上高手之路
程序员必看的十大电影
程序员必看的十大电影
编程语言是女人
编程语言是女人
什么才是优秀的用户界面设计
什么才是优秀的用户界面设计
初级 vs 高级开发者 哪个性价比更高?
初级 vs 高级开发者 哪个性价比更高?
为什么程序员都是夜猫子
为什么程序员都是夜猫子
要嫁就嫁程序猿—钱多话少死的早
要嫁就嫁程序猿—钱多话少死的早
 程序员的样子
程序员的样子
程序员周末都喜欢做什么?
程序员周末都喜欢做什么?
程序猿的崛起——Growth Hacker
程序猿的崛起——Growth Hacker
一个程序员的时间管理
一个程序员的时间管理
漫画:程序员的工作
漫画:程序员的工作
程序员眼里IE浏览器是什么样的
程序员眼里IE浏览器是什么样的
老程序员的下场
老程序员的下场
60个开发者不容错过的免费资源库
60个开发者不容错过的免费资源库
科技史上最臭名昭著的13大罪犯
科技史上最臭名昭著的13大罪犯
“肮脏的”IT工作排行榜
“肮脏的”IT工作排行榜
Java程序员必看电影
Java程序员必看电影
Web开发人员为什么越来越懒了?
Web开发人员为什么越来越懒了?
那些争议最大的编程观点
那些争议最大的编程观点
不懂技术不要对懂技术的人说这很容易实现
不懂技术不要对懂技术的人说这很容易实现
Web开发者需具备的8个好习惯
Web开发者需具备的8个好习惯
程序员的一天:一寸光阴一寸金
程序员的一天:一寸光阴一寸金
我跳槽是因为他们的显示器更大
我跳槽是因为他们的显示器更大
程序员和编码员之间的区别
程序员和编码员之间的区别
为啥Android手机总会越用越慢?
为啥Android手机总会越用越慢?
软件开发程序错误异常ExceptionCopyright © 2009-2015 MyException 版权所有