文档章节

详解 EnumWindows 与 EnumWindowsProc - 回复 "SplendourChiang" 的问题

涂孟超
 涂孟超
发布于 2014/09/26 15:35
字数 705
阅读 10
收藏 0

问题来源: http://www.cnblogs.com/del/archive/2009/10/16/1584488.html#1727205

// EnumWindows 的功能是遍历所有顶层窗口
function EnumWindows(
  lpEnumFunc: TFNWndEnumProc; {回调函数指针}
  lParam: LPARAM              {给回调函数的参数, 它对应回调函数的第二个参数}
): BOOL; stdcall; //成功与否, 其实是返回了回调函数的返回值

// EnumWindows 专用的回调函数的格式:
function EnumWindowsProc(
  hwnd: HWND;        {找到的窗口句柄}
  lParam: LPARAM     {EnumWindows 传给的参数; 因为它是指针, 可传入, 但一般用作传出数据}
): Boolean; stdcall; {函数返回 False 时, 调用它的 EnumWindows 将停止遍历并返回 False}

 
 
 
 
 

 

 

  

例一: 获取所有顶层窗口的句柄

//需要个 TListBox 显示数据
function EnumWindowsProc_1(hwnd: HWND; lParam: LPARAM): Boolean; stdcall;
begin
  Form1.ListBox1.Items.Add(IntToStr(hwnd));
  Result := True;
end;

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

 
 
 
 
 

 

 

  

例二: 获取所有顶层窗口的标题(排除无标题窗口)

function EnumWindowsProc_2(hwnd: HWND; lParam: LPARAM): Boolean; stdcall;
var
  buf: array[Byte] of Char;
begin
  GetWindowText(hwnd, buf, SizeOf(buf));
  if buf <> '' then Form1.ListBox1.Items.Add(buf);
  Result := True;
end;

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

 
 
 
 
 

 

 

  

例三: 查找第一个记事本的句柄

function EnumWindowsProc_3(hwnd: HWND; lParam: LPARAM): Boolean; stdcall;
var
  buf: array[Byte] of Char;
begin
  GetClassName(hwnd, buf, SizeOf(buf));
  if buf = 'Notepad' then
  begin
    Form1.ListBox1.Items.Add(Format('记事本句柄: %d', [hwnd]));
    Result := False; //如果不需要继续找, 找到第一个就结束
  end
  else
  begin
    Result := True;
  end;
end;

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

 
 
 
 
 

 

 

  

例四: 获取所有顶层窗口的句柄与类名数组:

type
  TMyStruct = record
    hwnd: HWND;
    ClassName: string;
  end;
  TMyStructArray = array of TMyStruct;
  PMyStructArray = ^TMyStructArray;

function EnumWindowsProc_4(hwnd: HWND; lParam: LPARAM): Boolean; stdcall;
var
  buf: array[Byte] of Char;
  p: PMyStructArray;
begin
  GetClassName(hwnd, buf, SizeOf(buf));
  p := PMyStructArray(lParam);
  SetLength(p^, Length(p^) + 1);
  p^[High(p^)].hwnd := hwnd;
  p^[High(p^)].ClassName := buf;
  Result := True;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  Arr: TMyStructArray;
begin
  EnumWindows(@EnumWindowsProc_4, Integer(@Arr));
  ShowMessage(IntToStr(Length(Arr)));                         //总数
  ShowMessageFmt('%d - %s', [Arr[0].hwnd, Arr[0].ClassName]); //第一个元素
end;

 
 
 
 
 

 

 

  

例五: 重复上一个例子, 如果数组是全局遍历并不靠参数传递, 代码会简单些

type
  TMyStruct = record
    hwnd: HWND;
    ClassName: string;
  end;
var
  Arr: array of TMyStruct;

function EnumWindowsProc_5(hwnd: HWND; lParam: LPARAM): Boolean; stdcall;
var
  buf: array[Byte] of Char;
begin
  GetClassName(hwnd, buf, SizeOf(buf));
  SetLength(Arr, Length(Arr) + 1);
  Arr[High(Arr)].hwnd := hwnd;
  Arr[High(Arr)].ClassName := buf;
  Result := True;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  SetLength(Arr, 0);
  EnumWindows(@EnumWindowsProc_5, Integer(Arr));
  ShowMessage(IntToStr(Length(Arr)));                         //总数
  ShowMessageFmt('%d - %s', [Arr[0].hwnd, Arr[0].ClassName]); //第一个元素
end;

 
 
 
 
 

 

 

  

SplendourChiang 的目的是获取进程 ID 和窗口句柄的数组, 按 "例四" 的方法给修改如下:

type
  MyProcessInfo = record
    PID, WinHWND : DWORD;
  end;
  TMyProcessInfoArray = array of MyProcessInfo;
  PMyProcessInfoArray = ^TMyProcessInfoArray;

function MyEnumWindowsProc(Wnd: DWORD; lParam: LPARAM): Bool; stdcall;
var
  PID : DWORD;
  p: PMyProcessInfoArray;
begin
  GetWindowThreadProcessID(Wnd, @PID);
  p := PMyProcessInfoArray(lParam);
  SetLength(p^, Length(p^) + 1);
  p^[High(p^)].PID := PID;
  p^[High(p^)].WinHWND := Wnd;
  Result := True;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  CC: TMyProcessInfoArray;
begin
  SetLength(CC, 0);
  EnumWindows(@MyEnumWindowsProc, Integer(@CC));
  ShowMessage(IntToStr(Length(CC)));                     //总数
  ShowMessageFmt('%d - %d', [CC[0].PID, CC[0].WinHWND]); //第一个元素
end;

 
 
 
 
 

 

 

  

本文转载自:http://www.cnblogs.com/del/archive/2009/12/18/1627110.html

共有 人打赏支持
涂孟超
粉丝 12
博文 2011
码字总数 14107
作品 0
深圳
程序员
私信 提问
Delphi 查找标题已知的窗口句柄,遍历窗口控件句柄(转)

Delphi 查找标题已知的窗口句柄,遍历窗口控件句柄(转) 用我的方法来控制其他程序窗体上的窗口控件,必须先了解什么是回调函数。我的理解是这样的: 回调函数写出来不是自己的程序去调用的,...

vga
2015/02/05
0
0
Windows窗体数据抓取详解

最近在客户项目上刚好遇到一个问题,项目需求是要获取某台机床的实时状态,问题点刚好就在于该机床不是传统意义上的数控机床,也不是PLC控制器,只有一个上传下载程序文件的应用程序,上面刚...

wangqiulin123456
2018/04/22
0
0
GetSafeHwnd()和GetSafeHandle()区别

一、GetSafeHwnd()和GetSafeHandle()的主要区别: 1、使用者不同 1)窗体使用 GetSafeHwnd()用于获取窗体的安全句柄(即HWND),有了HWND我们就可以方便的对HWND指向的窗体进行所需的操作了 ...

tomy000
2015/01/07
0
0
EnumChildWindows (user32)

C# Signature: [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] static extern bool EnumChildWindows(IntPtr hwndParent, EnumWindowsProc lpEnumFunc, IntPtr lParam)......

一个长老
2012/10/14
0
0
用C#调用Windows API向指定窗口发送按键消息

用C#调用Windows API向指定窗口发送 一、调用Windows API。  C#下调用Windows API方法如下:  1、引入命名空间:using System.Runtime.InteropServices;  2、引用需要使用的方法,格式:[...

RablePHP
2016/06/03
723
0

没有更多内容

加载失败,请刷新页面

加载更多

求推广,德邦快递坑人!!!!

完全没想好怎么来吐槽自己这次苦逼的德邦物流过程了,只好来记一个流水账。 从寄快递开始: 2019年1月15日从 德邦物流 微信小app上下单,截图如下: 可笑的是什么,我预约的是17号上门收件,...

o0无忧亦无怖
29分钟前
1
0
Mac Vim配置

1.升级 vim   我自己 MacBook Pro 的系统还是 10.11 ,其自带的 vim 版本为 7.3 ,我们将其升至最新版: 使用 homebrew : brew install vim --with-lua --with-override-system-vim 这将下...

Pasenger
41分钟前
0
0
vmware安装Ubuntu上不了网?上网了安装不了net-tools,无法执行ifconfig?

1.重新设置网络适配器还是不行,如下指定nat 2.还需要指定共享网络,我是在无线环境下 3.无法执行ifconfig https://packages.ubuntu.com/bionic/net-tools到这个网站下载net-tools的deb文件...

noob_chr
今天
1
0
解决SVN:E210007无法协商认证机制

svn:E210007 svn: Cannot negotiate authentication mechanism 执行下面代码即可 sudo yum install cyrus-sasl cyrus-sasl-plain cyrus-sasl-ldap...

临江仙卜算子
今天
1
0
java8的时间和`Date`的对比

java8的时间和Date的对比 java8提供了新的时间接口。相对Date,Calendar,个人感觉最大的好处是对时间操作的学习成本很低,比Calendar低。 1. LocalDate,LocalTime,LocalDateTime LocalDate 代...

北风刮的不认真了
今天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部