QQ2009版本的界面,和以前的版本有個顯著的不同,就是無法通過Spy++抓到界面上某些元素的句柄了,對于這個技術(shù)的實(shí)現(xiàn)方案,相信好多人都有一些揣度,實(shí)現(xiàn)方法怎樣,有人說是應(yīng)用的DirectUI技術(shù),也有人說是用反Hook,等等一些列的說道!在這,我也說說我的一點(diǎn)看法!我說的一種方法不屬于以上的任何一種方法。至于如何,且聽我慢慢道來!此思路,來源于一個偶然,在聊天窗口失去焦點(diǎn)與獲得焦點(diǎn)時的一個偶然。
聊天的時候,我們要輸入信息,首先要讓窗口獲得焦點(diǎn)!然后輸入框也要獲得焦點(diǎn),才能輸入。那么我們可以想象一下,在Delphi中什么情況下的控件時沒有句柄的,用Delphi的同僚都知道,TGraphicControl繼承下來的控件都沒有焦點(diǎn),既然如此,那么咱們就可以有一個混淆視聽的方式,寫的控件都從TGraphicControl繼承來寫,那么肯定就沒句柄的,這個Button,ScrollBar等不必體現(xiàn)輸入的,我相信沒有爭議,那么我實(shí)現(xiàn)一個編輯框Edit,也從TGraphicControl繼承來寫!這樣,別人不就無法找到這個編輯框的句柄了么?嘿嘿,此時一定會有很多人大惑不解,那么輸入呢,從TGraphicControl繼承的Edit,如何實(shí)現(xiàn)輸入?難道全部自己模擬消息來實(shí)現(xiàn)輸入?當(dāng)然不是,如果這樣,那將讓工作量增大N倍而不盡然能成功!重點(diǎn)就在這里,這是,我們可以在內(nèi)部放一個TEdit,本Edit是活動的,在鼠標(biāo)點(diǎn)下,或者模擬獲得焦點(diǎn)的時候,我們將內(nèi)置的Edit的Parent設(shè)置成我們從TGraphicControl繼承的Edit的Parent,也就是Edt.parent := self.parent;并且設(shè)置內(nèi)置Edit的區(qū)域,然后在內(nèi)置Edit.setFocus,這樣就能夠輸入了,然后當(dāng)這個內(nèi)置Edit失去焦點(diǎn)的時候,我們將內(nèi)置Edit的顯示文字抓成圖片,之后,將內(nèi)置edit的parent設(shè)置為nil,然后在在這個GrphicControl的Edit的對應(yīng)區(qū)域繪制上我們抓取出來的那個真實(shí)Edit的圖片,這樣,內(nèi)置的Edit已經(jīng)不再本界面上了,從而當(dāng)外部Spy++在Spy的時候,就無法找到那個Edit進(jìn)而進(jìn)行信息的獲取等操作了!這便是我的實(shí)現(xiàn)思路。那么就可以想象,QQ聊天窗口在我們要輸入信息的時候,獲得焦點(diǎn)了,RichEdit的parent為QQ聊天窗口,然后我們輸入信息,當(dāng)信息輸入完成,我們離開了之后,將內(nèi)部的RichEdit的parent設(shè)置為nil,然后再將RichEdit的畫面獲得到繪制到原來的位置上去。這樣 ,我們就無法Spy到RichEdit的句柄了。
下面給出俺的模擬代碼:
這個代碼中的DxEdit就是了,大家可用Spy查一下,肯定是查不到句柄的說!呵呵!
不過這個只是實(shí)現(xiàn)了一個簡單的模擬而已,如果要完全達(dá)到QQ的那個效果,還有許多其他工作要做,這里僅提供一個實(shí)現(xiàn)的思路參考
{不得閑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.