文档章节

详解 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
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

没有更多内容

加载失败,请刷新页面

加载更多

使用 React 和 Vue 创建相同的应用,他们有什么差异?

在工作中应用 Vue 之后,我对它有了相当深刻的理解。 不过,俗话说「外国的月亮比较圆」,我好奇「外国的」 React 是怎么样的。 我阅读了 React 文档并观看了一些教程视频,虽然它们很棒,但...

阿K1225
13分钟前
0
0
如何使用Kubernetes的configmap通过环境变量注入到pod里

在Kubernetes官网里,有这样一篇文章,提到了Kubernetes里的一个最佳实践就是把应用代码同配置信息分开,一种方式就是使用Kubernetes 1.2里引入的configmap概念。 https://kubernetes.io/bl...

JerryWang_SAP
29分钟前
0
0
2天闭门培训|以太坊智能合约从入门到实战(北京)

2天培训 16个课时 探寻技术原理,精通以太坊智能合约开发 以太坊智能合约是现在应用的最广泛的区块链应用开发方式,HiBlock区块链社区针对以太坊智能合约的学习特别推出2天闭门研修班,通过2...

HiBlock
31分钟前
0
0
限定某个目录禁止解析php,限制user_agent,php相关配置

11月20日任务 11.28 限定某个目录禁止解析php 11.29 限制user_agent 11.30/11.31 php相关配置 1.限定某个目录禁止解析php 核心配置文件内容 <Directory /data/wwwroot/www.123.com/upload> p...

hhpuppy
42分钟前
2
0
Spring的好文章

孤傲苍狼 https://www.cnblogs.com/xdp-gacl/p/4249939.html 跟我学spring http://jinnianshilongnian.iteye.com/blog/1413846 SpringIoc 和Spring Aop 代理模式: 静态代理 动态代理 cglib代......

wangwei2134
53分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部