Определить, сколько окон открыто из определенного приложения Windows?

Оконные API для меня новы. Я пытаюсь найти количество окон, открытых в настольном приложении Windows. Я хотел открыть только один экземпляр приложения.

У меня есть приложение abc.exe. Если пользователь попытается открыть приложение abc.exe в первый раз, приложение abc.exe откроется в обычном режиме. Но если приложение abc.exe уже открыто, и пользователь пытается открыть его снова, он должен предоставить уже открытый экземпляр приложения.

Я могу получить уже открытый экземпляр с помощью приведенного ниже кода в определенных условиях.

BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam) {
HWND *retHwnd = (HWND *)lParam;

if (*retHwnd) {
    return FALSE;
}

DWORD procID = 0;
auto threadID = GetWindowThreadProcessId(hwnd, &procID);

auto handle = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, procID);

QString fileName;
if (handle) {
    TCHAR filename[FILENAME_MAX];
    auto len = GetModuleFileNameEx(handle, NULL, filename, FILENAME_MAX);

    fileName = QFileInfo(QString::fromWCharArray(filename, len)).fileName();
    if (GetLastApplicationName() == fileName) {
        *retHwnd = hwnd;
    }

    CloseHandle(handle);
}

return TRUE;
}

void ShowExistingInstance() {
HWND hwnd = 0;
auto res = EnumWindows(&EnumWindowsProc, (LPARAM)&hwnd);

    if (hwnd) {
        ShowWindow(hwnd, SW_MINIMIZE);
        ShowWindow(hwnd, SW_MINIMIZE);
        ShowWindow(hwnd, SW_RESTORE);
    }
}

Однако я не получаю первый экземпляр приложения, если из приложения открыты два окна.

Ниже я упомяну две ситуации. В первой ситуации код работает нормально, а во второй ситуации код не работает нормально.

1) Получить уже открытый экземпляр приложения

Шаги:

а. Пользователь щелкает значок приложения abc.exe.

b. Главное окно открыто, например, его имя mainWindow1.

c. Восстановить или свернуть mainWindow1

d. Пользователь снова щелкает abc.exe, используя значок приложения.

e. Здесь я получаю mainWindow1, и это правильно.

2) Не получает уже открытый экземпляр приложения

Шаги:

а. Пользователь щелкает значок приложения abc.exe.

b. Главное окно открыто, например, его имя mainWindow1.

c. Пользователь открывает другое окно из текущего приложения, например, его имя mainWindow2. (mainWindow1 не является родителем mainWindow2).

d. Восстановить или свернуть mainWindow1 (здесь mainWindow2 также автоматически свернуто или восстановить вниз относительно mainWindow1)

e. Пользователь снова щелкает abc.exe, используя значок приложения.

f. Здесь я получаю mainWindow2 вместо mainWindow1.

Мне нужен был какой-то ориентир для Windows API, который помог бы мне найти Hwnd Mainwidnow1 во второй ситуации.


person Yash    schedule 20.02.2019    source источник
comment
Вы можете отслеживать Win32_ProcessStartTrace и Win32_ProcessStopTrace для обнаружения запуска и остановки приложений. Вот пример Win32_ProcessStopTrace. Однако, если у вас есть исходный код для abc.exe, вам нужно сделать его единственным экземпляром таким образом.   -  person Reza Aghaei    schedule 20.02.2019
comment
Спасибо, Реза Агай, за руководство.   -  person Yash    schedule 20.02.2019


Ответы (1)


Я получил свою функциональность с помощью кода ниже

BOOL isMainWindow(HWND handle) {
return GetWindow(handle, GW_OWNER) == (HWND)0 && IsWindowVisible(handle);
}

BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam) {
    HWND *retHwnd = (HWND *)lParam;

    if (*retHwnd) {
       return FALSE;
    }

    DWORD procID = 0;
    auto threadID = GetWindowThreadProcessId(hwnd, &procID);

    if (!isMainWindow(hwnd)) {
        return TRUE;
    }

    auto handle = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, procID);

   QString fileName;
   if (handle) {
        TCHAR filename[FILENAME_MAX];
        auto len = GetModuleFileNameEx(handle, NULL, filename, FILENAME_MAX);

        fileName = QFileInfo(QString::fromWCharArray(filename, len)).fileName();
        if (GetLastApplicationName() == fileName) {
            *retHwnd = hwnd;
        }

        CloseHandle(handle);
    }

return TRUE;
}
void ShowExistingInstance() {
    HWND hwnd = 0;
    auto res = EnumWindows(&EnumWindowsProc, (LPARAM)&hwnd);

   if (hwnd) {
       ShowWindow(hwnd, SW_MINIMIZE);
       ShowWindow(hwnd, SW_MINIMIZE);
       ShowWindow(hwnd, SW_RESTORE);
   }
 }
person Yash    schedule 20.02.2019