我正在用 C++ 编写一个小工具,用于查找 Windows 应用程序主窗口的某个子窗口(UI 是用 QT 编写的,但这不会影响问题)。
#include <windows.h>
#include <winnt.h>
#include <tchar.h>
#include <psapi.h>
#include "MainWindow.h"
#include "ui_MainWindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::addOutputLine(const QString &line)
{
ui->outputPlainTextEdit->appendPlainText(line);
}
QString QStringFromPTCHAR(TCHAR *in)
{
#ifdef UNICODE
return QString::fromUtf16((ushort *) in);
#else
return QString::fromLocal8Bit((char *) in);
#endif
}
BOOL CALLBACK enumerateChildWindows(HWND windowHandle, LPARAM ui)
{
MainWindow *thisUi = (MainWindow *) ui;
TCHAR buffer[4096];
DWORD bufferSize;
ZeroMemory(buffer, sizeof(buffer));
bufferSize = sizeof(buffer) / sizeof(buffer[0]);
GetWindowText(windowHandle, buffer, bufferSize);
QString windowTitle = QStringFromPTCHAR(buffer);
if (!windowTitle.isEmpty() && IsWindow(windowHandle) == TRUE && IsWindowVisible(windowHandle) == TRUE)
{
thisUi->addOutputLine(QString("SUB-WIN: ") + windowTitle);
}
return TRUE;
}
BOOL CALLBACK enumerateWindows(HWND windowHandle, LPARAM ui)
{
MainWindow *thisUi = (MainWindow *) ui;
TCHAR buffer[4096];
DWORD bufferSize;
ZeroMemory(buffer, sizeof(buffer));
bufferSize = sizeof(buffer) / sizeof(buffer[0]);
GetWindowText(windowHandle, buffer, bufferSize);
QString windowTitle = QStringFromPTCHAR(buffer);
if (!windowTitle.isEmpty() && IsWindow(windowHandle) == TRUE && IsWindowVisible(windowHandle) == TRUE)
{
thisUi->addOutputLine(QString("WIN: ") + windowTitle);
EnumChildWindows(windowHandle, enumerateChildWindows, ui);
}
return TRUE;
}
void MainWindow::on_enumerateWindowsPushButton_clicked()
{
ui->outputPlainTextEdit->clear();
EnumDesktopWindows(0, enumerateWindows, (LPARAM) this);
}
目前,我的子窗口列表中仍然有很多其他 UI 元素,例如Inter的“导航栏”、“地址栏”、“地址组合控制”等。
有没有办法过滤掉所有窗口,除了那些“真实”窗口,即带有边框、标题栏等的窗口?
最佳答案
一个有点幼稚的检查是使用 GetWindowLong() 过滤掉没有标题(和边框)的窗口。像这样:
BOOL CALLBACK enumerateChildWindows(HWND windowHandle, LPARAM ui)
{
LONG styles = GetWindowLong(windowHandle, GWL_STYLE);
if ((styles & WS_CHILD) == WS_CHILD && IsWindowVisible(windowHandle)
thisUi->addOutputLine(QString("SUB-WIN: ") + windowTitle);
return TRUE;
}
正如我所说,这个过滤器非常幼稚,但您可以检查 WS_CAPTION
(假设您正在查找的窗口有标题栏)。最后一点:永远不要使用 IsWindow()
函数,它非常危险,而且因为您在这里枚举窗口也是无用的。
关于c++ - 枚举 "real"窗口和子窗口,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26238674/