ProgramingTip

프로세스 ID에서 기본 창 핸들을 얻는 방법은 무엇입니까?

bestdevel 2021. 1. 6. 20:52
반응형

프로세스 ID에서 기본 창 핸들을 얻는 방법은 무엇입니까?


프로세스 ID에서 기본 창 핸들 을 얻는 방법은 무엇입니까?

이 창문을 앞으로 가져오고 싶습니다.

"프로세스 탐색기"에서 잘 작동합니다.


.NET이 기본 창을 결정하는 방법을 확인했습니다.

내 발견은 또한 EnumWindows().

이 코드는 .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);
}

나는 Windows (.NET과 반대)가 그것을 사용할 수있는 방법을 제공합니다.

내가 아는 유일한 방법은 모든 최상위 창을 열거 EnumWindows()한 다음 여러 프로세스를 찾는 것 GetWindowThreadProcessID()입니다. 이것은 실질적으로 비효율적으로 들리지만 예상만큼 나쁘게됩니다. 일반적인 경우에는 12 개의 최상위 창을 통과 할 수 있습니다.


여기에 오해의 가능성이 있습니다. .NET의 윈폼 프레임 워크는 자동적으로 작성 상기 윈도우 (예를 들어, 지정 Application.Run(new SomeForm())은 AS)를 MainWindow. 그러나 win32 API는 프로세스 당 "메인 창"이라는 개념을 인식하지 못합니다. 메시지 루프는 시스템 및 프로세스 리소스가 생성 할 수있는만큼의 "주"창을 완전히 처리 할 수 ​​있습니다. 따라서 프로세스에는 "메인 창"이 없습니다. 일반적인 경우에 할 수있는 최선의

EnumWindows()방법은 주어진 프로세스에서 버전이 아닌 모든 창을 활성화하고 몇 가지 휴리스틱을 사용하여 원하는 창이 무엇인지 알아내는 것입니다. 운 좋게도 대부분의 프로세스는 대부분의 경우 단일 "메인"창만 실행 대부분의 경우 좋은 결과를 얻을 수 있습니다.


이것은 최상위 답변을 기반으로 순수한 Win32 / C ++를 사용하는 내 솔루션입니다. 아이디어는 외부 서비스 함수 나 구조없이 필요한 모든 것을 하나의 함수로 래핑하는 것입니다.

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

귀하의 질문과 관련이 없을 수 없습니다. GetGUIThreadInfo 기능을 사용할 수 있습니다.


tid (스레드 ID)와 pid (프로세스 ID)를 혼동하지 않도록 방지하기 위해 :

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

Hiale 솔루션의 확장으로 여러 개의 기본 창이있는 프로세스를 지원하는 다른 또는 수정 된 버전을 제공 할 수 있습니다.

먼저 몇 가지 처리를 수행 할 수 있습니다.

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

둘째, 지속 함수를 수정합니다.

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

마지막으로 주 함수의 수익을 수정합니다.

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

참조 URL : https://stackoverflow.com/questions/1888863/how-to-get-main-window-handle-from-process-id

반응형