Получить HWND окна если заголовок постоянно меняется .

Gafask

Участник
Автор темы
137
13
Дратути , такой вопросик . Как можно получить HWND окна если название заголовочного окна постоянно меняется и их несколько .
Для тестов своего кода я получал его через - HWND HWND_POLIGON = FindWindowA(0, "Тестовый полигон"); , но я откладывал этот вопрос на потом и пытался искать и так не находил .
Подскажите как мне получить HWND нескольких запущенных окон если его название постоянно меняется , потипу "Яблоко 1" , и через одну сек. "Зеленое яблоко 2" , и сново через сек. "Красное яблоко 63" и через сек. "компутер зеленый 45" но при этом название процесса всегда одно - пример "Вентилятор.exe".

Еще 1 пример - Запущенно 3 окна и у каждого окна название процесса "Стул.exe" но название заголовка у всех окон меняется раз в 1 мин . но не целиком а только одно слово и нужно получить HWND каждого из 3 окон и к примеру перенести каждое окна в другой участок экрана .

Подскажите , я думал перебрать все окна и потом по названию процесса получить HWND каждого окна но что-то поиске в гугле не увенчались успехом .

Еще 2 пример - Запущена 5 окон "gta-sa.exe" а заголовок окна меняется рандомно и каким образом можно получить HWND окна если извесно только название процесса .

Еще 3 пример - Ваша программа запустила 3 окна через функцию CreateProcess и название процесса одинаковое но заголовок окна разный и меняется , и программе нужно перенести окна или свернуть их или как то с ними взаимодействовать но она не может так как она не знает их HWND а получить через FindWindowA она их не может иза того что заголовок окна меняется раз в 5 мин. и нужно это исправить так что-бы она могла работать правильно без вмешательства человека . ( Не очень пример но все же пусть будет . )
 
Решение
Привет, @Разраб ИИ
Конечно, решение @imring тоже имеет право на жизнь, хоть оно и спащено, но оно рабочее. Но у меня душа не будет спокойна, если я не разбируюсь с увиденным кодом. Итого просидел с кодом несколько часиков (мне интересно было узнать про нахождение окон по PID-у, с остальным я был знаком, засел на функции FindWindowExW, т.к читал документацию), расписал каждый шаг своего решения.
Использую wide char (UNICODE), т.к название может состоять не только из ANSI символов.
Если будут вопросы, задавай:
Solution:
#include <windows.h>
#include <tlhelp32.h>
#include <vector>
#include <wchar.h> // wcscmp
#include <stdio.h>


// функция получения списка дочерних и основного процессов по имени
void...

Gafask

Участник
Автор темы
137
13
1. получить ид процессов по названию (там надо немног изменить код, чтобы получить список идов): http://www.cplusplus.com/forum/windows/12137/#msg58394
2. https://stackoverflow.com/a/48207646
Ух , я в с++ не очень силен , а поподробнее можно если не затруднит вас . Есть ли русские сылочки так как мою английски не позволяет мне понять часть слов ) .
 

imring

Ride the Lightning
Всефорумный модератор
2,355
2,516
C++:
#include <iostream>
#include <vector>

#include <Windows.h>
#include <tlhelp32.h>

// https://stackoverflow.com/a/865201
void FindProcessIds(const char* processName, std::vector<DWORD> &ids)
{
    PROCESSENTRY32 entry;
    entry.dwSize = sizeof(PROCESSENTRY32);

    HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);

    if (Process32First(snapshot, &entry))
        while (Process32Next(snapshot, &entry))
            if (!strcmp(entry.szExeFile, processName))
                ids.push_back(entry.th32ProcessID);
    CloseHandle(snapshot);
}

// https://stackoverflow.com/a/48207646
void GetAllWindowsFromProcessID(DWORD dwProcessID, std::vector<HWND> &vhWnds)
{
    HWND hCurWnd = nullptr;
    do
    {
        hCurWnd = FindWindowEx(nullptr, hCurWnd, nullptr, nullptr);
        DWORD checkProcessID = 0;
        GetWindowThreadProcessId(hCurWnd, &checkProcessID);
        if (checkProcessID == dwProcessID)
            vhWnds.push_back(hCurWnd);
    } while (hCurWnd != nullptr);
}

int main() {
    const char* name = "chrome.exe";

    std::vector<DWORD> ids;
    FindProcessIds(name, ids);

    std::cout << "Process Ids \"" << name << "\":\n";
    for (auto &id: ids)
        std::cout << id << ' ';
    std::cout << '\n';

    std::vector<HWND> hwnds;
    for (auto &id: ids)
        GetAllWindowsFromProcessID(id, hwnds);

    std::cout << "HWND's \"" << name << "\"\n";
    for (auto& hwnd: hwnds)
        std::cout << reinterpret_cast<int>(hwnd) << ' ';
    std::cout << '\n';

    return 0;
}
 
  • Нравится
Реакции: Vintik

DolgorukovGTA

Известный
Проверенный
652
345
Привет, @Разраб ИИ
Конечно, решение @imring тоже имеет право на жизнь, хоть оно и спащено, но оно рабочее. Но у меня душа не будет спокойна, если я не разбируюсь с увиденным кодом. Итого просидел с кодом несколько часиков (мне интересно было узнать про нахождение окон по PID-у, с остальным я был знаком, засел на функции FindWindowExW, т.к читал документацию), расписал каждый шаг своего решения.
Использую wide char (UNICODE), т.к название может состоять не только из ANSI символов.
Если будут вопросы, задавай:
Solution:
#include <windows.h>
#include <tlhelp32.h>
#include <vector>
#include <wchar.h> // wcscmp
#include <stdio.h>


// функция получения списка дочерних и основного процессов по имени
void getAllProcessIdsByProcNameW(LPCWSTR lpczProcName, std::vector<DWORD> *pidsVec)
{
    pidsVec->clear(); // очистка вектора, на всякий случай, не помешает
    PROCESSENTRY32W procEntry = {sizeof(PROCESSENTRY32W)}; // инициализация структуры
    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); // получаем список абсолютно всех процессов в системе (за это отвечает флаг TH32CS_SNAPPROCESS)
    if (Process32FirstW(hSnapshot, &procEntry)) // обработка первого процесса
    {
        while (Process32NextW(hSnapshot, &procEntry)) // и последующих
        {
            // если учитывать, что дочерние процессы носят такое же имя, что и основной процесс, то мы сравниваем строки
            if (wcscmp(procEntry.szExeFile, lpczProcName) == 0)
            {
                pidsVec->push_back(procEntry.th32ProcessID); // закидываем PID в вектор
            }
        }
    }

    CloseHandle(hSnapshot); // не забываем обнулить дескриптор
}


void getAllWindowHandlesByPyPidsVec(const std::vector<DWORD> *pidsVec, std::vector<HWND> *hwndVec)
{
    hwndVec->clear(); // аналогично
    HWND hCurrentWindow = nullptr; // дескриптор текущего окна, пока ни на что не указывает
    DWORD dwProcessID = 0; // PID текущего процесса

    for (size_t i = 0; i < pidsVec->size(); i++) // пробегаемся по нашему списку процессов
    {
        while (true)
        {
            hCurrentWindow = FindWindowExW(nullptr, hCurrentWindow, nullptr, nullptr); // пробежка по списку
            // Все окна в Windows взаимосвязаны между собой и обобщены в список Z-order
            // При помощи конструкции выше мы перебираем этот список, спускаемся, можно сказать
            if (hCurrentWindow == nullptr) // если окна, на которое мы перешли не существует (дескриптор пустой)
            {
                break; // выходим из while-цикла
            }
            else
            {
                GetWindowThreadProcessId(hCurrentWindow, &dwProcessID); // получаем процесс, к которому относится текущее окно
                // поток нас не интересует, поэтому возвращаемое значение никак не обрабатывается
                if (dwProcessID == (*pidsVec)[i]) // сравнение: эквивалентен ли текущий PID окна PID-у из списка
                {
                    hwndVec->push_back(hCurrentWindow); // если да, записываем окно в список, оно нам подходит
                }
            }
        }
    }
}


int main()
{
    LPCWSTR lpczProcName = L"firefox.exe";
    std::vector<DWORD> pidsVec{}; // вектор, хранящий в себе PID-ы (идентификаторы) процессов
    std::vector<HWND> hwndVec{}; // вектор, хранящий в себе дескрипторы окошек

    getAllProcessIdsByProcNameW(lpczProcName, &pidsVec);
    if (!pidsVec.empty()) // проверки никогда лишними не будут
    {
        getAllWindowHandlesByPyPidsVec(&pidsVec, &hwndVec);
        if (!hwndVec.empty())
        {
            for (size_t i = 0; i < hwndVec.size(); i++)
            {
                // дескриптор окна - это указатель внутри, поэтому и выводим с соответствующим спецификатором
                wprintf(L"%p\n", hwndVec[i]);
            }
        }

        else wprintf(L"The PIDs haven't visible (no only message) windows.\n"); // у процесса нет видимых окон
    }

    else wprintf(L"There're no processes with specified name.\n"); // нет процессов с таким именем
    return 0;
}
 

Gafask

Участник
Автор темы
137
13
Привет, @Разраб ИИ
Конечно, решение @imring тоже имеет право на жизнь, хоть оно и спащено, но оно рабочее. Но у меня душа не будет спокойна, если я не разбируюсь с увиденным кодом. Итого просидел с кодом несколько часиков (мне интересно было узнать про нахождение окон по PID-у, с остальным я был знаком, засел на функции FindWindowExW, т.к читал документацию), расписал каждый шаг своего решения.
Использую wide char (UNICODE), т.к название может состоять не только из ANSI символов.
Если будут вопросы, задавай:
Solution:
#include <windows.h>
#include <tlhelp32.h>
#include <vector>
#include <wchar.h> // wcscmp
#include <stdio.h>


// функция получения списка дочерних и основного процессов по имени
void getAllProcessIdsByProcNameW(LPCWSTR lpczProcName, std::vector<DWORD> *pidsVec)
{
    pidsVec->clear(); // очистка вектора, на всякий случай, не помешает
    PROCESSENTRY32W procEntry = {sizeof(PROCESSENTRY32W)}; // инициализация структуры
    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); // получаем список абсолютно всех процессов в системе (за это отвечает флаг TH32CS_SNAPPROCESS)
    if (Process32FirstW(hSnapshot, &procEntry)) // обработка первого процесса
    {
        while (Process32NextW(hSnapshot, &procEntry)) // и последующих
        {
            // если учитывать, что дочерние процессы носят такое же имя, что и основной процесс, то мы сравниваем строки
            if (wcscmp(procEntry.szExeFile, lpczProcName) == 0)
            {
                pidsVec->push_back(procEntry.th32ProcessID); // закидываем PID в вектор
            }
        }
    }

    CloseHandle(hSnapshot); // не забываем обнулить дескриптор
}


void getAllWindowHandlesByPyPidsVec(const std::vector<DWORD> *pidsVec, std::vector<HWND> *hwndVec)
{
    hwndVec->clear(); // аналогично
    HWND hCurrentWindow = nullptr; // дескриптор текущего окна, пока ни на что не указывает
    DWORD dwProcessID = 0; // PID текущего процесса

    for (size_t i = 0; i < pidsVec->size(); i++) // пробегаемся по нашему списку процессов
    {
        while (true)
        {
            hCurrentWindow = FindWindowExW(nullptr, hCurrentWindow, nullptr, nullptr); // пробежка по списку
            // Все окна в Windows взаимосвязаны между собой и обобщены в список Z-order
            // При помощи конструкции выше мы перебираем этот список, спускаемся, можно сказать
            if (hCurrentWindow == nullptr) // если окна, на которое мы перешли не существует (дескриптор пустой)
            {
                break; // выходим из while-цикла
            }
            else
            {
                GetWindowThreadProcessId(hCurrentWindow, &dwProcessID); // получаем процесс, к которому относится текущее окно
                // поток нас не интересует, поэтому возвращаемое значение никак не обрабатывается
                if (dwProcessID == (*pidsVec)[i]) // сравнение: эквивалентен ли текущий PID окна PID-у из списка
                {
                    hwndVec->push_back(hCurrentWindow); // если да, записываем окно в список, оно нам подходит
                }
            }
        }
    }
}


int main()
{
    LPCWSTR lpczProcName = L"firefox.exe";
    std::vector<DWORD> pidsVec{}; // вектор, хранящий в себе PID-ы (идентификаторы) процессов
    std::vector<HWND> hwndVec{}; // вектор, хранящий в себе дескрипторы окошек

    getAllProcessIdsByProcNameW(lpczProcName, &pidsVec);
    if (!pidsVec.empty()) // проверки никогда лишними не будут
    {
        getAllWindowHandlesByPyPidsVec(&pidsVec, &hwndVec);
        if (!hwndVec.empty())
        {
            for (size_t i = 0; i < hwndVec.size(); i++)
            {
                // дескриптор окна - это указатель внутри, поэтому и выводим с соответствующим спецификатором
                wprintf(L"%p\n", hwndVec[i]);
            }
        }

        else wprintf(L"The PIDs haven't visible (no only message) windows.\n"); // у процесса нет видимых окон
    }

    else wprintf(L"There're no processes with specified name.\n"); // нет процессов с таким именем
    return 0;
}
Хорошо , щас попробую код и оптишу . Возможно попробую даже завтра так как через 2 дня , диплом защищать а я сижу код пишу ) .
 

Gafask

Участник
Автор темы
137
13
если тебе нужно это для гташки, то получай hwnd через адресс
код:
HWND gameWindow = *(HWND*)0xC97C1Cu;
не для гта , но и не длл ) . А я так понял это работает через длл , ну вариант который ты мне предложил . Но буду иметь ввиду .
Привет, @Разраб ИИ
Конечно, решение @imring тоже имеет право на жизнь, хоть оно и спащено, но оно рабочее. Но у меня душа не будет спокойна, если я не разбируюсь с увиденным кодом. Итого просидел с кодом несколько часиков (мне интересно было узнать про нахождение окон по PID-у, с остальным я был знаком, засел на функции FindWindowExW, т.к читал документацию), расписал каждый шаг своего решения.
Использую wide char (UNICODE), т.к название может состоять не только из ANSI символов.
Если будут вопросы, задавай:
Solution:
#include <windows.h>
#include <tlhelp32.h>
#include <vector>
#include <wchar.h> // wcscmp
#include <stdio.h>


// функция получения списка дочерних и основного процессов по имени
void getAllProcessIdsByProcNameW(LPCWSTR lpczProcName, std::vector<DWORD> *pidsVec)
{
    pidsVec->clear(); // очистка вектора, на всякий случай, не помешает
    PROCESSENTRY32W procEntry = {sizeof(PROCESSENTRY32W)}; // инициализация структуры
    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); // получаем список абсолютно всех процессов в системе (за это отвечает флаг TH32CS_SNAPPROCESS)
    if (Process32FirstW(hSnapshot, &procEntry)) // обработка первого процесса
    {
        while (Process32NextW(hSnapshot, &procEntry)) // и последующих
        {
            // если учитывать, что дочерние процессы носят такое же имя, что и основной процесс, то мы сравниваем строки
            if (wcscmp(procEntry.szExeFile, lpczProcName) == 0)
            {
                pidsVec->push_back(procEntry.th32ProcessID); // закидываем PID в вектор
            }
        }
    }

    CloseHandle(hSnapshot); // не забываем обнулить дескриптор
}


void getAllWindowHandlesByPyPidsVec(const std::vector<DWORD> *pidsVec, std::vector<HWND> *hwndVec)
{
    hwndVec->clear(); // аналогично
    HWND hCurrentWindow = nullptr; // дескриптор текущего окна, пока ни на что не указывает
    DWORD dwProcessID = 0; // PID текущего процесса

    for (size_t i = 0; i < pidsVec->size(); i++) // пробегаемся по нашему списку процессов
    {
        while (true)
        {
            hCurrentWindow = FindWindowExW(nullptr, hCurrentWindow, nullptr, nullptr); // пробежка по списку
            // Все окна в Windows взаимосвязаны между собой и обобщены в список Z-order
            // При помощи конструкции выше мы перебираем этот список, спускаемся, можно сказать
            if (hCurrentWindow == nullptr) // если окна, на которое мы перешли не существует (дескриптор пустой)
            {
                break; // выходим из while-цикла
            }
            else
            {
                GetWindowThreadProcessId(hCurrentWindow, &dwProcessID); // получаем процесс, к которому относится текущее окно
                // поток нас не интересует, поэтому возвращаемое значение никак не обрабатывается
                if (dwProcessID == (*pidsVec)[i]) // сравнение: эквивалентен ли текущий PID окна PID-у из списка
                {
                    hwndVec->push_back(hCurrentWindow); // если да, записываем окно в список, оно нам подходит
                }
            }
        }
    }
}


int main()
{
    LPCWSTR lpczProcName = L"firefox.exe";
    std::vector<DWORD> pidsVec{}; // вектор, хранящий в себе PID-ы (идентификаторы) процессов
    std::vector<HWND> hwndVec{}; // вектор, хранящий в себе дескрипторы окошек

    getAllProcessIdsByProcNameW(lpczProcName, &pidsVec);
    if (!pidsVec.empty()) // проверки никогда лишними не будут
    {
        getAllWindowHandlesByPyPidsVec(&pidsVec, &hwndVec);
        if (!hwndVec.empty())
        {
            for (size_t i = 0; i < hwndVec.size(); i++)
            {
                // дескриптор окна - это указатель внутри, поэтому и выводим с соответствующим спецификатором
                wprintf(L"%p\n", hwndVec[i]);
            }
        }

        else wprintf(L"The PIDs haven't visible (no only message) windows.\n"); // у процесса нет видимых окон
    }

    else wprintf(L"There're no processes with specified name.\n"); // нет процессов с таким именем
    return 0;
}
Спасибо вам , код рабочий . Информативно и спасибо за Коментарии почти к каждой строке ) . Ответил бы раньше , но защита диплома была важнее , а щас все , защитил успешно если интересно !
 
Последнее редактирование: