![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
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 функции передавай объект своей формы. Или любой другой объект, который содержит этот самый массив.