it-swarm.com.de

Wie bekomme ich das Hauptfenster-Handle von der Prozess-ID?

Wie bekomme ich main window handle von der Prozess-ID?

Ich möchte dieses Fenster nach vorne bringen.

Es funktioniert gut im "Process Explorer".

53
Alexey Malistov

Ich habe geprüft, wie .NET das Hauptfenster bestimmt.

Mein Befund zeigte, dass es auch EnumWindows() verwendet.

Dieser Code sollte dies ähnlich wie .NET tun:

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

Ich glaube nicht, dass Windows (im Gegensatz zu .NET) einen direkten Weg bietet, dies zu erreichen.

Die einzige Möglichkeit, die ich kenne, besteht darin, alle Fenster der obersten Ebene mit EnumWindows() aufzuzählen und dann herauszufinden, welcher Prozess zu GetWindowThreadProcessID() gehört. Das klingt indirekt und ineffizient, aber es ist nicht so schlimm, wie Sie vielleicht erwarten - in einem typischen Fall haben Sie vielleicht ein Dutzend Fenster auf oberster Ebene, durch die Sie gehen können.

36
Jerry Coffin

Hier besteht die Möglichkeit eines Missverständnisses. Das WinForms-Framework in .Net bestimmt automatisch das erste erstellte Fenster (z. B. Application.Run(new SomeForm())) als MainWindow. Die Win32-API erkennt jedoch nicht die Idee eines "Hauptfensters" pro Prozess. Die Nachrichtenschleife ist in der Lage, so viele "Hauptfenster" zu verarbeiten, wie Sie von System- und Prozessressourcen erstellt werden können. Ihr Prozess hat also kein "Hauptfenster". Das Beste, was Sie im Allgemeinen tun können, ist EnumWindows(), um alle nicht untergeordneten Fenster für einen bestimmten Prozess zu aktivieren, und versuchen Sie, anhand einiger Heuristiken herauszufinden, welches das gewünschte ist. Glücklicherweise haben die meisten Prozesse meist nur ein einziges "Hauptfenster", daher sollten Sie in den meisten Fällen gute Ergebnisse erzielen.

11
Dathan

Dies ist meine Lösung mit reinem Win32/C++, basierend auf der Top-Antwort. Die Idee ist, alles Erforderliche in einer Funktion zusammenzufassen, ohne dass externe Callback-Funktionen oder -Strukturen erforderlich sind:

#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

Obwohl dies möglicherweise nicht mit Ihrer Frage zusammenhängt, lesen Sie die GetGUIThreadInfo-Funktion .

2
AntonK

Nur um sicherzugehen, dass Sie nicht die tid (Thread ID) und die pid (Prozess ID) verwechseln:

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

Als Erweiterung der Lösung von Hiale können Sie eine andere oder geänderte Version bereitstellen, die Prozesse mit mehreren Hauptfenstern unterstützt.

Ändern Sie zunächst die Struktur, um das Speichern mehrerer Handles zu ermöglichen:

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

Zweitens ändern Sie die Rückruffunktion:

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

Ändern Sie abschließend die Rückgaben für die Hauptfunktion:

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