句柄2

没有WM_CLICK,我想你说的应该是WM_LBUTTONDOWN,这个就是当被鼠标左键点击时引发的消息;
BM_CLICK是其他窗口发送给按钮控件的消息,让按钮执行点击操作,可以模拟按钮点击;
BN_CLICK是当按钮被点击时,按钮控件发送给按钮控件的父窗口的,告诉父窗口我被点击了
 
///////////////////////
如果BUTTON太多的话,再把GetWindowText也加上,来判断哪一个是你想要的!!
 
 
 
先用FindWindow找主窗口,再用GetDlgItem一级一级往下找子窗口,直到找到你想要的Button
 
假设你的窗口的句柄是:hw   程序如下: 
var
    h1,h2,h3:Thandle;
begin
    h1:=findwindowex(hw,0, 'TButton ',nil);
    h2:=GetNextWindow(h1,GW_HWNDNEXT);
    h3:=GetNextWindow(h2,GW_HWNDNEXT);
    sendmessage(hw,wm_command,BN_CLICKED,h1);//点击第一个按钮
    ...
   
end;
 
////////////////////////////////////////////////////
 
//如果只打开一个记事本的话用下面的代码,如果是有多个的话,需要修改一下枚举窗口时的窗口名
//if pos(sample.txt - 记事本',StrPas(WinText))>0 then
 
unit Unit1;
 
interface
 
uses
 Windows, Messages, SysUtils, Classes, Controls, Forms, StdCtrls;
 
type
 TForm1 = class(TForm)
    Button1: TButton;
    Memo1: TMemo;
    Edit1: TEdit;
    procedure Button1Click(Sender: TObject);
 private
 public
 end;
 
var
 Form1: TForm1;
 HEdit: THandle;
 
implementation
 
{$R *.dfm}
 
//向控件发送字符
procedure SendDBCSString(hFocus: HWND; const sSend: string);
var
 k : integer;
 ch : byte;
begin
 k := 1;
 while k <= Length(sSend) do begin
    ch := byte(sSend[k]);
    if Windows.IsDBCSLeadByte(ch) then
    begin
      Inc(k);
      SendMessage(hFocus, WM_IME_CHAR, MakeWord(byte(sSend[k]), ch), 0);
    end
    else
      SendMessage(hFocus, WM_IME_CHAR, word(ch), 0);
    Inc(k);
 end;
end;
 
//枚举记事本窗口,获取记事本的内容输入框句柄
Function EnumWinProc(Wnd: HWND; Form1: TForm1): Boolean; Export;StdCall;
var
 WinText : Array[0..255] of Char;
begin
 GetWindowText(Wnd, WinText, 255);
 Result := True;
 if pos('记事本',StrPas(WinText))>0 then
 HEdit:=FindWindowEx(WND,0,'Edit','');
end;
 
procedure TForm1.Button1Click(Sender: TObject);
begin
 EnumWindows(@EnumWinProc, LongInt(Self));
 SendDBCSString(HEdit,'预先设定的文字');
end;
 

end.

///////////////////////////////////////////////////

基本上句柄是标志窗口,我可以根据句柄又可引申其中更多如类名,windowtitle等属性所以基于这点,一般开发工具会提供查句柄,查类名等工具,vs提供的spy++就是一个很好例子。现在教你们一查句柄知多少。其实也简单,下面贴出源代码。

procedure Tform1.TimerTimer(Sender: TObject);
  var
  Pos: TPoint;
  Handle: HWND;
  ScreenDC: HDC;
  Buf: array[0..1024] of Char;
  ScreenColor: COLORREF;
  begin
  GetCursorPos(Pos); // 得到当前光标位置
  Handle := WindowFromPoint(Pos); // 返回当前位置的句柄
  HandleText.Caption := IntToStr(Handle);
  GetClassName(Handle, Buf, 1024); // 得到类名
  ClassNameText.Caption := Buf;
  SendMessage(Handle, WM_GETTEXT, 33, Integer(@Buf)); // 得到标题
  TitleText.Caption := Buf;
  { 得到光标处点的颜色 }
  ScreenDC := GetDC(0);
  ScreenColor := GetPixel(ScreenDC, Pos.X, Pos.Y);
  Shape.Brush.Color := TColor(ScreenColor);
  RGBColorText.Caption := ': ' + IntToStr(GetRValue(ScreenColor)) +
  绿: ' + IntToStr(GetGValue(ScreenColor)) + '  : ' +
  IntToStr(GetBValue(ScreenColor));
  ReleaseDC(0, ScreenDC);
  DelphiColorText.Caption := Format('Delphi中颜色值:$00%2.2x%2.2x%2.2x', [GetBValue(ScreenColor),
  GetGValue(ScreenColor), GetRValue(ScreenColor)]);
  HTMLColorText.Caption := Format('HTML颜色值:#%2.2x%2.2x%2.2x', [GetRValue(ScreenColor),
  GetGValue(ScreenColor), GetBValue(ScreenColor)]);
  end; 

/////////////////////////////////////////////////////////////////////////////////////////////

SendMessage(TreeView.Handle,TVM_SETBKCOLOR,0,RGB(255,0,0)); 设置TV背景颜色

SendMessage(Button.Handle,WM_LBUTTONDOWN,0,0);
  鼠标左键按下
SendMessage(Button.Handle,WM_LBUTTONUP,0,0);
   鼠标左键抬起
SendMessage(Edit.Handle,WM_SETTEXT,255,Integer(PChar('abc')));
 传递文本
SendMessage(Edit.Handle,WM_Char,Wparam('Q'),2);
  传递字符
SendMessage(Button.Handle,BM_SETSTYLE,BS_RADIOBUTTON,1);
  改变Button风格
SendMessage(ComboBox.Handle,CB_SETDROPPEDWIDTH,300,0);
  改变CBDownWidth
WM_CUT
WM_COPYWM_PASTE  剪切,复制,粘帖

实现任意组合键
keybd_event(VK_Control, MapVirtualKey(VK_Control, 0), 0, 0);
keybd_event(ord('V'), MapVirtualKey(ord('V'), 0), 0, 0);
keybd_event(ord('V'), MapVirtualKey(ord('V'), 0), KEYEVENTF_KEYUP, 0);
keybd_event(VK_Control, MapVirtualKey(VK_Control, 0), KEYEVENTF_KEYUP, 0);

SendMessageA
说明:       调用一个窗口的窗口函数,将一条消息发给那个窗口。除非消息处理完毕,否则该函数不会返回SendMessage所包含4个参数:    
1.       hwnd       32
位的窗口句柄窗口可以是任何类型的屏幕对象,因为Win32能够维护大多数可视对象的句柄
2.       wMsg      
用于区别其他消息的常量值,这些常量可以是Windows单元中预定义的常量,也可以是自定义的常量
3.       wParam      
通常是一个与消息有关的常量值,也可能是窗口或控件的句柄
4.       lParam      
通常是一个指向内存中数据的指针。由于WParmlParamPointer都是32位的,因此,它们之间可以相互转换
wMsg
函数    
WM_CREATE       创建一个窗口
WM_DESTROY       当一个窗口被破坏时发送
WM_MOVE       移动一个窗口
WM_SIZE       改变一个窗口的大小
WM_ACTIVATE       一个窗口被激活或失去激活状态
WM_SETFOCUS       一个窗口获得焦点
WM_KILLFOCUS       一个窗口失去焦点
WM_ENABLE       一个窗口改变成Enable状态
WM_SETREDRAW       设置窗口是否能重画
WM_SETTEXT       应用程序发送此消息来设置一个窗口的文本
WM_GETTEXT       应用程序发送此消息来复制对应窗口的文本到缓冲区
WM_GETTEXTLENGTH       得到与一个窗口有关的文本的长度(不包含空字符)
WM_PAINT       要求一个窗口重画自己
WM_CLOSE       当一个窗口或应用程序要关闭时发送一个信号
WM_QUERYENDSESSION       用户选择结束对话框或程序自己调用ExitWindows函数
WM_QUIT       用来结束程序运行
WM_QUERYOPEN       用户窗口恢复以前的大小位置时,把此消息发送给某个图标
WM_ERASEBKGND       当窗口背景必须被擦除时(例在窗口改变大小时)
WM_SYSCOLORCHANGE       当系统颜色改变时,发送此消息给所有顶级窗口
WM_QUERYENDSESSION       消息后,此消息发送给应用程序,通知它对话是否结束
WM_SHOWWINDOW       当隐藏或显示窗口是发送此消息给这个窗口
WM_ACTIVATEAPP       发此消息给应用程序哪个窗口是激活的,哪个是非激活的    
WM_FONTCHANGE       当系统的字体资源库变化时发送此消息给所有顶级窗口
WM_TIMECHANGE       当系统的时间变化时发送此消息给所有顶级窗口
WM_CANCELMODE       发送此消息来取消某种正在进行的摸态(操作)
WM_SETCURSOR       如果鼠标引起光标在某个窗口中移动
WM_ENDSESSION       当系统进程发出且鼠标输入没有被捕获时,就发消息给某个窗口
WM_MOUSEACTIVATE       当光标在某个非激活的窗口中而用户正按着鼠标的某个键发送此消息给当前窗口
WM_CHILDACTIVATE       送此消息给MDI子窗口当用户点击此窗口的标题栏,或当窗口被激活,移动,改变大小
WM_QUEUESYNC     此消息由基于计算机的训练程序发送,通过       WH_JOURNALPALYBACKhook程序分离出用户输入消息
WM_GETMINMAXINFO       此消息发送给窗口当它将要改变大小或位置    
WM_PAINTICON       发送给最小化窗口当它图标将要被重画
WM_ICONERASEBKGND       此消息发送给某个最小化窗口,仅当它在画图标前它的背景必须被重画
WM_NEXTDLGCT发送此消息给一个对话框程序去更改焦点位置
WM_SPOOLERSTATUS       每当打印管理列队增加或减少一条作业时发出此消息    
WM_DRAWITEM       buttoncomboboxlistboxmenu的可视外观改变时发送
WM_MEASUREITEM       button,       combobox,       listbox,       listview       control,       or       menuitem       被创建时
WM_VKEYTOITEM       此消息有一个LBS_WANTKEYBOARDINPUT风格的发出给它的所有者来响应WM_KEYDOWN消息    
WM_CHARTOITEM       此消息由一个LBS_WANTKEYBOARDINPUT风格的列表框发送给他的所有者来响应WM_CHAR消息    
WM_SETFONT       当绘制文本时程序发送此消息得到控件要用的颜色
WM_GETFONT       应用程序发送此消息得到当前控件绘制文本的字体
WM_SETHOTKEY       应用程序发送此消息让一个窗口与一个热键相关连
WM_GETHOTKEY       应用程序发送此消息来判断热键与某个窗口是否有关联
WM_QUERYDRAGICON       此消息发送给最小化窗口,当此窗口将要被拖放而它的类中没有定义图标,应用程序能返回一个图标或光标的句柄,当用户拖放图标时系统显示这个图标或光标
WM_COMPAREITEM       发送此消息来判定comboboxlistbox新增加的项的相对位置
WM_COMPACTING       显示内存已经很少了
WM_WINDOWPOSCHANGING       发送此消息给那个窗口的大小和位置将要被改变时,来调用setwindowpos函数或其它窗口管理函数
WM_WINDOWPOSCHANGED       发送此消息给那个窗口的大小和位置已经被改变时,来调用setwindowpos函数或其它窗口管理函数
WM_POWER       当系统将要进入暂停状态时发送此消息
WM_COPYDATA       当一个应用程序传递数据给另一个应用程序时发送此消息
WM_CANCELJOURNA       当某个用户取消程序日志激活状态,提交此消息给程序
WM_NOTIFY       当某个控件的某个事件已经发生或这个控件需要得到一些信息时,发送此消息给它的父窗口    
WM_INPUTLANGCHANGEREQUEST       当用户选择某种输入语言,或输入语言的热键改变
WM_INPUTLANGCHANGE       当平台现场已经被改变后发送此消息给受影响的最顶级窗口
WM_TCARD       当程序已经初始化windows帮助例程时发送此消息给应用程序
WM_HELP       此消息显示用户按下了F1,如果某个菜单是激活的,就发送此消息个此窗口关联的菜单,否则就发送给有焦点的窗口,如果当前都没有焦点,就把此消息发送给当前激活的窗口
WM_USERCHANGED       当用户已经登入或退出后发送此消息给所有的窗口,当用户登入或退出时系统更新用户的具体设置信息,在用户更新设置时系统马上发送此消息
WM_NOTIFYFORMAT       公用控件,自定义控件和他们的父窗口通过此消息来判断控件是使用ANSI还是UNICODE结构

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Delphi获取其它进程窗口句柄的3种方法

Delphi获取其它进程窗口句柄的3种方法
━━━━━━━━━━━━━━━━━━━━━━━━━━

作者:张国斌

    本文主要跟大家介绍Delphi中获取其它进程的窗口句柄,在Delphi中获取其它进程的窗口句柄,绝大部分人首先想到的会使用:FindWindow或者用GetWindow来遍历查找,如:

handle := FindWindow(nil,PChar('窗口的标题'));
或者:
procedure TForm1.Button1Click(Sender: TObject);
var
  hCurrentWindow: HWnd;
  WndText:String;
begin
  hCurrentWindow := GetWindow(Handle, GW_HWNDFIRST);
  while hCurrentWindow <> 0 do
  begin
    WndText:=GetWndText(hCurrentWindow);
    if UpperCase(WndText)='窗口的标题' then begin
      ...
      ...
    end;
    hCurrentWindow:=GetWindow(hCurrentWindow, GW_HWNDNEXT);
  end;
end;

    因为目前网络上绝大部分的代码都是介绍用这两种方法取得其它进程的窗口句柄。虽这两种方法都可以达到查找其它进程的窗口句柄的目的,但本人认为这两都方法存在较大的弊端。因为这两种方法都是根据其它进程的标题来查找的,如果其它进程的标题在运行时不断的发生变化,那么这两种方法就无法没办法用了。


   
今天给大家介绍第三种通过进程的文件名来查找窗口句柄。首先通过进程快照得到要查找的进程ID(ProcessId),其次,再跟据ProcessId获取进程的窗口句柄。以下为本文章的代码:


uses TLHelp32;

procedure TForm1.Button1Click(Sender: TObject);
var
ProcessName : string; //
进程名
FSnapshotHandle:THandle; //
进程快照句柄
FProcessEntry32:TProcessEntry32; //
进程入口的结构体信息
ContinueLoop:BOOL;
MyHwnd:THandle;
begin
FSnapshotHandle:=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0); //
创建一个进程快照
FProcessEntry32.dwSize:=Sizeof(FProcessEntry32);
ContinueLoop:=Process32First(FSnapshotHandle,FProcessEntry32); //
得到系统中第一个进程
//
循环例举   
while ContinueLoop do  
begin
    ProcessName := FProcessEntry32.szExeFile;

    if(ProcessName = '要找的应用程序名.exe') then begin
      MyHwnd := GetHWndByPID(FProcessEntry32.th32ProcessID);
      ...

      ...
    end;
    ContinueLoop:=Process32Next(FSnapshotHandle,FProcessEntry32);
end;
CloseHandle(FSnapshotHandle);   //  
释放快照句柄
end;


//
跟据ProcessId获取进程的窗口句柄

function TForm1.GetHWndByPID(const hPID: THandle): THandle;
type
    PEnumInfo = ^TEnumInfo;
    TEnumInfo = record
    ProcessID: DWORD;
    HWND: THandle;
    end;

    function EnumWindowsProc(Wnd: DWORD; var EI: TEnumInfo): Bool; stdcall;
    var
    PID: DWORD;
    begin
    GetWindowThreadProcessID(Wnd, @PID);
    Result := (PID <> EI.ProcessID) or
        (not IsWindowVisible(WND)) or
        (not IsWindowEnabled(WND));

    if not Result then EI.HWND := WND;
    end;

    function FindMainWindow(PID: DWORD): DWORD;
    var
    EI: TEnumInfo;
    begin
    EI.ProcessID := PID;
    EI.HWND := 0;
    EnumWindows(@EnumWindowsProc, Integer(@EI));
    Result := EI.HWND;
    end;
begin
    if hPID<>0 then
    Result:=FindMainWindow(hPID)
    else
    Result:=0;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

当光标被另外一个线程掌握时,就无法用GetCursor()应用接口获得光标句柄。本文阐述如何在任何线程掌握光标时都能够获取光标句柄。

 

=========================================================

 

{

 当光标被另外一个线程掌握时,就无法用GetCursor()应用接口获得光标句柄。

 本文阐述如何在任何线程掌握光标时都能够获取光标句柄。

 例如,想在屏幕截取程序中放置光标时该如何做。

}

 

function GetCursorHandle: HCURSOR;

var

 hWindow: HWND;

 pt: TPoint;

 pIconInfo: TIconInfo;

 dwThreadID, dwCurrentThreadID: DWord;

begin

 // 检查哪个窗体掌握光标

 GetCursorPos(pt);

 hWindow := WindowFromPoint(pt);

 

 // 获得光标所有者的线程ID

 dwThreadID := GetWindowThreadPRocessId(hWindow, nil);

 

 // 获得当前线程的ID

 dwCurrentThreadID := GetCurrentThreadId;

 

 // 如果光标所有者的线程不是当前线程,就要把光标所有者的线程配属到当前线程。

 //然后调用GetCursor()来获得正确的光标句柄(hCursor)

 

 if (dwCurrentThreadID <> dwThreadID) then

 begin

    if AttachThreadInput(dwCurrentThreadID, dwThreadID, True) then

    begin

      // 获得光标句柄

      Result := GetCursor;

      AttachThreadInput(dwCurrentThreadID, dwThreadID, False);

    end;

 end else

 begin

    Result := GetCursor;

 end;

end;

 

procedure TForm1.Button1Click(Sender: TObject);

var

 CurPosX, CurPoxY: Integer;

 MyCursor: TIcon;

 pIconInfo: TIconInfo;

begin

 MyCursor := TIcon.Create;

 try

    MyCursor.Handle := GetCursorHandle;

    // 获得光标位置

    GetIconInfo(MyCursor.Handle, pIconInfo);

    CurPosX := pIconInfo.xHotspot;

    CurPoxY := pIconInfo.yHotspot;

    // 在窗体上画出光标

    Canvas.Draw(CurPoxY, CurPoxY, MyCursor);

 finally

 

当光标被另外一个线程掌握时,就无法用GetCursor()应用接口获得光标句柄。本文阐述如何在任何线程掌握光标时都能够获取光标句柄。

 

=========================================================

 

{

 当光标被另外一个线程掌握时,就无法用GetCursor()应用接口获得光标句柄。

 本文阐述如何在任何线程掌握光标时都能够获取光标句柄。

 例如,想在屏幕截取程序中放置光标时该如何做。

}

 

function GetCursorHandle: HCURSOR;

var

 hWindow: HWND;

 pt: TPoint;

 pIconInfo: TIconInfo;

 dwThreadID, dwCurrentThreadID: DWORD;

begin

 // 检查哪个窗体掌握光标

 GetCursorPos(pt);

 hWindow := WindowFromPoint(pt);

 

 // 获得光标所有者的线程ID

 dwThreadID := GetWindowThreadProcessId(hWindow, nil);

 

 // 获得当前线程的ID

 dwCurrentThreadID := GetCurrentThreadId;

 

 // 如果光标所有者的线程不是当前线程,就要把光标所有者的线程配属到当前线程。

 //然后调用GetCursor()来获得正确的光标句柄(hCursor)

 

 if (dwCurrentThreadID <> dwThreadID) then

 begin

    if AttachThreadInput(dwCurrentThreadID, dwThreadID, True) then

    begin

      // 获得光标句柄

      Result := GetCursor;

      AttachThreadInput(dwCurrentThreadID, dwThreadID, False);

    end;

 end else

 begin

    Result := GetCursor;

 end;

end;

 

procedure TForm1.Button1Click(Sender: TObject);

var

 CurPosX, CurPoxY: Integer;

 MyCursor: TIcon;

 pIconInfo: TIconInfo;

begin

 MyCursor := TIcon.Create;

 try

    MyCursor.Handle := GetCursorHandle;

    // 获得光标位置

    GetIconInfo(MyCursor.Handle, pIconInfo);

    CurPosX := pIconInfo.xHotspot;

    CurPoxY := pIconInfo.yHotspot;

    // 在窗体上画出光标

    Canvas.Draw(CurPoxY, CurPoxY, MyCursor);

 finally

    MyCursor.ReleaseHandle;

    MyCursor.Free;

 end;

end;

 

// 另外一种解决办法:

 

procedure TForm1.Timer1Timer(Sender: TObject);

var

 CI: TCursorInfo;

begin

 CI.cbSize := SizeOf(CI);

 GetCursorInfo(CI);

 Image1.Picture.Icon.Handle := CI.hCursor;

end;

 

    MyCursor.ReleaseHandle;

    MyCursor.Free;

 end;

end;

 

// 另外一种解决办法:

 

procedure TForm1.Timer1Timer(Sender: TObject);

var

 CI: TCursorInfo;

begin

 CI.cbSize := SizeOf(CI);

 GetCursorInfo(CI);

 Image1.Picture.Icon.Handle := CI.hCursor;

end;

 

 

 

资料引用:http://www.knowsky.com/335397.html

////////////////////////////////////////////////////////////////////////////////////////////////////////////

Delphi~通过程序窗体句柄获取程序路径

引用PsAPI

var
  h:HWND;
  pid: Cardinal;
  pHandle: THandle;
  buf: array[0..MAX_PATH] of Char;
begin
  h:=GetForegroundWindow; //
获取当前激活的窗体句柄
  GetWindowThreadProcessId(h, @pid); //
通过句柄获取其进程ID
  pHandle := OpenProcess(PROCESS_ALL_ACCESS, False, pid);//
通过进程ID获取进程句柄
  GetModuleFileNameEx(pHandle, 0, buf, Length(buf));//
通过进程句柄获取其模块路径
  CloseHandle(pHandle);
  Edit1.Text:= buf;
end;//
把它放进一个Timer里,半秒获取一次。。。

 

//////////////////////////////////////////////////////////////////////////////////////////////////////////

delphi实现句柄关闭迅雷

dos命令:
TASKKILL /F /IM thunder5.exe
delphi命令:
var
  H: THandle;
  Process, ProcessId: Cardinal;
begin
  H := FindWindow('Afx:400000:0:0:0:807b3', nil);
  GetWindowThreadProcessId(H, ProcessId);
  Process := OpenProcess(PROCESS_ALL_ACCESS, False, ProcessId);
  TerminateProcess(Process, 0);
end;

方法:
apy++查找类名 或者用进程快照定位都可以!
窗口类名:
Afx:400000:0:0:0:807b3

效果如图:

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Delphi 关于QQ输入控件无法Spy到句柄的实现方案可行性研究

2010619日联系商易上海电子商务网站建设,了解更多

 

 


Delphi
关于QQ输入控件无法Spy到句柄的实现方案可行性研究

 

 

 

    QQ2009版本的界面,和以前的版本有个显著的不同,就是无法通过Spy++抓到界面上某些元素的句柄了,对于这个技术的实现方案,相信好多人都有一些揣度,实现方法怎样,有人说是应用的DirectUI技术,也有人说是用反Hook,等等一些列的说道!在这,我也说说我的一点看法!我说的一种方法不属于以上的任何一种方法。至于如何,且听我慢慢道来!此思路,来源于一个偶然,在聊天窗口失去焦点与获得焦点时的一个偶然。

 

 聊天的时候,我们要输入信息,首先要让窗口获得焦点!然后输入框也要获得焦点,才能输入。那么我们可以想象一下,在Delphi中什么情况下的控件时没有句柄的,用Delphi的同僚都知道,TGraphicControl继承下来的控件都没有焦点,既然如此,那么咱们就可以有一个混淆视听的方式,写的控件都从TGraphicControl继承来写,那么肯定就没句柄的,这个Button,ScrollBar等不必体现输入的,我相信没有争议,那么我实现一个编辑框Edit,也从TGraphicControl继承来写!这样,别人不就无法找到这个编辑框的句柄了么?嘿嘿,此时一定会有很多人大惑不解,那么输入呢,从TGraphicControl继承的Edit,如何实现输入?难道全部自己模拟消息来实现输入?当然不是,如果这样,那将让工作量增大N倍而不尽然能成功!重点就在这里,这是,我们可以在内部放一个TEdit,本Edit是活动的,在鼠标点下,或者模拟获得焦点的时候,我们将内置的EditParent设置成我们从TGraphicControl继承的EditParent,也就是Edt.parent := self.parent;并且设置内置Edit的区域,然后在内置Edit.setFocus,这样就能够输入了,然后当这个内置Edit失去焦点的时候,我们将内置Edit的显示文字抓成图片,之后,将内置editparent设置为nil,然后在在这个GrphicControlEdit的对应区域绘制上我们抓取出来的那个真实Edit的图片,这样,内置的Edit已经不再本界面上了,从而当外部Spy++Spy的时候,就无法找到那个Edit进而进行信息的获取等操作了!这便是我的实现思路。那么就可以想象,QQ聊天窗口在我们要输入信息的时候,获得焦点了,RichEditparentQQ聊天窗口,然后我们输入信息,当信息输入完成,我们离开了之后,将内部的RichEditparent设置为nil,然后再将RichEdit的画面获得到绘制到原来的位置上去。这样 ,我们就无法SpyRichEdit的句柄了。

 

下面给出俺的模拟代码:

 

这个代码中的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.

 

////////////////////////////////////////////////////////////////////////////////////////////////////////////////

delphi 多种方法查找窗口句柄

第一种:使用API函数FindWindow
hw:=FindWindow(nil,PChar('窗口的标题名称'));

第二种:通过枚举所有窗口,查询特定条件的窗口
function EnumWindowsProc(Wnd: HWND; Param: Integer): Boolean; stdcall;
var
cn : Array[0..255] of char;
tab : HWND;
tId : DWORD;
begin
Result := TRUE;
if GetClassName(wnd, cn, 255) > 0 then
if cn = '#32770' then
begin
if (FindWindowEx(wnd, 0, 'Button','新建窗口') <> 0) and
(FindWindowEx(wnd, 0, 'Button','拨打电话') <> 0) and
(FindWindowEx(wnd, 0, 'Button','发送(Enter)') <> 0) then
begin
tID := GetWindowThreadProcessID(wnd, nil);
Form1.Memo1.Lines.Add('对话框句柄:'+IntToStr(Wnd));
Form1.Memo1.Lines.Add('对话框线程ID' + IntToSTr(tID));
end;
end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
EnumWindows(@EnumWindowsProc,0);
end;

第三种: 查找字窗口内元素的句柄
FindWindowEx(wnd, 0, 'Button','拨打电话')

第四种: 直接使用类似spy++工具软件查询

//////////////////////////////////////////////////////////////////////////////////////////////////////////

原文地址:https://www.cnblogs.com/hssbsw/p/1963940.html