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 ,如需转载请自行联系原作者