Подтвердить что ты не робот

Как получить главный дескриптор окна из идентификатора процесса?

Как получить дескриптор окна main из идентификатора процесса?

Я хочу перенести это окно на передний план.

Он отлично работает в "Process Explorer".

4b9b3361

Ответ 1

Я проверил, как .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);
}

Ответ 2

Я не считаю, что Windows (в отличие от .NET) предоставляет прямой способ получить это.

Единственный способ, которым я знаю, - перечислить все окна верхнего уровня с помощью EnumWindows(), а затем найти, какой процесс принадлежит каждому из GetWindowThreadProcessID(). Это звучит косвенно и неэффективно, но это не так плохо, как вы могли ожидать - в типичном случае у вас может быть дюжина окон верхнего уровня, чтобы пройти...

Ответ 3

Там есть возможность неправильного понимания здесь. Структура WinForms в .Net автоматически определяет первое созданное окно (например, Application.Run(new SomeForm())) как MainWindow. Однако API win32 не распознает идею "главного окна" для каждого процесса. Цикл сообщений полностью способен обрабатывать столько "главных" окон, сколько системные и технологические ресурсы позволят вам создать. Таким образом, ваш процесс не имеет "главного окна". Лучшее, что вы можете сделать в общем случае, это использовать EnumWindows(), чтобы активировать все не-дочерние окна в данном процессе и попытаться использовать некоторые эвристики, чтобы выяснить, какой из них вам нужен. К счастью, большинство процессов, скорее всего, будут иметь одно "основное" окно, выполняемое большую часть времени, поэтому вы должны получать хорошие результаты в большинстве случаев.

Ответ 4

Это моё решение с использованием чистого 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;
}

Ответ 5

Хотя это может быть не связано с вашим вопросом, посмотрите функцию GetGUIThreadInfo.

Ответ 6

Просто чтобы убедиться, что вы не путаете tid (идентификатор потока) и pid (идентификатор процесса):

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

Ответ 7

В качестве расширения для решения 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;   
 }

Наконец, внесите изменения в функцию main:

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

Ответ 8

Я ищу функцию в заголовке "winuser.h".

Мой код:

#include <vcl.h>
#include <windows.h>
#include <winuser.h>
#include <stdlib.h>
#include <string.h>
#include <iostream.h>'


#pragma hdrstop
#include "Unit1.h"

#pragma package(smart_init)
#pragma resource "*.dfm"
TWinyMouse *WinyMouse;

#define WM_LBUTTONDOWN 0x0201
#define WM_LBUTTONDBLCLK 0x0203
#define WM_RBUTTONDOWN 0x0204

#define MOUSEEVENTF_MOVE 0x0001
#define MOUSEEVENTF_LEFTDOWN 0x0002
#define MOUSEEVENTF_LEFTUP 0x0004
#define MOUSEEVENTF_RIGHTDOWN 0x0008
#define MOUSEEVENTF_RIGHTUP 0x0010
#define MOUSEEVENTF_MIDDLEDOWN 0x0020
#define MOUSEEVENTF_MIDDLEUP 0x0040
#define MOUSEEVENTF_XDOWN 0x0080
#define MOUSEEVENTF_XUP 0x0100
#define MOUSEEVENTF_WHEEL 0x0800
#define MOUSEEVENTF_VIRTUALDESK 0x4000
#define MOUSEEVENTF_ABSOLUTE 0x8000

int SleepTime;
int VectorX[10000];
int VectorY[10000];
int MouseFunction[10000];
int TrackBarPosition;
int IterationEnd;
int VectorIndex=0;
int RecordSwitch=0;
char Key;
POINT Coordinates;
int XCoord, YCoord;
//int X,Y;
//int Button,State;
int XPos,YPos;
//TMessage Mensaje;
HWND hWnd;
//enum TMouseButton { mbLeft, mbRight, mbMiddle };
TMouseButton Button;
TShiftState Estado;
int X,Y;
int XPointer;
int YPointer;
TMouseButton Boton;
POINT RasterCoords;
int Playing;
int TestMode;
int XDrag,YDrag;
int XDragged,YDragged;
int XStore,YStore;
int Timer1Enabled;
int FirstClickDetected;
int cx,cy;
MSG msg;
bool bRet;
int TimerEnabled=0;
TMessage WndProcMessage;
AnsiString DesktopWindowHandle;
LPTSTR StringClass;
DWORD lpdwProcessId;


__fastcall TWinyMouse::TWinyMouse(TComponent* Owner)
        : TForm(Owner)
{
 /*static HINSTANCE hLib;

 hLib = LoadLibrary("user32.dll");

 if (hLib == NULL)
   {
    ShowMessage("LoadLibrary Failed.\n");
   }


  HWND hwnd;
  MSG msg;
  WNDCLASSEX wcx;

  //Definimos la estructura de clase de ventana (campos):
  wcx.cbSize = sizeof( WNDCLASSEX );      // tamaño de la estruct.
  wcx.style = CS_HREDRAW | CS_VREDRAW;    // valores más usuales
  wcx.lpfnWndProc = WndProc;              // función de ventana
  wcx.cbClsExtra = 0;
  wcx.cbWndExtra = 0;                     // informaciones extra
  wcx.hInstance = hInstance;              // instancia actual

  //icono, cursor, fondo e icono pequeño de la clase de ventana:
  wcx.hIcon = LoadIcon(NULL, IDI_WINLOGO);
  wcx.hCursor = LoadCursor(NULL, IDC_ARROW);
  wcx.hbrBackground = (HBRUSH) GetStockObject( WHITE_BRUSH );
  wcx.hIconSm = LoadIcon(NULL, IDI_WINLOGO);

  wcx.lpszMenuName = NULL;                // nombre del menú
  wcx.lpszClassName = WindowName;         // nombre de la ventana

  //Registramos la clase de ventana ya preparada:
  if( !RegisterClassEx( &wcx ) )
  return( FALSE );               // si hay error salir

 //Creamos la ventana con CreateWindowEx():
    hwnd = CreateWindowEx(
    WS_EX_OVERLAPPEDWINDOW,          // estilo extendido
    WindowName,                      // nombre de la ventana
    WindowTitle,                     // título de la ventana
    WS_OVERLAPPEDWINDOW,             // estilo de ventana
    CW_USEDEFAULT, CW_USEDEFAULT,    // Posición (x,y) en pantalla
    400, 300,                        // ancho y alto de la ventana
    NULL, NULL,                      // ventana padre e hija+menú
    hInstance,                       // instancia actual
    NULL                             // no hay más información
                       );

  //Comprobamos la creación de la ventana:
  if( !hwnd )
    return( FALSE );                 // si hay error, salir

  Hacemos visible la ventana y la actualizamos:
  ShowWindow( hwnd, nCmdShow );
  UpdateWindow( hwnd );
  */
 }


void StoreLeftClick()
    {
     GetCursorPos(&Coordinates);
     XStore=Coordinates.x;
     YStore=Coordinates.y;
     VectorX[VectorIndex]=XStore;
     VectorY[VectorIndex]=YStore;
     MouseFunction[VectorIndex]=1;
     VectorIndex++;
     WinyMouse->LabelActionNumber->Caption=VectorIndex;
    }

void StoreDoubleClick()
    {
     GetCursorPos(&Coordinates);
     XStore=Coordinates.x;
     YStore=Coordinates.y;
     VectorX[VectorIndex]=XStore;
     VectorY[VectorIndex]=YStore;
     MouseFunction[VectorIndex]=2;
     VectorIndex++;
     WinyMouse->LabelActionNumber->Caption=VectorIndex;
    }

void StoreRightClick()
    {
     GetCursorPos(&Coordinates);
     XStore=Coordinates.x;
     YStore=Coordinates.y;
     VectorX[VectorIndex]=XStore;
     VectorY[VectorIndex]=YStore;
     MouseFunction[VectorIndex]=3;
     VectorIndex++;
     WinyMouse->LabelActionNumber->Caption=VectorIndex;
    }


void Play(void)
    {
     if (RecordSwitch==0)
       {
        Playing=1;
        for(VectorIndex=0;VectorIndex<IterationEnd;VectorIndex++)
           {
            switch (MouseFunction[VectorIndex])
                  {
                   case 1:
                          XCoord=VectorX[VectorIndex];
                          YCoord=VectorY[VectorIndex];
                          SetCursorPos(XCoord,YCoord);
                          mouse_event(MOUSEEVENTF_LEFTDOWN,XCoord,YCoord,0,0);
                          mouse_event(MOUSEEVENTF_LEFTUP,XCoord,YCoord,0,0);
                          break;

                  case 2:
                          XCoord=VectorX[VectorIndex];
                          YCoord=VectorY[VectorIndex];
                          SetCursorPos(XCoord,YCoord);
                          mouse_event(MOUSEEVENTF_LEFTDOWN,XCoord,YCoord,0,0);
                          mouse_event(MOUSEEVENTF_LEFTUP,XCoord,YCoord,0,0);
                          mouse_event(MOUSEEVENTF_LEFTDOWN,XCoord,YCoord,0,0);
                          mouse_event(MOUSEEVENTF_LEFTUP,XCoord,YCoord,0,0);
                          break;

                  case 3:
                         XCoord=VectorX[VectorIndex];
                         YCoord=VectorY[VectorIndex];
                         SetCursorPos(XCoord,YCoord);
                         mouse_event(MOUSEEVENTF_RIGHTDOWN,XCoord,YCoord,0,0);
                         mouse_event(MOUSEEVENTF_RIGHTUP,XCoord,YCoord,0,0);
                        break;
                  default:
                          break;
                 }
            Sleep(SleepTime);
           }

        }
       Playing=0;
     }

void StopTimer(void)
    {
     TimerEnabled=0;
    }

void StartTimer(void)
   {
    TimerEnabled=1;
   }

void __fastcall TWinyMouse::ButtonRecordClick(TObject *Sender)
{
 RecordSwitch=1;
 WinyMouse->AlphaBlend=true;
 StartTimer();
}

void __fastcall TWinyMouse::ButtonStopClick(TObject *Sender)
{
 RecordSwitch=0;
 IterationEnd=VectorIndex;
 WinyMouse->AlphaBlend=false;
 StopTimer();
}

void __fastcall TWinyMouse::ButtonPlayClick(TObject *Sender)
{
 Play();
}

void __fastcall TWinyMouse::ButtonClearClick(TObject *Sender)
{
 for (VectorIndex=0;VectorIndex<=IterationEnd;VectorIndex++)
    {
     VectorX[VectorIndex]=0;
     VectorY[VectorIndex]=0;
     MouseFunction[VectorIndex]=0;
    }
 LabelActionNumber->Caption=0;
 VectorIndex=0;
}

void __fastcall TWinyMouse::TrackBarSTBAChange(TObject *Sender)
 {
  TrackBarPosition=(WinyMouse->TrackBarSTBA->Position);
  SleepTime=5001-TrackBarPosition;
  WinyMouse->LabelSTBAms->Caption=SleepTime;
 }


void __fastcall TWinyMouse::TimerTimer(TObject *Sender)
{
 if (TimerEnabled==1)
   {
     //GetClassNameA(hWnd, StringClass, 1024);

    //-->Here it'd come the help I'm asking for

    while( GetMessage( &msg, hWnd, 0, 0 ) )
   {

    //Label1->Caption=hWnd.c_str();
    TranslateMessage( &msg );    // convertimos el mensaje kbd
    DispatchMessage( &msg );     // lanzamos WndProc
    switch(msg.message)
              {
               case WM_LBUTTONDOWN:
                    StoreLeftClick();
                    break;

               case WM_LBUTTONDBLCLK:
                    StoreDoubleClick();
                    break;

               case WM_RBUTTONDOWN:
                    StoreRightClick();
                    break;

               default:
                       break;
              }
    }
  }
  else
      {
      }
}

Как называется функция, которая будет извлекать переменную HWND любого окна из любого процесса? Примеры: окно Windows, Adobe Reader, Firefox, Chrome, pdfktbuilder и т.д.

Ответ 9

Честно говоря, я не хочу, чтобы ты был твоим врагом, так что это мой последний пост.

Я допускаю расхождения, но не хочу входить в бесконечный цикл:

Мы (и я не говорил вам) не можем объявить функцию как CALLBACK... в большинстве случаев, если вы переопределите функцию CALLBACK, мы не сможем получить какую-либо переменную ввода/вывода для этих функций.

С наилучшими пожеланиями.

В любом случае спасибо за ответ