marco56
marco56

Reputation: 165

Getting a list of all open windows in c++ and storing them

I'm currently trying to get a list of all opened windows and storing them inside a vector. I've been looking at the code so much that the solution could be very easy but I don't seem to get it done without a global variable (which I want to avoid).

Here is the code:

#include "stdafx.h"
#include "json.h"
#include <algorithm>  

using namespace std;
vector<string> vec;


BOOL CALLBACK speichereFenster(HWND hwnd, LPARAM substring){
    const DWORD TITLE_SIZE = 1024;
    TCHAR windowTitle[TITLE_SIZE];

    GetWindowText(hwnd, windowTitle, TITLE_SIZE);
    int length = ::GetWindowTextLength(hwnd);

    wstring temp(&windowTitle[0]);
    string title(temp.begin(), temp.end());



    if (!IsWindowVisible(hwnd) || length == 0 || title == "Program Manager") {
        return TRUE;
    }

    vec.push_back(title);

    return TRUE;
}

int main() {
    EnumWindows(speichereFenster, NULL);
    cin.get();
    return 0;
}

I want to store all titles in the vector but I don't know how as I can't pass the vector into the function...

Thanks!!!

Upvotes: 6

Views: 25209

Answers (2)

gil123
gil123

Reputation: 679

Simple code to get all visible windows with non empty title

for (HWND hwnd = GetTopWindow(NULL); hwnd != NULL; hwnd = GetNextWindow(hwnd, GW_HWNDNEXT))
{   

    if (!IsWindowVisible(hwnd))
        continue;

    int length = GetWindowTextLength(hwnd);
    if (length == 0)
        continue;

    char* title = new char[length+1];
    GetWindowText(hwnd, title, length+1);

    if (title == "Program Manager")
        continue;

    std::cout << "HWND: " << hwnd << " Title: " << title << std::endl;

}

Upvotes: 7

IInspectable
IInspectable

Reputation: 51395

The second parameter (lParam) to EnumWindows is documented as:

An application-defined value to be passed to the callback function.

Just pass your container to the API call:

int main() {
    std::vector<std::wstring> titles;
    EnumWindows(speichereFenster, reinterpret_cast<LPARAM>(&titles));
    // At this point, titles if fully populated and could be displayed, e.g.:
    for ( const auto& title : titles )
        std::wcout << L"Title: " << title << std::endl;
    cin.get();
    return 0;
}

And use it in your callback:

BOOL CALLBACK speichereFenster(HWND hwnd, LPARAM lParam){
    const DWORD TITLE_SIZE = 1024;
    WCHAR windowTitle[TITLE_SIZE];

    GetWindowTextW(hwnd, windowTitle, TITLE_SIZE);

    int length = ::GetWindowTextLength(hwnd);
    wstring title(&windowTitle[0]);
    if (!IsWindowVisible(hwnd) || length == 0 || title == L"Program Manager") {
        return TRUE;
    }

    // Retrieve the pointer passed into this callback, and re-'type' it.
    // The only way for a C API to pass arbitrary data is by means of a void*.
    std::vector<std::wstring>& titles =
                              *reinterpret_cast<std::vector<std::wstring>*>(lParam);
    titles.push_back(title);

    return TRUE;
}

Notes:

  • The code presented uses a std::wstring in place of std::string. This is necessary so that the entire character set can be represented.
  • As written, the code isn't correct. There are (invisible) code paths, that have no well-defined meaning. The Windows API is strictly exposed as a C interface. As such, it doesn't understand C++ exceptions. Particularly with callbacks it is vital to never let C++ exceptions travel across unknown stack frames. To fix the code apply the following changes:
    • [C++11 only] Mark the callback noexcept.
    • Wrap the entire callback inside a try-catch block, and handle any exceptions appropriately.
    • [C++11 only] With C++11 you can pass C++ exceptions across unknown stack frames, by passing a std::exception_ptr, and calling std::rethrow_exception at the call site.

Upvotes: 13

Related Questions