versiones guia español descargar actualizar c++ windows winapi windows-7

c++ - guia - ¿Cómo obtener el identificador de la ventana principal desde la identificación del proceso?



qgis manual (7)

¿Cómo obtener el identificador de la ventana principal desde la identificación del proceso?

Quiero llevar esta ventana al frente.

Funciona bien en "Process Explorer".



Como una extensión de la solución de Hiale, podría proporcionar una versión diferente o modificada que admita procesos que tengan múltiples ventanas principales.

Primero, modifique la estructura para permitir el almacenamiento de múltiples identificadores:

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

En segundo lugar, modifique la función de devolución de llamada:

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

Finalmente, modifique los retornos de la función 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; }


Comprobé cómo .NET determina la ventana principal.

Mi hallazgo mostró que también usa EnumWindows() .

Este código debería hacerlo de manera similar a la forma .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); }


Esta es mi solución usando Win32 / C ++ puro basado en la respuesta principal. La idea es envolver todo lo requerido en una función sin la necesidad de funciones o estructuras externas de devolución de llamada:

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


Existe la posibilidad de un malentendido aquí. El framework WinForms en .Net designa automáticamente la primera ventana creada (por ejemplo, Application.Run(new SomeForm()) ) como MainWindow . La API win32, sin embargo, no reconoce la idea de una "ventana principal" por proceso. El ciclo de mensajes es totalmente capaz de manejar tantas ventanas "principales" como los recursos del sistema y del proceso le permitirán crear. Entonces, su proceso no tiene una "ventana principal". Lo mejor que puede hacer en el caso general es usar EnumWindows() para EnumWindows() todas las ventanas no secundarias en un proceso determinado e intente utilizar algunas heurísticas para determinar cuál es la que desea. Afortunadamente, la mayoría de los procesos tienen una única ventana "principal" ejecutándose la mayor parte del tiempo, por lo que debería obtener buenos resultados en la mayoría de los casos.


No creo que Windows (a diferencia de .NET) proporcione una forma directa de obtener eso.

La única forma que conozco es enumerar todas las ventanas de nivel superior con EnumWindows() y luego buscar qué proceso pertenece cada una a GetWindowThreadProcessID() . Esto suena indirecto e ineficiente, pero no es tan malo como cabría esperar: en un caso típico, es posible que tenga que recorrer una docena de ventanas de nivel superior ...


Solo para asegurarse de que no confunde el tid (id. De subproceso) y el pid (Id. De proceso):

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