Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

EnumChildWindows [D6, Win2k]


Сережа550 ©   (2004-04-20 10:57:00) 

Уважаемые знатоки, подскажите пожалуйста, как можно через EnumChildWindows положить хендлы объектов дочернего окна в массив? Дескриптор родительского окна известен. Массив, например, array [0..255] of HWND;


Сережа550   (2004-04-21 10:38:00) [1]

Вообще, откровенно говоря, мне необходимо следующее: необязательно кликать на флешки - мне надо узнать, на какой сайт эти флешки ведут. Но так, как флеш - может содержать кучу кнопок, каждая из которых ведет на свой сайт, (или никуда не ведет, а выполняет какое-то действие), то я хотел прокликать по всем координатам флешки, отловить все URL куда браузер переходит и дальше уже работать с полученными данными... А если еще учесть, что флешки бывают: с прописанными в коде страницы URL'ами, вшитыми в них URL'ами, URL'ами, грузящимися из Java-script'ов, то единственный универсальный способ понять, куда ведет флешка - это только кликнуть на нее... И именно с этим я и мучаюсь уже три недели к ряду... Молю всех о помощи.

2 MetalFan:Спасибо большое за код, но как я уже писал, это не поможет решить мне мою задачу... :(


MetalFan   (2004-04-21 10:14:00) [2]


> int64   (20.04.04 14:40) [10]
> 1. Я так и предполагал. Не нужны им левые сообщения.
> 2. У меня работает. Может дело в Д6. Попробуй так:
> TempUnk.QueryInterface(IShockwaveFlash, Result);

TempUnk.QueryInterface(IID_IShockwaveFlash, Result);


Сережа550   (2004-04-21 10:08:00) [3]

Спасибо, этот способ, к сожалению, не решит моей задачи, потому что мне не надо двигать мышь к объекту, а затем нажимать на него, мне надо на него лишь нажать (даже если окно с этим объектом свернуто). Окон с эксплорерами будет очень много, многие из них будут свернуты. Вообщем, я уже обдумывал этот метод и он, к моему огромному сожалению, мне не подходит...


nikkie   (2004-04-20 20:58:00) [4]

имитировать действия мышью можно с помощью mouse_event


Сережа550   (2004-04-20 17:50:00) [5]

1. Я так и предполагал. Не нужны им левые сообщения.
Самое странное, что "левое" сообщение правого клика работает, а левого клика - уже нет. :(

2. У меня работает. Может дело в Д6. Попробуй так:
TempUnk.QueryInterface(IShockwaveFlash, Result);
Теперь ошибки не происходит, но Assigned(Flash) остается False. Да, и к тому же, ты прав - если я даже загружу флешку в ShockwaveFlash - то это врядли поможет мне решить мою задачу...

Нет, все таки - каким же образом можно программно кликнуть по Flash-баннеру? С меня ящик пива за правильный ответ! ПОМОГИТЕ!:)


int64   (2004-04-20 14:40:00) [6]

1. Я так и предполагал. Не нужны им левые сообщения.
2. У меня работает. Может дело в Д6. Попробуй так:
TempUnk.QueryInterface(IShockwaveFlash, Result);


Сережа550   (2004-04-20 14:14:00) [7]

1. Через PostMessage не удается - все работает: без проблем эмулируется событие клика правой кнопки мыши, закрывается, а при посыле сообщения клика левой кнопкой мышки - ничего не происходит... В чем может быть проблема?
2. Этот код у меня, к сожалению, не работает... В функции GetFlash строка "Result := TempUnk as IShockwaveFlash" вызывает ошибку - Interface Not Supported. В чем может быть проблема?


int64   (2004-04-20 13:53:00) [8]

Через интефейсы сможешь делать что-то типа Play, Stop...
Для твоей задачи не подойдет.
Тогда уж лучше PostMessage.

Как получить интерфейс:

function GetFlash(WB: IWebbrowser2; FlashNumber: Integer): IShockwaveFlash;
var
 OleContainer: IOleContainer;
 enum: IEnumUnknown;
 TempUnk: IUnknown;
 Fetched: PLongint;
 ObjNo, FlasNo: integer;
 Coll: HTMLElementCollection;
begin
 FlasNo := 0;
 with WB do
   begin
     while ReadyState <> READYSTATE_COMPLETE do
       Forms.Application.ProcessMessages;
     if Assigned(document) then
       begin
         Coll := HTMLElementCollection(HTMLDocument(Document).All.Tags('OBJECT'));
         for ObjNo := 0 to Coll.length - 1 do
           if HtmlObjectElement(Coll.item(ObjNo, varEmpty)).classid =
             'clsid:D27CDB6E-AE6D-11cf-96B8-444553540000' then
             begin
               if FlasNo = FlashNumber then
                 break;
               inc(FlasNo);
             end;
         Fetched := nil;
         OleContainer := Document as IOleContainer;
         OleContainer.EnumObjects(OLECONTF_EMBEDDINGS, Enum);
         Enum.Skip(ObjNo);
         Enum.Next(1, TempUnk, Fetched);
         Result := TempUnk as IShockwaveFlash;
       end
     else
       Result := nil;
   end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
 Flash: IShockwaveFlash;
begin
 Flash := GetFlash(WebBrowser1.ControlInterface, 0);
 if Assigned(Flash) then
   Flash.Zoom(2);
end;


Не забудь импортировать Shockwave Flash (Flash.ocx).


Сережа550   (2004-04-20 12:59:00) [9]

Я в этом не особенно разбираюсь. Может напишешь небольшой примерчик "получения COM-интерфейса к флешу". Необходимость та же - на загруженной страничке кликать флэшки в определенные координаты... На самом деле, необходимость в этом очень большая, я уже 3 недели мучаюсь...


int64   (2004-04-20 12:06:00) [10]

Откуда такая уверенность, что Flash-объект будет обрабатывать ваши сообщения.

function GetFirstFlashFomFirstHWND_IE: HWND;
begin
 Result := FindWindow('IEFrame', nil);
 Result := FindWindowEX(Result, 0, 'Shell DocObject View', nil);
 Result := FindWindowEX(Result, 0, 'Internet Explorer_Server', nil);
 Result := FindWindowEX(Result, 0, 'MacromediaFlashPlayerActiveX', nil);
end;


Не лучше ли получить СОМ-интерфейс к флешу.


Сережа550   (2004-04-20 11:58:00) [11]

Я просто написал упрощенный пример, чтобы не возникало дополнительных трудностей. На самом деле необходимо следующее: На форме есть TWebBrowser, в него загружен определенный сайт. На сайте есть куча Flash-объектов. Я так понимаю, что все flash-объекты данного сайта являются как бы дочерними окнами WebBrowser'а и мне необходимо узнать Handl'ы этих объектов, чтобы затем послать им сообщение о нажатии на него левой кнопкой мышки:

PostMessage(Handle этого объекта, WM_LBUTTONDOWN, 0, MAKELPARAM(1,1));
PostMessage(Handle этого объекта, WM_LBUTTONUP, 0, MAKELPARAM(1,1));

Если есть другой вариант каким-то образом нажать на Flash-объект, буду очень благодарен... :)


easy   (2004-04-20 11:57:00) [12]

unit Unit1;

interface

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

type
 TForm1 = class(TForm)
   Button1: TButton;
   TreeView1: TTreeView;
   procedure Button1Click(Sender: TObject);
 private
   { Private declarations }
 public
   { Public declarations }
 end;

var
 Form1: TForm1;

implementation

{$R *.dfm}
function GetWindowTitle(hwnd: HWND): string;
begin
 SetLength(Result, 255);
 SetLength(Result, GetWindowText(hwnd, PChar(Result), 255));
end;

function GetWindowClass(hwnd: HWND): string;
begin
 SetLength(Result, 255);
 SetLength(Result, GetClassName(hwnd, PChar(Result), 255));
end;

function GetWindowInfo(hwnd: HWND): string;
begin
 Result := GetWindowTitle(hwnd) + ' [' + GetWindowClass(hwnd) +
   '] (' + IntToStr(hwnd) + ')';
end;

function EnumChildProc(hwnd: HWND; lParam: Integer): BOOL; stdcall;
var
 NewNode, ParentNode: TTreeNode;
begin
 Result := True;
 ParentNode := TTreeNode(lParam);
 NewNode := ParentNode.Owner.AddChild(ParentNode,
   GetWindowInfo(hwnd));
 EnumChildWindows(hwnd, @EnumChildProc, Integer(NewNode));
end;

function EnumWindowsProc(hwnd: HWND; lParam: Integer): BOOL; stdcall;
var
 NewNode: TTreeNode;
begin
 Result := True;
 NewNode := TTreeView(lParam).Items.Add(nil, GetWindowInfo(hwnd));
 EnumChildWindows(hwnd, @EnumChildProc, Integer(NewNode));
end;

procedure EnumWindowsTree(Tree: TTreeView);
begin
 EnumWindows(@EnumWindowsProc, Integer(Tree));
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
 TreeView1.Items.Clear;
 EnumWindowsTree(TreeView1);
end;

end.


int64   (2004-04-20 11:47:00) [13]

Какой практический смысл?
Не пришлось бы заполнять дерево.


Сережа550   (2004-04-20 11:45:00) [14]

Может я чего-то не понял (опыта с winapi было мало)... Но, объясню по другому:
Есть TGroupBox, в нем лежат какие-то объекты (кнопки, edit'ы и т.п.) - но я не знаю сколько их, как они называются и т.п. Вот мне и нужно с помощью EnumChildWindows - указать в качестве родительского окна - GroupBox1.Handle, а далее забить в массив хендлы всех дочерних этому GroupBox'у объектов. Но как это сделать, я, к сожалению, не знаю... Если можно, небольшой (или большой) пример.


SPeller   (2004-04-20 11:32:00) [15]

В параметре CallBack функции передавай объект своей формы. Или любой другой объект, который содержит этот самый массив.


Наверх

Титульная страница Поиск, карта сайта Написать письмо