如何让 EnumWindows 列出所有窗口?

Posted

技术标签:

【中文标题】如何让 EnumWindows 列出所有窗口?【英文标题】:How can I get EnumWindows to list all windows? 【发布时间】:2012-04-20 12:41:14 【问题描述】:

我假设,我所要求的实际上应该是默认设置,但我遇到了一些我不理解的行为。

#include "stdafx.h"

using namespace std;

BOOL CALLBACK enumWindowsProc(
  __in  HWND hWnd,
  __in  LPARAM lParam
) 
  if( !::IsIconic( hWnd ) ) 
    return TRUE;
  

  int length = ::GetWindowTextLength( hWnd );
  if( 0 == length ) return TRUE;

  TCHAR* buffer;
  buffer = new TCHAR[ length + 1 ];
  memset( buffer, 0, ( length + 1 ) * sizeof( TCHAR ) );
  
  GetWindowText( hWnd, buffer, length + 1 );
  tstring windowTitle = tstring( buffer );
  delete[] buffer;

  wcout << hWnd << TEXT( ": " ) << windowTitle << std::endl;

  return TRUE;


int _tmain( int argc, _TCHAR* argv[] ) 
  wcout << TEXT( "Enumerating Windows..." ) << endl;
  BOOL enumeratingWindowsSucceeded = ::EnumWindows( enumWindowsProc, NULL );
  cin.get();
  return 0;

如果我调用该代码,它将列出所有最小化的窗口:

现在,我不再只对最小化的窗口感兴趣,现在我想要所有这些。所以我删除了IsIconic 检查:

BOOL CALLBACK enumWindowsProc(
  __in  HWND hWnd,
  __in  LPARAM lParam
) 
  /*
  if( !::IsIconic( hWnd ) ) 
    return TRUE;
  
  */

  int length = ::GetWindowTextLength( hWnd );
  if( 0 == length ) return TRUE;

  TCHAR* buffer;
  buffer = new TCHAR[ length + 1 ];
  memset( buffer, 0, ( length + 1 ) * sizeof( TCHAR ) );
  
  GetWindowText( hWnd, buffer, length + 1 );
  tstring windowTitle = tstring( buffer );
  delete[] buffer;

  wcout << hWnd << TEXT( ": " ) << windowTitle << std::endl;

  return TRUE;

现在我得到所有窗口除了最小化的窗口(这次没有列出之前列出的窗口句柄):

为了完整起见,这是stdafx.h

#pragma once

#include "targetver.h"


#include <iostream>
#include <map>
#include <string>

namespace std 
  #if defined _UNICODE || defined UNICODE
    typedef wstring tstring;
  #else
    typedef string tstring;
  #endif


#include <stdio.h>
#include <tchar.h>
#include <Windows.h>
#include <psapi.h>

我做错了什么?

【问题讨论】:

为什么不结合这两个函数来获得想要的结果? 如果我不能解决这个问题,那么我想这就是我要做的。但我确信我的代码中存在错误。我更愿意解决它。 我的评论有点不合格,抱歉(有其他想法);) 我假设您尝试向下滚动? @TonyK 是的,我调整了窗口的高度以适合屏幕截图的文本。 【参考方案1】:

好吧,wcout.flush() 永远不会起作用,但是 wcout.clear() 修复了您的代码,至少对我来说是这样。

wcout << hWnd << TEXT( ": " ) << windowTitle << std::endl;
wcout.clear();
return TRUE;

而且我知道这个问题已经有一年的历史了,但是现在回答永远不会太晚。

【讨论】:

你说得对,这行得通。但是,在查找 ios::clear 的文档后,我对 为什么 它起作用感到有点困惑。【参考方案2】:

这是一个列出所有打开窗口的回调函数:

#include <string>
#include <iostream>
#include <Windows.h>

static BOOL CALLBACK enumWindowCallback(HWND hWnd, LPARAM lparam) 
    int length = GetWindowTextLength(hWnd);
    char* buffer = new char[length + 1];
    GetWindowText(hWnd, buffer, length + 1);
    std::string windowTitle(buffer);

    // List visible windows with a non-empty title
    if (IsWindowVisible(hWnd) && length != 0) 
        std::cout << hWnd << ":  " << windowTitle << std::endl;
    
    return TRUE;


int main() 
    std::cout << "Enmumerating windows..." << std::endl;
    EnumWindows(enumWindowCallback, NULL);
    std::cin.ignore();
    return 0;

如果要检查窗口是否最小化,可以使用IsIconic()

另见:

微软:EnumWindows function 堆栈溢出:Getting a list of all open windows in c++ and storing them

【讨论】:

我想你忘记了delete[] 声明...这可能导致内存泄漏 @MMD 很好。您能建议将其作为编辑吗?【参考方案3】:

(如我所料)EnumWindows 根本不是问题。问题出在输出流上。

在调试时,我注意到 enumWindowsProc 对于每个窗口都可以正常调用,但某些迭代根本不会产生输出。

暂时改用_tprintf,但不明白原代码有什么问题。调用wcout.flush() 也没有理想的效果。

【讨论】:

您是否尝试单步执行您的代码?如果这样做,您可能会注意到仍然有一个代码路径,您的回调函数在其中返回而不打印任何内容。 是的,在将 wcout &lt;&lt; ... 部分替换为 _tprintf 后,一切都按预期工作。我一定是错误地使用了流,或者是其他原因导致了这个问题。 使用调试器检查 windowTitle 中某些“遗漏”窗口的数据可能会帮助您找出应该提供原因提示的共同点。【参考方案4】:

Windows 文档(不知道其准确性)说 EnumWindows 仅枚举***窗口。如果你想枚举子窗口,你需要使用 EnumChildWindows 函数,你必须传递父窗口的句柄

【讨论】:

以上是关于如何让 EnumWindows 列出所有窗口?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 EnumWindows 不能在服务中工作?

获取任务栏中的窗口(EnumWindows函数)

具有 enumwindows 接口和进程的程序列表

c#获取窗口句柄后 如何遍历所有控件

c ++如何获得系统所有窗口名称 包括隐藏窗口

Delphi如何获得窗口的名字?