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) div2;
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 =nilthen
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) div2;
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.

 

    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) div2;
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 =nilthen
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) div2;
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.
posted @ 2012-01-06 23:47  许明吉博客  阅读(814)  评论(0编辑  收藏  举报