Delphi版 关于QQ输入控件无法Spy到句柄的实现方案可行性研究

简介:

    QQ2009版本的界面,和以前的版本有个显著的不同,就是无法通过Spy++抓到界面上某些元素的句柄了,对于这个技术的实现方案,相信好多人都有一些揣度,实现方法怎样,有人说是应用的DirectUI技术,也有人说是用反Hook,等等一些列的说道!在这,我也说说我的一点看法!我说的一种方法不属于以上的任何一种方法。至于如何,且听我慢慢道来!此思路,来源于一个偶然,在聊天窗口失去焦点与获得焦点时的一个偶然。

  聊天的时候,我们要输入信息,首先要让窗口获得焦点!然后输入框也要获得焦点,才能输入。那么我们可以想象一下,在Delphi中什么情况下的控件时没有句柄的,用Delphi的同僚都知道,TGraphicControl继承下来的控件都没有焦点,既然如此,那么咱们就可以有一个混淆视听的方式,写的控件都从TGraphicControl继承来写,那么肯定就没句柄的,这个Button,ScrollBar等不必体现输入的,我相信没有争议,那么我实现一个编辑框Edit,也从TGraphicControl继承来写!这样,别人不就无法找到这个编辑框的句柄了么?嘿嘿,此时一定会有很多人大惑不解,那么输入呢,从TGraphicControl继承的Edit,如何实现输入?难道全部自己模拟消息来实现输入?当然不是,如果这样,那将让工作量增大N倍而不尽然能成功!重点就在这里,这是,我们可以在内部放一个TEdit,本Edit是活动的,在鼠标点下,或者模拟获得焦点的时候,我们将内置的Edit的Parent设置成我们从TGraphicControl继承的Edit的Parent,也就是Edt.parent := self.parent;并且设置内置Edit的区域,然后在内置Edit.setFocus,这样就能够输入了,然后当这个内置Edit失去焦点的时候,我们将内置Edit的显示文字抓成图片,之后,将内置edit的parent设置为nil,然后在在这个GrphicControl的Edit的对应区域绘制上我们抓取出来的那个真实Edit的图片,这样,内置的Edit已经不再本界面上了,从而当外部Spy++在Spy的时候,就无法找到那个Edit进而进行信息的获取等操作了!这便是我的实现思路。那么就可以想象,QQ聊天窗口在我们要输入信息的时候,获得焦点了,RichEdit的parent为QQ聊天窗口,然后我们输入信息,当信息输入完成,我们离开了之后,将内部的RichEdit的parent设置为nil,然后再将RichEdit的画面获得到绘制到原来的位置上去。这样 ,我们就无法Spy到RichEdit的句柄了。

下面给出俺的模拟代码:

这个代码中的DxEdit就是了,大家可用Spy查一下,肯定是查不到句柄的说!呵呵!

不过这个只是实现了一个简单的模拟而已,如果要完全达到QQ的那个效果,还有许多其他工作要做,这里仅提供一个实现的思路参考

下载

 

复制代码
{不得闲2010-2-25}
unit
 Unit4;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

type
TDxEdit 
=   class (TGraphicControl)
private
edt: TEdit;
edtbndrect: TRect;
bmp: TBitmap;
OldEdtwndproc: TWndMethod;
protected
procedure  Paint; override ;
procedure  HookedtWndProc( var  msg: TMessage);
procedure  MouseDown(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer); 
override ;
procedure  SetParent(AParent: TWinControl); override ;
public
constructor  Create(AOwner: TComponent);
procedure  BeforeDestruction; override ;
destructor  Destroy; override ;
end ;
TForm4 
=   class (TForm)
procedure  FormCreate(Sender: TObject);
private
{  Private declarations  }
public
{  Public declarations  }
medt,edt2: TDxEdit;
end ;

var
Form4: TForm4;
implementation

var
edt: TEdit;
type
TWControl 
=   class (TWinControl)  end ;

procedure  GetControlBitmap(Control: TWinControl;bmp: TBitmap);
var
ControlWidth,ControlHeight: integer;
ControlDc,hCaptureDC: HDC;
begin
ControlWidth :
=  Control.ClientWidth;
ControlHeight :
=  Control.ClientHeight;
ControlDc :
=  GetDC(Control.Handle);
hCaptureDC :
=  CreateCompatibleDC(ControlDc);
bmp.Handle :
= CreateCompatibleBitmap(ControlDc,ControlWidth,ControlHeight);
SelectObject(hCaptureDC,bmp.Handle);

BitBlt(hCaptureDC,
0 , 0 ,ControlWidth,ControlHeight,ControlDc, 0 , 0 ,SRCCOPY);
ReleaseDC(GetDesktopWindow,ControlDc);
DeleteDC(hCaptureDC);
end ;
{ $R *.dfm }

procedure  TForm4.FormCreate(Sender: TObject);
begin
medt :
=  TDxEdit.Create(self);
medt.Parent :
=  self;

edt2 :
=  TDxEdit.Create(self);
edt2.Parent :
=  self;
edt2.Left :
=   150 ;
edt2.Top :
=   10 ;
end ;

{  TDxEdit  }

procedure  TDxEdit.BeforeDestruction;
begin

inherited ;
end ;

constructor  TDxEdit.Create(AOwner: TComponent);
begin
inherited ;
edtbndrect :
=  Rect( 0 , 0 , 0 , 0 );
bmp :
=  TBitmap.Create;
Cursor :
=  crIBeam;
Height :
=   21 ;
Width :
=   121 ;
end ;

destructor  TDxEdit.Destroy;
begin
inherited ;
bmp.Free;
end ;

procedure  TDxEdit.HookedtWndProc( var  msg: TMessage);
begin
OldEdtwndproc(msg);
case  msg.Msg  of
WM_KILLFOCUS:
begin
GetControlBitmap(edt,bmp);
// bmp.SaveToFile( ' C:\1.bmp ' );
edtbndrect.Left :
=   2 ;
edtbndrect.Top :
=  (Height  -  edt.Height)  div   2 ;
edtbndrect.Right :
=  edtbndrect.Left  +  edt.Width;
edtbndrect.Bottom :
=  edtbndrect.Top  +  edt.Height;
edt.Parent :
=   nil ;
end ;
end ;

end ;

procedure  TDxEdit.MouseDown(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer);
begin
inherited ;
if  Button  =  mbLeft  then
begin
if  edt  =   nil   then
begin
edt :
=  TEdit.Create( nil );
OldEdtwndproc :
=  edt.WindowProc;
edt.WindowProc :
=  HookedtWndProc;
edt.BorderStyle :
=  bsNone;
edt.Height :
=   14 ;
end ;
edt.Left :
=  Left  +   2 ;
edt.Top :
=  top  +  (Height  -  edt.Height)  div   2 ;
edt.Width :
=  Width  -   4 ;
edt.Parent :
=  self.Parent;
edt.SetFocus;
// edt.SelLength : =   0 ;
end ;
end ;

procedure  TDxEdit.Paint;
begin
Canvas.Brush.Color :
=  clWhite;
Canvas.FillRect(ClientRect);
Canvas.Brush.Color :
=  clBlue;
Canvas.FrameRect(ClientRect);
// 然后开始绘制文字
if  (edt  <>   nil and  (edt.Parent  =   nil then
begin
// bmp : =  TBitmap.Create;
// GetControlBitmap(edt);
if  edtbndrect.Left  <>  edtbndrect.Right  then

Canvas.CopyRect(edtbndrect,bmp.Canvas,bmp.Canvas.ClipRect);
end ;
end ;


procedure  TDxEdit.SetParent(AParent: TWinControl);
begin
inherited ;

end ;

initialization

finalization

end .
复制代码

  不得闲作于2010-2-25


本文转自 不得闲 博客园博客,原文链接:http://www.cnblogs.com/DxSoft/archive/2010/02/25/1673601.html   ,如需转载请自行联系原作者


相关文章
|
编解码 小程序 前端开发
微信小程序自定义顶部导航栏并适配不同机型
自定义导航栏是小程序中不可或缺的一个组件,它能够为用户提供清晰的页面结构和功能指引,提高用户体验和操作效率。在实现自定义导航栏时,需要考虑不同机型的适配问题,确保导航栏在不同设备上都能正常显示和使用。同时,还需要注意导航栏的设计风格与页面整体风格的一致性,以及导航项的布局和交互方式等细节问题。
723 4
微信小程序自定义顶部导航栏并适配不同机型
|
iOS开发 MacOS 智能硬件
如何搭建远程控制家中设备的Home Assistant智能家居系统【内网穿透】(下)
如何搭建远程控制家中设备的Home Assistant智能家居系统【内网穿透】
665 0
|
7月前
|
人工智能 Java 测试技术
Blackbox.Ai体验:AI编程插件如何提升开发效率
Blackbox.ai 是一款广受好评的AI集成平台,汇聚了多个知名AI助手,如deepseek-R1、ChatGPT-4o等,并深度集成到VSCode中。用户无需频繁上传文件,直接在编辑器内与AI对话,极大提升了开发效率。其特色功能包括自动化网页生成、代码翻译和测试用例自动生成。无论是代码生成、翻译还是审查,Blackbox.ai都能高效智能地完成任务,成为开发者不可或缺的得力工具。现可免费试用90天高级模型,官网:&lt;https://www.blackbox.ai/&gt;。
351 14
|
程序员 API 计算机视觉
技术经验解读:【python自动化】02.pywin32库自动操作键鼠(保姆级代码注释)
技术经验解读:【python自动化】02.pywin32库自动操作键鼠(保姆级代码注释)
384 0
|
存储 NoSQL 关系型数据库
数据存储架构的演进和实操(一)
数据存储架构的演进和实操(一)
|
Linux API C++
音视频windows安装ffmpeg6.0并使用vs调试源码笔记
音视频windows安装ffmpeg6.0并使用vs调试源码笔记
515 0
|
小程序 安全 Android开发
微信小程序中识别HTML标签的方法
微信小程序中识别HTML标签的方法
575 1
|
存储 缓存 编解码
FFmpeg开发笔记(九):ffmpeg解码rtsp流并使用SDL同步播放
FFmpeg开发笔记(九):ffmpeg解码rtsp流并使用SDL同步播放
FFmpeg开发笔记(九):ffmpeg解码rtsp流并使用SDL同步播放
|
监控 Java 测试技术
SpringBoot 如何使用 JProfiler 进行性能测试
SpringBoot 如何使用 JProfiler 进行性能测试
|
数据采集 Web App开发 IDE
玫瑰花变蚊子血,自动化无痕浏览器对比测试,新贵PlayWright Vs 老牌Selenium,基于Python3.10
Selenium一直都是Python开源自动化浏览器工具的王者,但这两年微软开源的PlayWright异军突起,后来者居上,隐隐然有撼动Selenium江湖地位之势,本次我们来对比PlayWright与Selenium之间的差异,看看曾经的玫瑰花Selenium是否会变成蚊子血。
玫瑰花变蚊子血,自动化无痕浏览器对比测试,新贵PlayWright Vs 老牌Selenium,基于Python3.10