c++ - 枚举 "real"窗口和子窗口

标签 c++ winapi

我正在用 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/

相关文章:

c++ - 使用类方法而不实例化的优点/缺点

c++ - 模板参数隐藏

c++ - 如何重载/专门化模板类函数来处理算术类型和容器类

c++ - 在 cout 中使用 Hook 函数时应用程序崩溃

c++ - 有人可以用 Sleep(1) 解释这种有趣的行为吗?

C - 仅使用 ntdll 的堆栈分配

c++ - C++引用和退出范围

java - 如何对整数除法的结果进行四舍五入?

c++ - 以编程方式更改组合框

c# - SetWindowPos 插入之后,而不是之前?