Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Общие вопросы > Список дочерных объектов


Автор: Serebrus 22.12.2011, 09:14
Привет всем.
В окне другой программы (разработан не в Delphi) имеются несколько объектов: (в языке delphi) 1 Panel, в нем 2 GroupBox и в каждом из них по две button..

Хотел узнать, как можно создать список всех имеющихся объектов, включая их классы (если можно по иерархии).
Главное (родительское) окно нашел с помощью FindWindow, а вот самих объектов не смог функцией FindWindowEx

Спасибо

Автор: Serebrus 22.12.2011, 09:57
Функции GetWindow и GetNextWindow с флагом GW_HWNDNEXT тоже не помогли, они зацикливаются в одном объекте (т.е. не переходят на другой, после нахождения второго объекта повторяют отображать его)

Автор: Coder 22.12.2011, 13:35
Нужно использовать функцию EnumChildWindows().
Есть пример обхода формы и составления иерархи объектов, но он на C++. Если разбираешься могу скинуть.

Автор: Serebrus 22.12.2011, 13:47
Coder, был бы очен презнателен.

Автор: Coder 22.12.2011, 13:53
Держи smile
Unicode версия.

Код

// Вывод строки на экран
void __log(TCHAR *_str, HWND _hWnd){
    int i = SendMessage(g_StatusList, LB_ADDSTRING, 0, LPARAM(_str));
    if (i != LB_ERR)
        SendMessage(g_StatusList, LB_SETITEMDATA, i, LPARAM(_hWnd));
}

TCHAR WindowName[MAX_PATH], ClassName[MAX_PATH], FullName[MAX_PATH*2+1]; 

// ф-ия обратного вызова. 
// hWnd - найденное окно
// _lParam - используется для передачи уровня иерархии
bool CALLBACK EnumWindowsProc(HWND hWnd, LPARAM _lParam) {    
    ZeroMemory(FullName, sizeof(FullName));
    ZeroMemory(WindowName, sizeof(WindowName));
    ZeroMemory(FullName, sizeof(FullName));

    // Получаем класс и имя окна
    GetWindowText(hWnd, WindowName, sizeof(WindowName)); 
    GetClassName(hWnd, ClassName, sizeof(ClassName));

    // форматируем текст для вывода
    
    // в зависимости от уровня иерархии сдвигаем надпись вправо
    for (int i=0; i<_lParam; i++)
        wcscat_s(FullName, ARRAYSIZE(FullName), L"        ");
    // если это не 0 уровень, добавим >
    if (_lParam)
        wcscat_s(FullName, ARRAYSIZE(FullName), L"> ");

    // добавляем имя класса
    wcscat_s(FullName, ARRAYSIZE(FullName), ClassName);
    // если окно имеет имя, выводим его чере точку.
    if (wcslen(WindowName) > 0){
        wcscat_s(FullName, ARRAYSIZE(FullName), L".");
        wcscat_s(FullName, ARRAYSIZE(FullName), WindowName);
    }

    // выводим на экран полученную строку - Класс.ИмяОкна
    __log(FullName, hWnd);

    // начинаем поиск дочерних окно для текущего. увеличиваем уровень иерархии на 1
    EnumChildWindows(hWnd, (WNDENUMPROC)EnumWindowsProc, _lParam+1);

    return true;
}

void _EnumWindows(){
    // Родительское окно - начинаем поиск с него
    HWND TopWnd = FindWindow(NULL, L"new 1 - Notepad++");
    EnumChildWindows(TopWnd, (WNDENUMPROC)EnumWindowsProc, 0);

    return;
}

Автор: Serebrus 22.12.2011, 15:15
Спасибо Coder.

Вот мой код:
Код

function GetNew(hw: HWND): BOOL; stdcall;
var s:Pchar;
begin
s:=GetMemory(200);
SendMessage(hw,WM_GetText,200,integer(s));
Form1.ListBox1.Items.Add(IntToStr(hw)+' - '+s);
FreeMemory(s);
EnumChildWindows(hw, @GetNew, 0);
end;

procedure TForm1.Button2Click(Sender: TObject);
var
 s:Pchar;
 p, Wnd, h:Hwnd;
 buff: ARRAY [0..127] OF Char;
begin
ListBox1.Items.Clear;
p:=FindWindow(nil,'Single Code');
if p<>0 then
 GetNew(p);
else
 ShowMessage('Окно не найдено');


Но почемуто этот код не отображает все компоненты, как буд-то функции EnumChildWindows сказано найти только n-ое количество компонентов.
В чем может быть "ограничение"?

Автор: Coder 23.12.2011, 03:31
Держи...

Код

var
  WindowName, ClassName : array[0..MAX_PATH] of char;
  FullName : array[0..MAX_PATH*2] of char;

// ф-ия обратного вызова. 
// hWnd - найденное окно
// _lParam - используется для передачи уровня иерархии
function EnumWindowsProc(hWnd : HWND; _lParam : LPARAM) : boolean; stdcall;
var
  i : Integer;
begin
  ZeroMemory(@FullName, sizeof(FullName));
  ZeroMemory(@WindowName, sizeof(WindowName));
  ZeroMemory(@FullName, sizeof(FullName));

  // Получаем класс и имя окна
  GetWindowText(hWnd, @WindowName, sizeof(WindowName));
  GetClassName(hWnd, @ClassName, sizeof(ClassName));

  // форматируем текст для вывода
    
  // в зависимости от уровня иерархии сдвигаем надпись вправо
  for i:=0 to _lParam-1 do
    StrCat(FullName, '        ');

  // если это не 0 уровень, добавим >
  if (_lParam>0) then
    StrCat(FullName, '> ');

  // добавляем имя класса
  StrCat(FullName, ClassName);
  // если окно имеет имя, выводим его чере точку.
  if (strlen(WindowName) > 0) then
    begin
      StrCat(FullName, '.');
      StrCat(FullName, WindowName);
    end;

  // выводим на экран полученную строку - Класс.ИмяОкна
  Form1.Memo1.Lines.Add(FullName);

  // начинаем поиск дочерних окно для текущего. увеличиваем уровень иерархии на 1
  EnumChildWindows(hWnd, @EnumWindowsProc, _lParam+1);

  result:=true;
end;

procedure _EnumWindows();
var
  TopWnd : HWND;
begin
    // Родительское окно - начинаем поиск с него
    TopWnd := FindWindow(0, 'The Bat!');
    EnumChildWindows(TopWnd, @EnumWindowsProc, 0);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  Memo1.Clear;
  _EnumWindows();
end;

Автор: Serebrus 23.12.2011, 07:35
Coder, огромное спасибо вам.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)