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