Форум по Delphi программированию

Delphi Sources



Вернуться   Форум по Delphi программированию > Все о Delphi > [ "Начинающим" ]
Ник
Пароль
Регистрация <<         Правила форума         >> FAQ Пользователи Календарь Поиск Сообщения за сегодня Все разделы прочитаны

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
  #1  
Старый 18.10.2010, 19:13
MrDiG MrDiG вне форума
Начинающий
 
Регистрация: 05.10.2010
Сообщения: 112
Репутация: 1227
По умолчанию Клик в свёрнутом окне

На форме WebBrowser. В нём - флеш игра. Нужно кликнуть по заданым координатам. Всё отлично работает через Mouse_event.

Код:
  {Переместим курсор мыши}
  Mouse_Event(MOUSEEVENTF_ABSOLUTE or MOUSEEVENTF_MOVE, Pt.x, Pt.y, 0, 0);
  {Имитируем нажатие левой кнопки мыши}
Mouse_Event(MOUSEEVENTF_ABSOLUTE or MOUSEEVENTF_LEFTDOWN, Pt.x, Pt.y, 0, 0);
  {Имитируем отпускание левой кнопки мыши}
Mouse_Event(MOUSEEVENTF_ABSOLUTE or MOUSEEVENTF_LEFTUP, Pt.x, Pt.y, 0, 0)

Главная проблема - в том, что окно с ботом должно быть открыто. При свёрнутом в трей курсор бегает где угодно, но не там где нужно. Намутил решение через postmessage, но отчего-то работать не хочет. В чём проблема?

Код:
procedure TfrmMain.Button3Click(Sender: TObject);
var
  Pt: TPoint;
  left, top:integer;

  begin
  left:=strtoint(Edit31.Text);
  top:=strtoint(Edit32.Text);
  {Позволим кнопке перерисоваться}
  Application.ProcessMessages;
  {Найдем координаты центра button 1}
  Pt.x := WebBrowser1.Left + left;
  Pt.y := WebBrowser1.Top + top + 25; //костыль в 25 от верхней границы

    {Преобразуем Pt к координатам экрана}
  Pt := ClientToScreen(Pt);
  {Преобразуем Pt к "mickeys" (аболютным координатам курсора мышки}
  Pt.x := Round(Pt.x * (65535 / Screen.Width));
  Pt.y := Round(Pt.y * (65535 / Screen.Height));


postmessage(frmMain.WebBrowser1.Handle,WM_MOVE,0,(Pt. x shl 16)+ Pt.y);
postmessage(frmMain.WebBrowser1.Handle,WM_LBUTTONDOWN,0,(Pt. x shl 16)+ Pt.y);
postmessage(frmMain.WebBrowser1.Handle,WM_LBUTTONUP,0,(Pt.x shl 16)+ Pt.y);
Ответить с цитированием
  #2  
Старый 18.10.2010, 22:13
Asinkrit Asinkrit вне форума
Местный
 
Регистрация: 29.10.2009
Сообщения: 446
Репутация: 271
По умолчанию

Решал я эту задачу, и много форумов обшарил, отправить клик мышки в неактивное окно мне кажется нереальным, единственное что мне удалось, отправить клик мышки в неактивное окно, но и тут есть проблема, окно так и норовит стать активным. Задачу решил следующим способом, перед тем как кликнуть в флешке, я делал окно активным (в моем случае было пять окон), дальше отправлял нужно кол-во кликов, и переходил к следующему окну. А для того что бы это работало на заднем плане, поставил виртуальную машину с XPшкой, там это все и запустил.
Вот ссылка на мои творения в этом направлении.
Ответить с цитированием
  #3  
Старый 18.10.2010, 23:10
MrDiG MrDiG вне форума
Начинающий
 
Регистрация: 05.10.2010
Сообщения: 112
Репутация: 1227
По умолчанию

Вот топик нашёл:
http://www.programmersforum.ru/showthread.php?t=77918

Вроде как рабочий вариант для Notepad.
Код:
postmessage(FindWindowEx(FindWindow('notepad', nil), 0, 'Edit', nil),WM_LBUTTONDOWN,0,(x shl 16)+ y);
postmessage(FindWindowEx(FindWindow('notepad', nil), 0, 'Edit', nil),WM_LBUTTONUP,0, (x shl 16)+ y);
Но как узнать нужный хэндлер я так и не понял.
Ответить с цитированием
  #4  
Старый 20.10.2010, 09:06
MrDiG MrDiG вне форума
Начинающий
 
Регистрация: 05.10.2010
Сообщения: 112
Репутация: 1227
По умолчанию

Перекопал кучу русскоязычных форумов - отправился за материалом в буржунет. Решение существует. Дело в том, что нужно передавать хэндл дочернего окна. А проблема - получается такая "матрёшка" что до нужного хэндла нужно докопаться.

Вот приблизительный код:
Цитата:
procedure TfrmMain.Button3Click(Sender: TObject);
var
Pt: TPoint;
left, top:integer;
Wnd:HWnd;

begin
left:=strtoint(Edit31.Text);
top:=strtoint(Edit32.Text);
{Позволим кнопке перерисоваться}
Application.ProcessMessages;
{Найдем координаты центра button 1}
Pt.x := WebBrowser1.Left + left;
Pt.y := WebBrowser1.Top + top + 25; //костыль в 25 от верхней границы (PageBox)

Pt := ClientToScreen(Pt);
Pt.x := Round(Pt.x * (65535 / Screen.Width));
Pt.y := Round(Pt.y * (65535 / Screen.Height));


Wnd:=FindWindow('TfrmMain',nil);
Wnd:=FindWindowEx(Wnd,0,'TPageContol',nil);
Wnd:=FindWindowEx(Wnd,0,'Shell Embedding',nil);
Wnd:=FindWindowEx(Wnd,0,'Shell DocObject View',nil);
Wnd:=FindWindowEx(Wnd,0,'Internet Explorer_Server',nil);
Wnd:=FindWindowEx(Wnd,0,'MacromediaFlashPlayerActi veX',nil);


postmessage(Wnd,WM_MOVE,0,(Pt. x shl 16)+ Pt.y);
postmessage(Wnd,WM_LBUTTONDOWN,0,(Pt. x shl 16)+ Pt.y);
postmessage(Wnd,WM_LBUTTONUP,0,(Pt.x shl 16)+ Pt.y);

end;

Меня смущает TPageContol - там вкладки две. Как на нужную вывести? Кто сможет объяснить как добраться до нужного хэндла? Вот вывод Spy++:
Ответить с цитированием
  #5  
Старый 20.10.2010, 09:30
Asinkrit Asinkrit вне форума
Местный
 
Регистрация: 29.10.2009
Сообщения: 446
Репутация: 271
По умолчанию

Вот таким вот образом я добирался до флешки, только через WinSight32 дочернее окно называется GeckoPlugin.
Код:
procedure TForm1.GetSubChild(wd: HWnD);
Var Cw:HWnd;
Begin
If WD=0 then Exit;
Cw := FindWindowEx(Wd, 0, nil, nil);
 while (Cw <> 0) do
    begin
       FRes:=cw;
       GetSubChild(Cw);
       Cw := FindWindowEx(Wd, Cw, nil, nil);
     End;
end;
то есть, етот метод ищет самое нижнее дочернее окно, правда если в броузере будет две закладки, то искать будет самое нижнее только в первой вкладке.
Код:
postmessage(Wnd,WM_MOVE,0,(Pt. x shl 16)+ Pt.y);
postmessage(Wnd,WM_LBUTTONDOWN,0,(Pt. x shl 16)+ Pt.y);
postmessage(Wnd,WM_LBUTTONUP,0,(Pt.x shl 16)+ Pt.y);
А вот этот кодя пробовал, действительно клик отправляется в неактивное окно (в свернутое нереально), правда через раз, и приложение все равно пытается стать активным.

Последний раз редактировалось Asinkrit, 20.10.2010 в 09:35.
Ответить с цитированием
  #6  
Старый 20.10.2010, 09:48
MrDiG MrDiG вне форума
Начинающий
 
Регистрация: 05.10.2010
Сообщения: 112
Репутация: 1227
По умолчанию

Цитата:
Сообщение от Asinkrit
А вот этот кодя пробовал, действительно клик отправляется в неактивное окно (в свернутое нереально), правда через раз, и приложение все равно пытается стать активным.

Ну вот продедура, которая отправляет в свёрнутое окно блокнота
Код:
procedure TForm1.Button1Click(Sender: TObject);
var wnd: HWND; i: Integer; s: string;
begin
wnd:=FindWindow('notepad', nil);
if wnd<>0 then
    begin
    wnd:=FindWindowEx(wnd, 0, 'Edit', nil);
    s:='Hello';
    for i:=1 to Length(s) do
        SendMessage(wnd, WM_CHAR, Word(s[i]), 0);
    // Simulate Return Key.
    PostMessage(wnd, WM_KEYDOWN, VK_RETURN, 0);
    // Simulate Space.
    PostMessage(wnd, WM_KEYDOWN, VK_SPACE, 0);
    end;
end;

Только что проверил - работает. И активным стать не пытается.
Ответить с цитированием
  #7  
Старый 20.10.2010, 09:51
Asinkrit Asinkrit вне форума
Местный
 
Регистрация: 29.10.2009
Сообщения: 446
Репутация: 271
По умолчанию

Да но это не клик мышки, ты попробуй именно клик мышки сделать (с клавиатурными сообщениями все немного проще), или к примеру в блокноте добавь кучу текста и попробуй выделить его, то есть MouseDown, MouseMove, MouseUp.
Ответить с цитированием
  #8  
Старый 20.10.2010, 10:07
MrDiG MrDiG вне форума
Начинающий
 
Регистрация: 05.10.2010
Сообщения: 112
Репутация: 1227
По умолчанию

Значит создал файл в блокноте. Забил его единичками. Нижеприведённый код выставляет курсор в указанное мной место. В данном примере x=200 y=200 Проверил и на других числах - работает.
Код:
procedure TForm1.Button1Click(Sender: TObject);
var wnd: HWND; i: Integer; s: string;
begin
wnd:=FindWindow('notepad', nil);
if wnd<>0 then
	begin
	wnd:=FindWindowEx(wnd, 0, 'Edit', nil);
	s:='PIZDEC';
	for i:=1 to Length(s) do
		//SendMessage(wnd, WM_CHAR, Word(s[i]), 0);
	// Simulate Return Key.
	//PostMessage(wnd, WM_KEYDOWN, VK_RETURN, 0);
	// Simulate Space.
	//PostMessage(wnd, WM_KEYDOWN, VK_SPACE, 0);
postmessage(Wnd,WM_MOVE,0,(200 shl 16)+ 200);
postmessage(Wnd,WM_LBUTTONDOWN,0,(200 shl 16)+ 200);
postmessage(Wnd,WM_LBUTTONUP,0,(200 shl 16)+ 200)
	end;
end;

Значит можно-таки движение мыши передать.
Ответить с цитированием
  #9  
Старый 20.10.2010, 10:26
Asinkrit Asinkrit вне форума
Местный
 
Регистрация: 29.10.2009
Сообщения: 446
Репутация: 271
По умолчанию

Ок, а теперь попробуй в флешку тоже самое отправить..) хендл флешки можешь получить используя процедуру что я выше давал, в нее надо передать хендл окна броузера, в FRes получишь хендл флешки.
Ответить с цитированием
  #10  
Старый 20.10.2010, 11:00
MrDiG MrDiG вне форума
Начинающий
 
Регистрация: 05.10.2010
Сообщения: 112
Репутация: 1227
По умолчанию

Торможу с процедурой с утра. Так нужно использовать?
Код:
 var wnd,xxx: HWND;
begin
...
xxx:=frmMain.Webbrowser1.Handle;
wnd:=GetSubChild(xxx);

Где wnd искомый?
Ответить с цитированием
  #11  
Старый 20.10.2010, 14:59
Asinkrit Asinkrit вне форума
Местный
 
Регистрация: 29.10.2009
Сообщения: 446
Репутация: 271
По умолчанию

Я же сказал, в FRes, вот переделал, что бы возвращала хендл.
Код:
function GetSubChild(wd: HWnd):HWnd;
Var 
  Cw:HWnd;
Begin
  Result:=0;
  If WD=0 then Exit;
  Cw := FindWindowEx(Wd, 0, nil, nil);
  while (Cw <> 0) do
    begin
       Result:=cw;
       GetSubChild(Cw);
       Cw := FindWindowEx(Wd, Cw, nil, nil);
     End;
end;
Ответить с цитированием
  #12  
Старый 20.10.2010, 16:48
MrDiG MrDiG вне форума
Начинающий
 
Регистрация: 05.10.2010
Сообщения: 112
Репутация: 1227
По умолчанию

Попробовал. Не тот хэндл отдаёт.

+++Shell DocObject View (этот получил)
++++++Internet Explorer_Server
+++++++++MacromediaFlashPlayerActiveX (этот нужен)
Хотя пиши эти строки и понимаю, что нужно попробовать несколько раз твою функцию использовать


UPD: Ура! О да! Кажется я это сделал! Сейчас домой убегать нужно, рабочий день заканчивается - дома нужно будет потестить. Потом отпишусь.

Последний раз редактировалось MrDiG, 20.10.2010 в 16:58.
Ответить с цитированием
  #13  
Старый 21.10.2010, 03:01
Asinkrit Asinkrit вне форума
Местный
 
Регистрация: 29.10.2009
Сообщения: 446
Репутация: 271
По умолчанию

Функция и так рекурсивная, сама себя вызывает несколько раз, пока до нижнего уровня не дойдет.

Давай, пиши о результатах, очень интересно, если все таки получится невозможное)
Ответить с цитированием
  #14  
Старый 21.10.2010, 09:08
MrDiG MrDiG вне форума
Начинающий
 
Регистрация: 05.10.2010
Сообщения: 112
Репутация: 1227
По умолчанию

Получилось! Только спускать нужно было не до флешки, а до браузера. Навёл WinSpy++ на окно. Показало, что это браузер и уточнил его хэндл. Используя твою функцию и выводя промежуточные хэндлы "спустился" до нужного окна.
Код выглядит приблизительно так:
Код:
procedure TfrmMain.ClickToPage(const left: integer; const top: integer);
var
  Pt: TPoint;
  var wnd: HWND;

  begin
  Application.ProcessMessages;
  Pt.x := WebBrowser1.Left + left;
  Pt.y := WebBrowser1.Top + top;
  Pt := ClientToScreen(Pt);
//{Преобразуем Pt к "mickeys" (аболютным координатам курсора мышки}
//Pt.x := Round(Pt.x * (65535 / Screen.Width));
// Pt.y := Round(Pt.y * (65535 / Screen.Height));


  wnd:=frmMain.WebBrowser1.Handle;
  wnd:=frmMain.GetSubChild(wnd);
  wnd:=frmMain.GetSubChild(wnd);
  //ShowMessage(inttostr(wnd)); // выдаст в десятичной то что WinSpy видит в HEX

postmessage(wnd,WM_MOVE,0,(Pt.x shl 16)+ Pt.y);
postmessage(wnd,WM_LBUTTONDOWN,0,(Pt.x shl 16)+ Pt.y);
postmessage(wnd,WM_LBUTTONUP,0,(Pt.x shl 16)+ Pt.y);
Application.ProcessMessages;

Окно свёрнуто. Активным стать не пытается. Иногда правда что-то не попадаеть, но я думаю это из-за моего остального кода. У меня случайные координаты для клика в случайное место кнопки. Я его ещё не поправил.

Последний раз редактировалось MrDiG, 21.10.2010 в 09:10.
Ответить с цитированием
  #15  
Старый 21.10.2010, 09:39
Asinkrit Asinkrit вне форума
Местный
 
Регистрация: 29.10.2009
Сообщения: 446
Репутация: 271
По умолчанию

Если это работает, то это великолепно, однако есть другая проблема, получить изображение флешки в свернутом окне, вот она точно не решается.
Ответить с цитированием
Ответ


Delphi Sources

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB-коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход


Часовой пояс GMT +3, время: 15:58.


 

Сайт

Форум

FAQ

Соглашения

Прочее

 

Copyright © Форум "Delphi Sources" by BrokenByte Software, 2004-2025