c++ - 在 C++ 中获取特定的窗口名称

标签 c++ windows

我使用此代码获取窗口名称:

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

int main() {
    TCHAR title[500];
    int i=0;
    while(i<10) {
        GetWindowText(GetForegroundWindow(), title, 500);
        printf("%s\n",title);
        i++;
        system("pause");
    }
}

但是,它只获取前景窗口。

  1. 我需要获取所有窗口名称

  2. 或者,实际上,我需要获取一个属于“notepad.exe”进程的特定窗口名称。

感谢您的帮助:)

最佳答案

我不认为使用原始 winapi 真的有任何更简单的方法,但这里是:

  1. 使用 Toolhelp32 API 获取可执行名称与“notepad.exe”匹配的进程 ID 列表。
  2. 枚举窗口以查找其 PID 与列表中的一个相匹配的窗口。
  3. 捕获那个窗口的标题,然后用它做你想做的事。

这是我想出的代码:

#include <iostream>
#include <string>
#include <vector>

#include <windows.h>
#include <tlhelp32.h>

bool isNotepad(const PROCESSENTRY32W &entry) {
    return std::wstring(entry.szExeFile) == L"notepad.exe";
}

BOOL CALLBACK enumWindowsProc(HWND hwnd, LPARAM lParam) {
    const auto &pids = *reinterpret_cast<std::vector<DWORD>*>(lParam);

    DWORD winId;
    GetWindowThreadProcessId(hwnd, &winId);

    for (DWORD pid : pids) {
        if (winId == pid) {
            std::wstring title(GetWindowTextLength(hwnd) + 1, L'\0');
            GetWindowTextW(hwnd, &title[0], title.size()); //note: C++11 only

            std::cout << "Found window:\n";
            std::cout << "Process ID: " << pid << '\n';
            std::wcout << "Title: " << title << "\n\n";
        }
    }

    return TRUE;
}

int main() {
    std::vector<DWORD> pids;

    HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    // Do use a proper RAII type for this so it's robust against exceptions and code changes.
    auto cleanupSnap = [snap] { CloseHandle(snap); };

    PROCESSENTRY32W entry;
    entry.dwSize = sizeof entry;

    if (!Process32FirstW(snap, &entry)) {
        cleanupSnap();
        return 0;
    }

    do {
        if (isNotepad(entry)) {
            pids.emplace_back(entry.th32ProcessID);
        }
    } while (Process32NextW(snap, &entry));
    cleanupSnap();

    EnumWindows(enumWindowsProc, reinterpret_cast<LPARAM>(&pids));
}

按顺序进行:

首先注意函数和字符串的宽版本。 TCHAR 不好用,如果其中一个标题恰好包含 UTF-16,那将是一种耻辱。

isNotepad 只是检查 PROCESSENTRY32W 结构的可执行名称成员,看它是否等于“notepad.exe”。这假定记事本使用此进程名称,并且不是记事本的任何东西都使用该进程名称。要消除误报,您必须进行更多检查,但您永远不能太确定。

enumWindowsProc 中,请注意 lParam 实际上是一个指向 PID vector 的指针(以避免我们必须使用全局变量)。这构成了函数开头的强制转换。接下来,我们获取找到的窗口的 PID。然后,我们遍历传入的 PID 列表并检查它是否匹配。如果是,我选择抓取标题并输出 PID 和窗口标题。请注意,使用标准字符串作为缓冲区只能保证在 C++11 中工作,并且不能覆盖额外的空字符(不是长度的一部分)。最后,我们返回 TRUE,以便它继续枚举,直到它遍历每个顶级窗口。

main 上,您首先看到的是我们最初为空的 PID 列表。我们拍摄流程快照并检查它们。我们使用辅助函数 isNotepad 来检查进程是否为“notepad.exe”,如果是,则存储其 PID。最后,我们调用 EnumWindows 来枚举窗口,并传入 PID 列表,伪装成所需的 LPARAM

如果你没有做过这类事情,这有点棘手,但我希望它是有道理的。如果您想要子窗口,正确的做法是添加 EnumChildWindowsProc 并在我输出有关找到的窗口的信息的位置调用 EnumChildWindows。如果我是正确的,您不需要递归调用 EnumChildWindows 来获取孙子等,因为它们将包含在第一次调用中。

关于c++ - 在 C++ 中获取特定的窗口名称,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14029626/

相关文章:

C++ 通过引用传递数组

c++ - fprintf 的组合函数和 c/c++ 中的 write

python - 如何在 Windows 上访问文件的属性?

c# - 为什么在我上次将输出编码保留为 UTF8 时 csc.exe 崩溃?

c++ - 运行时用户输入解析

c++ - 无法打开存在的二进制文件

c++ - 如何在 Windows 中使用手写的 makefile 编译和构建 C++ 应用程序?

windows - 将所有批处理文件参数转发给内部命令

windows - HH 的命令行选项和打开 CHM Windows 帮助文件

c++ - COM 接口(interface)指针与实现类有何关系?