getting a specific window name in c++

c++, windows

Solution

I don't think there's really any easier way by using the raw winapi, but here goes:

- Use the Toolhelp32 API to get a list of process IDs whose executable names match "notepad.exe".

- Enumerate the windows to find any whose PID matches one in the list.

- Grab the title of that window and do what you will with it.

Here's the code I came up with:

#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));
}

Going through in order:

First note the wide versions of functions and strings. `TCHAR` is not good to use and it would be a shame if one of the titles happened to have UTF-16 in it.

`isNotepad` just checks the executable name member of the `PROCESSENTRY32W` structure to see whether it equals "notepad.exe". This assumes Notepad uses this process name, and that nothing that isn't Notepad uses the process name. To eliminate false positives, you'd have to do more checking, but you can never be too sure.

In `enumWindowsProc`, take note that `lParam` is actually a pointer to a vector of PIDs (to save ourselves from having to use a global). This constitutes the cast at the beginning of the function. Next, we get the PID of the window we found. Then, we loop through the list of PIDs passed in and check whether it matches any. If it does, I chose to grab the title and output the PID and the window title. Note that using a standard string as a buffer is only guaranteed to work in C++11, and must not have the extra null character (not part of the length) overwritten. Lastly, we return `TRUE` so that it keeps enumerating until it has gone through every top-level window.

Onto `main`, the first thing you see is our initially empty list of PIDs. We take a snapshot of the processes and go through them. We use the helper function, `isNotepad` to check whether the process is "notepad.exe", and if so, store its PID. Lastly, we call `EnumWindows` to enumerate the windows, and pass in the list of PIDs, disguised as the required `LPARAM`.

It's a bit tricky if you haven't done this sort of thing, but I hope it makes sense. If you want the child windows, the correct thing to do would be to add a `EnumChildWindowsProc` and call `EnumChildWindows` with that in the spot where I output information about the found window. If I'm correct, you don't need to recursively call `EnumChildWindows` to get grandchildren etc., as they will be included in the first call.

Problem

I use this code to get the window name: ``` #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"); } } ``` However, it gets only the foreground window. I need to get all window names Or, actually, I need to get one specific window name which belongs to the "notepad.exe" process. Thanks for your help :)

Original source