zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    Irrlicht_0.1源码学习(3)—Irrlicht.cpp & include/Irrlicht.h
    Irrlicht_0.1源码学习(2)—引擎目录结构
    Irrlicht_0.1源码学习(1)—Welcome to the Irrlicht Engine
    Visual Studio 2013 编译时 "error LNK2026:模块对于 SAFESEH 映像是不安全的" 解决方案
    Windows平台下Lua环境的搭建
    系统调用与API
    前端学习技巧分享
    简单的bootstarp项目实例
    js显示表单的提交验证
    拷贝一张图片,从一个目录到另外一个目录下(PS:是拷贝是不是移动)
  • 原文地址:https://www.cnblogs.com/DxSoft/p/1673601.html
Copyright © 2011-2022 走看看