七月网

findwindowex(FindWindowEx查找子窗口)

七月网5070

一、如何使用FindWindowEx获取窗体内控件句柄

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

findwindowex(FindWindowEx查找子窗口)

handle:= FindWindow(nil,PChar('窗口的标题'));

procedure TForm1.Button1Click(Sender: TObject);

hCurrentWindow:= GetWindow(Handle, GW_HWNDFIRST);

while hCurrentWindow<> 0 do

WndText:=GetWndText(hCurrentWindow);

if UpperCase(WndText)='窗口的标题' then begin

hCurrentWindow:=GetWindow(hCurrentWindow, GW_HWNDNEXT);

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

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

procedure TForm1.Button1Click(Sender: TObject);

FSnapshotHandle:THandle;//进程快照句柄

FProcessEntry32:TProcessEntry32;//进程入口的结构体信息

FSnapshotHandle:=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);//创建一个进程快照

FProcessEntry32.dwSize:=Sizeof(FProcessEntry32);

ContinueLoop:=Process32First(FSnapshotHandle,FProcessEntry32);//得到系统中第一个进程

ProcessName:= FProcessEntry32.szExeFile;

if(ProcessName='要找的应用程序名.exe') then begin

MyHwnd:= GetHWndByPID(FProcessEntry32.th32ProcessID);

ContinueLoop:=Process32Next(FSnapshotHandle,FProcessEntry32);

CloseHandle(FSnapshotHandle);//释放快照句柄

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

function TForm1.GetHWndByPID(const hPID: THandle): THandle;

function EnumWindowsProc(Wnd: DWORD; var EI: TEnumInfo): Bool; stdcall;

GetWindowThreadProcessID(Wnd,@PID);

Result:=(PID<> EI.ProcessID) or

if not Result then EI.HWND:= WND;

function FindMainWindow(PID: DWORD): DWORD;

EnumWindows(@EnumWindowsProc, Integer(@EI));

我说的是组件的句柄,不是窗体的句柄

findwindowex();获取指定句柄窗口下的子控件,当然是有句柄的控件

窗体的句柄都知道,还能不知道里面组件的句柄?——windows标准组件

procedure TForm1.Button2Click(Sender: TObject);

//这是OK。这真要感谢baidu,google

canvas1.Handle:= GetDc(panel1.Handle);

canvas1.TextOut(1,1,'hello');

Form1.Canvas.TextOut(10, 10,'fff');

ShowMessage(IntToStr(TWinControl(Form1.FindChildControl('Panel1')).Handle));

二、VB中findwindowex函数的用法。。

函数功能:在窗口列表中寻找与指定条件相符的第一个子窗口。

该函数获得一个窗口的句柄,该窗口的类名和窗口名与给定的字符串相匹配。这个函数查找子窗口,从排在给定的子窗口后面的下一个子窗口开始。在查找时不区分大小写。

参数:(1)hwndParent:要查找的子窗口所在的父窗口的句柄(如果设置了hwndParent,则表示从这个hwndParent指向的父窗口中搜索子窗口)。

如果hwndParent为 0,则函数以桌面窗口为父窗口,查找桌面窗口的所有子窗口。

Windows NT5.0 and later:如果hwndParent是HWND_MESSAGE,函数仅查找所有消息窗口。

(2)hwndChildAfter:子窗口句柄。查找从在Z序中的下一个子窗口开始。子窗口必须为hwndParent窗口的直接子窗口而非后代窗口。如果HwndChildAfter为NULL,查找从hwndParent的第一个子窗口开始。如果hwndParent和 hwndChildAfter同时为NULL,则函数查找所有的顶层窗口及消息窗口。

(3)lpszClass:指向一个指定了类名的空结束字符串,或一个标识类名字符串的成员的指针。如果该参数为一个成员,则它必须为前次调用theGlobaIAddAtom函数产生的全局成员。该成员为16位,必须位于lpClassName的低16位,高位必须为0。

(4)lpszWindow:指向一个指定了窗口名(窗口标题)的空结束字符串。如果该参数为 NULL,则为所有窗口全匹配。

返回值:Long,找到的窗口的句柄。如未找到相符窗口,则返回零。会设置GetLastError

如果函数成功,返回值为具有指定类名和窗口名的窗口句柄。如果函数失败,返回值为NULL。

若想获得更多错误信息,请调用GetLastError函数。

Private Declare Function FindWindowEx Lib"user32" Alias"FindWindowExA"(ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long

[DllImport("user32.dll", SetLastError= true)]

public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string className, string windowTitle);

<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)>_

Private Shared Function FindWindowEx(ByVal parentHandle As IntPtr,_

ByVal windowTitle As String) As IntPtr

'Example Name: Changing a VB Toolbar to a Rebar-Style Toolbar

Public Const TB_SETSTYLE= WM_USER+ 56

Public Const TB_GETSTYLE= WM_USER+ 57

Public Const TBSTYLE_FLAT=&H800

Public Declare Function SendMessage Lib"user32"_

Public Declare Function FindWindowEx Lib"user32"_

ByVal lpsz2 As String) As Long

.Width= Toolbar1.Buttons("combo1").Width

.Top=(Toolbar1.Height- Combo1.Height)\ 2

.Left= Toolbar1.Buttons("combo1").Left

.AddItem"Black"' Add colours for text.

三、FindWindowEx用法怎么用

1、Private Declare Function FindWindowEx Lib"user32" Alias"FindWindowExA"(ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long

2、看里面的参数,第一个和第二个:ByVal hWnd1 As Long,ByVal hWnd2 As Long,这里都需要传入句柄,再看第三个和第四个:ByVal lpsz1 As String, ByVal lpsz2 As String,这里所要传入的是字符串。具体意思如下:

3、hWnd1---------- Long,在其中查找子的父窗口。如设为零,表示使用桌面窗口(通常说的顶级窗口都被认为是桌面的子窗口,所以也会对它们进行查找)

4、hWnd2---------- Long,从这个窗口后开始查找。这样便可利用对FindWindowEx的多次调用找到符合条件的所有子窗口。如设为零,表示从第一个子窗口开始搜索

5、lpsz1---------- String,欲搜索的类名。零表示忽略,注意一般传入vbNullString

6、lpsz2---------- String,欲搜索的类名。零表示忽略,注意一般传入vbNullString

7、用实践帮我们分析,这里还是拿记事本开刀。打开一个记事本,新建一个标准EXE,接着新建一个CommandButton,Caption设置为:设置文本。OK,写入以下代码:

8、Private Declare Function FindWindow Lib"user32" Alias"FindWindowA"(ByVal lpClassName As String, ByVal lpWindowName As String) As Long

9、Private Declare Function FindWindowEx Lib"user32" Alias"FindWindowExA"(ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long

10、Private Declare Function EnableWindow Lib"user32"(ByVal hwnd As Long, ByVal fEnable As Long) As Long

11、Dim WindowHandle As Long, ChildWindowHandle As Long

12、WindowHandle= FindWindow(vbNullString,"无标题-记事本")

13、If WindowHandle Then'如果获取句柄成功

14、ChildWindowHandle= FindWindowEx(WindowHandle, 0,"Edit", vbNullString)

15、If ChildWindowHandle Then'如果成功获取子句柄

16、EnableWindow ChildWindowHandle, False'禁用子窗口

17、好了,帮大家分析。看第一行:Dim WindowHandle As Long, ChildWindowHandle As Long,用于储存获取的句柄的。WindowHandle= FindWindow(vbNullString,"无标题-记事本")这个就不用讲了,上面已经讲过。

18、ChildWindowHandle= FindWindowEx(WindowHandle, 0,"Edit", vbNullString),这一段是通过我们已经获取的记事本句柄获取其中的子窗口句柄。大家可以用Spy++查看到记事本的TextBox类,然后根据类名写入即可。

19、EnableWindow ChildWindowHandle, False这又是一个新的API,虽然前面我没有前过,但是这个API使用起来及其简单。这个API中有两个参数,第一个理所当然是传入窗口句柄,第二个为Long变量,其实这里应该设为Boolean变量好些,主要是用来处理当前窗口是否可用。True可用,False禁用。

20、现在F5运行,记得打开记事本哦,然后点击Command1,看看能不能在记事本的文本框中输入字符串?是否被禁用了?

好了,关于findwindowex和FindWindowEx查找子窗口的问题到这里结束啦,希望可以解决您的问题哈!