Показать сообщение отдельно
  #10  
Старый 21.04.2009, 11:51
Nyctos Kasignete Nyctos Kasignete вне форума
Активный
 
Регистрация: 29.03.2009
Сообщения: 300
Репутация: 94
По умолчанию

одинадцатый, функцию EnumChildWindows необходимо вызывать из самой callback функции EnumThrWndProc! Я теперь уже забросила первый вариант, который вы привели. Использую тот, который в посте #6. Поэтому буду показывать на примере именно его.
Да простят меня модераторы, но приведу код полностью (в который раз!), чтобы не оставалось никаких неясностей, в конце концов...
Код:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  THandles = array of HWND;

  TThreadIdHandles = record
    ThreadId: Cardinal;
    Handles: THandles;
  end;

  TForm1 = class(TForm)
    StartProgramBtn: TButton;
    GetTextBtn: TButton;
    Memo1: TMemo;
    procedure StartProgramBtnClick(Sender: TObject);
    procedure GetTextBtnClick(Sender: TObject);
  private
    { Private declarations }
    procedure GetAllWndHandlesFromThreads;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  ThreadIdHandles: array[0..3] of TThreadIdHandles;
  function EnumThrWndProc(hndl: HWND; lprm: LPARAM): BOOL; stdcall;
  function EnumChildWndProc(hndl: HWND; lprm: LPARAM): BOOL; stdcall;

implementation

{$R *.dfm}

function EnumChildWndProc(hndl: HWND; lprm: LPARAM): BOOL; stdcall;
var
  WndTxt: PChar;
begin
  Result := True;
  GetMem(WndTxt, 255);
  try
    GetWindowText(hndl, WndTxt, 255);
    Form1.Memo1.Lines.Add(StrPas(WndTxt));
  finally
    FreeMem(WndTxt, 255);
  end;
end;

function EnumThrWndProc(hndl: HWND; lprm: LPARAM): BOOL; stdcall;
var
  ToolWndStyle: Integer;
  PrevHandlesLen: Integer;
begin
  Result := True;
  ToolWndStyle := GetWindowLong(hndl, GWL_EXSTYLE) and WS_EX_TOOLWINDOW;
  { take into account only non-tool windows from the thread }
  if ToolWndStyle = 0 then
     with ThreadIdHandles[lprm] do
     begin
       PrevHandlesLen := Length(Handles);
       SetLength(Handles, PrevHandlesLen + 1);
       Handles[PrevHandlesLen] := hndl;
     end;
  EnumChildWindows(hndl, @EnumChildWndProc, 0);
end;

procedure TForm1.GetAllWndHandlesFromThreads;
var
  i: Byte;
begin
  for i := 0 to 3 do
    EnumThreadWindows(ThreadIdHandles[i].ThreadId, @EnumThrWndProc, i);
end;

procedure TForm1.StartProgramBtnClick(Sender: TObject);
const
  WinDirPath = 'g:\programs\forex\mt4';
  ProgPath = 'g:\programs\forex\mt4\terminal.exe';
var
  i: Byte;
  _si: STARTUPINFO;
  _pi: PROCESS_INFORMATION;
  Evnt: THandle;
begin
  for i := 0 to 3 do
  begin
    ThreadIdHandles[i].Handles := nil;
    FillChar(_si, SizeOf(_si), 0);
    _si.cb := SizeOf(_si);
    _si.dwFlags := STARTF_USESHOWWINDOW;
    _si.wShowWindow := SW_SHOWNORMAL;

    CreateProcess(@ProgPath[1], nil, nil, nil, False, NORMAL_PRIORITY_CLASS, nil,
                  @WinDirPath[1], _si, _pi);
    ThreadIdHandles[i].ThreadId := _pi.dwThreadId;
  end;

  // do a delay only once before calling GetAllWndHandlesFromThreads proc.
  Evnt := CreateEvent(nil, False, False, nil);
  WaitForSingleObject(Evnt, 1500);
  CloseHandle(Evnt);
  Form1.GetAllWndHandlesFromThreads();
end;

procedure TForm1.GetTextBtnClick(Sender: TObject);
var
  i: Byte;
  j: Integer;
  wndtxt: PChar;
begin
  GetMem(wndtxt, 200);
  try
    Memo1.Lines.Clear;
    for i := 0 to 3 do
      for j := 0 to High(ThreadIdHandles[i].Handles) do
      begin
        GetWindowText(ThreadIdHandles[i].Handles[j], wndtxt, 200);
        Memo1.Lines.Add(StrPas(wndtxt));
      end;
  finally
    FreeMem(wndtxt, 200);
  end;
end;

end.
При переборе дочерних теперь выводятся в Memo заголовки кнопок и прочего.

P.S. одинадцатый, уже давайте что-ли пользоваться BB-кодами, а то схватите предупреждение от Admin'а или модератора...
Код оформляется так: [code]Сюда вставляется код[/code]

P.P.S. По поводу различий при запуске с ярлыка и с CreateProcess. Раскопайте в справке описание функции CreateProcess. Возможно, что дело в том, что вы не используете атрибуты безопасности при запуске приложения. Вместо некоторых nil, которые вы передаете в параметрах функции CreateProcess, в общем случае должны стоять указатели на структуру SECURITY_ATTRIBUTES. Хотя я не утверждаю, что дело именно в этом. И атрибутами безопасности я никогда не пользовалась...
Ответить с цитированием