it-swarm.dev

Como obter o identificador da janela principal do id do processo?

Como obter o manipulador main window do id do processo?

Eu quero trazer essa janela para a frente.

Funciona bem no "Process Explorer".

53
Alexey Malistov

Eu verifiquei como o .NET determina a janela principal.

Minha descoberta mostrou que também usa EnumWindows().

Este código deve fazê-lo de forma semelhante ao modo .NET:

struct handle_data {
    unsigned long process_id;
    HWND window_handle;
};

HWND find_main_window(unsigned long process_id)
{
    handle_data data;
    data.process_id = process_id;
    data.window_handle = 0;
    EnumWindows(enum_windows_callback, (LPARAM)&data);
    return data.window_handle;
}

BOOL CALLBACK enum_windows_callback(HWND handle, LPARAM lParam)
{
    handle_data& data = *(handle_data*)lParam;
    unsigned long process_id = 0;
    GetWindowThreadProcessId(handle, &process_id);
    if (data.process_id != process_id || !is_main_window(handle))
        return TRUE;
    data.window_handle = handle;
    return FALSE;   
}

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

Eu não acredito que o Windows (em oposição ao .NET) forneça uma maneira direta de conseguir isso.

A única maneira que conheço é enumerar todas as janelas de nível superior com EnumWindows() e depois descobrir qual processo cada pertence a GetWindowThreadProcessID(). Isso parece indireto e ineficiente, mas não é tão ruim quanto você poderia esperar - em um caso típico, você pode ter uma dúzia de janelas de nível superior para percorrer ...

36
Jerry Coffin

Existe a possibilidade de um mal entendido aqui. O framework WinForms em .Net designa automaticamente a primeira janela criada (por exemplo, Application.Run(new SomeForm())) como MainWindow. A API do win32, no entanto, não reconhece a ideia de uma "janela principal" por processo. O loop de mensagens é totalmente capaz de manipular tantas janelas "principais" quanto os recursos do sistema e do processo permitem criar. Então, o seu processo não tem uma "janela principal". O melhor que você pode fazer no caso geral é usar EnumWindows() para obter todas as janelas não-filhas ativas em um determinado processo e tentar usar algumas heurísticas para descobrir qual delas é a desejada. Felizmente, a maioria dos processos provavelmente só tem uma única janela "principal" em execução na maioria das vezes, portanto você deve obter bons resultados na maioria dos casos.

11
Dathan

Esta é a minha solução usando o Win32/C++ puro com base na resposta principal. A ideia é envolver tudo o que é necessário em uma função sem a necessidade de funções ou estruturas externas de retorno de chamada:

#include <utility>

HWND FindTopWindow(DWORD pid)
{
    std::pair<HWND, DWORD> params = { 0, pid };

    // Enumerate the windows using a lambda to process each window
    BOOL bResult = EnumWindows([](HWND hwnd, LPARAM lParam) -> BOOL 
    {
        auto pParams = (std::pair<HWND, DWORD>*)(lParam);

        DWORD processId;
        if (GetWindowThreadProcessId(hwnd, &processId) && processId == pParams->second)
        {
            // Stop enumerating
            SetLastError(-1);
            pParams->first = hwnd;
            return FALSE;
        }

        // Continue enumerating
        return TRUE;
    }, (LPARAM)&params);

    if (!bResult && GetLastError() == -1 && params.first)
    {
        return params.first;
    }

    return 0;
}
5
Benj

Embora possa não estar relacionado à sua pergunta, dê uma olhada em GetGUIThreadInfo Function .

2
AntonK

Apenas para ter certeza de que você não está confundindo o tid (id do thread) e o pid (id do processo):

DWORD pid;
DWORD tid = GetWindowThreadProcessId( this->m_hWnd, &pid);
0
Oliver Zendel

Como uma extensão da solução da Hiale, você poderia fornecer uma versão diferente ou modificada que suporte processos que tenham várias janelas principais.

Primeiro, altere a estrutura para permitir o armazenamento de várias alças:

struct handle_data {
    unsigned long process_id;
    std::vector<HWND> handles;
};

Em segundo lugar, altere a função de retorno de chamada:

BOOL CALLBACK enum_windows_callback(HWND handle, LPARAM lParam)
{
    handle_data& data = *(handle_data*)lParam;
    unsigned long process_id = 0;
    GetWindowThreadProcessId(handle, &process_id);
    if (data.process_id != process_id || !is_main_window(handle)) {
        return TRUE;
    }
    // change these 2 lines to allow storing of handle and loop again
    data.handles.Push_back(handle);
    return TRUE;   
 }

Por fim, corrija os retornos da função principal:

std::vector<HWD> find_main_window(unsigned long process_id)
{
    handle_data data;
    data.process_id = process_id;
    EnumWindows(enum_windows_callback, (LPARAM)&data);
    return data.handles;
}
0
Class Skeleton