没有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_COPY和WM_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 通常是一个指向内存中数据的指针。由于WParm、lParam和Pointer都是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_JOURNALPALYBACK的hook程序分离出用户输入消息
★WM_GETMINMAXINFO 此消息发送给窗口当它将要改变大小或位置
★WM_PAINTICON 发送给最小化窗口当它图标将要被重画
★WM_ICONERASEBKGND 此消息发送给某个最小化窗口,仅当它在画图标前它的背景必须被重画
★WM_NEXTDLGCT★发送此消息给一个对话框程序去更改焦点位置
★WM_SPOOLERSTATUS 每当打印管理列队增加或减少一条作业时发出此消息
★WM_DRAWITEM 当button,combobox,listbox,menu的可视外观改变时发送
★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 发送此消息来判定combobox或listbox新增加的项的相对位置
★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
////////////////////////////////////////////////////////////////////////////////////////////////////////////
引用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到句柄的实现方案可行性研究 |
2010年6月19日联系商易上海电子商务网站建设,了解更多 |
|
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}
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
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++工具软件查询
//////////////////////////////////////////////////////////////////////////////////////////////////////////