枚举"真实"窗户和儿童窗户

时间:2014-10-07 14:41:03

标签: 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元素,例如国际电联的“导航栏”,“地址栏”,“地址组合控制”等。

有没有办法过滤所有这些,但那些是“真正的”窗口,即带边框,标题栏等?

1 个答案:

答案 0 :(得分:2)

有点天真的检查是使用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() 功能,它非常危险,因为你在这里枚举窗口也没用。