>Форум Mozilla Россия http://forum.mozilla-russia.org/index.php >Разработка http://forum.mozilla-russia.org/viewforum.php?id=18 >Отправка щелчков мышки во flash-объекты из расширения http://forum.mozilla-russia.org/viewtopic.php?id=56791 |
SunnyDay > 25-10-2012 12:38:39 |
Известно, что при симуляции события из под расширения, например щелчка по какому либо элементу: Выделить код Код:evt = target_document.createEvent("MouseEvents"); evt.initMouseEvent("click", true, true, target_document.defaultView, 1, x+ox, y+oy, x, y, false, false, false, false, v, null); element.dispatchEvent(evt); оно посылается с параметром trusted=true , тоесть ведёт себя в принципе как настоящее, и target_document его видит как настоящее. Тоесть по логике при симуляции щелчка на sfw объекте, фаерфокс должен передать события в Flash интерпретатор, но он этого не делает. Собственно необходимо симулировать щелчок на flash-кнопке. Пробовал сделать: DOM видит событие, а во flash не выполняется действие по щелчку в заданных координатах - тоесть во флеше событие не пошло. Вопрос - как средствами фаерфокс-расширения кормить флешу события, чтобы он их обрабатывал ровно также, как настоящие щелчки/перемещения мышки, нажатия клавиш? Буду очень благодарен за любую помощь и ссылки! |
Magneto > 25-10-2012 12:45:32 |
Ну по сути флешки на сайте являются независимыми элементами и все события они обрабатывают напрямую и сами. И если в флешке не предусмотрено пробрасывание события из скрипта, то наверное никак. |
SunnyDay > 25-10-2012 12:54:23 |
-и все события они обрабатывают напрямую и сами -о наверное никак |
hydrolizer > 25-10-2012 14:23:53 |
SunnyDay |
SunnyDay > 25-10-2012 14:54:10 |
hydrolizer пишет
Большое спасибо за инфу, отличное решение! Единственное, в первый раз слышу о js-ctypes, тоесть надо примерно так сделать: Всё верно? Если реализовывал сам, поделись плиз кусочком кода |
hydrolizer > 25-10-2012 17:51:44 |
SunnyDay SunnyDay пишет
Именно это - не реализовывал, я через js-ctypes работал с системными раскладками (GetKeyboardLayout/GetKeyboardLayoutList/ActivateKeyboardLayout etc). |
SunnyDay > 25-10-2012 18:04:56 |
Ясно, спасибо. Что-то придумаю, решение кину в тему. Кнопки в флеше не являются окнами, покрайней мере в AS3. |
SunnyDay > 09-11-2012 18:00:03 |
Проблемма решена! Как и обещал, выкладываю решение: небольшая обёрточка на js-ctypes для работы с windows-окнами, и отправки событий мышки: Выделить код Код:var YBWindows = { loaded: false, //объявление windows-типов CallBackABI: false, WinABI: false, EnumWindowsProc: false, //windows-функции EnumWindows: false, EnumChildWindows: false, PostMessage: false, load: function () { try{ eval('Components.utils.import("resource://gre/modules/ctypes.jsm")'); this.user32dll = ctypes.open("user32.dll"); /* Linux ctypes.open("libc.so.6"); Most other Unixes libc = ctypes.open("libc.so"); */ if (ctypes.size_t.size == 8) { this.CallBackABI = ctypes.default_abi; this.WinABI = ctypes.default_abi; } else { this.CallBackABI = ctypes.stdcall_abi; this.WinABI = ctypes.winapi_abi; } //объявляем тип коллбека this.EnumWindowsProc = ctypes.FunctionType(this.CallBackABI, ctypes.bool, [ctypes.size_t, ctypes.size_t]); //объявляем методы user32.dll для работы с окнами и для отправки событий this.EnumWindows = this.user32dll.declare('EnumWindows', this.WinABI, ctypes.bool, this.EnumWindowsProc.ptr, ctypes.size_t); this.EnumChildWindows = this.user32dll.declare('EnumChildWindows', this.WinABI, ctypes.bool, ctypes.size_t, this.EnumWindowsProc.ptr, ctypes.size_t); eval("this.GetClassName = this.user32dll.declare('GetClassNameW', this.WinABI, ctypes.int, ctypes.size_t, ctypes.jschar.ptr, ctypes.int);"); eval("this.GetWindowText = this.user32dll.declare('GetWindowTextW', this.WinABI, ctypes.int, ctypes.size_t, ctypes.jschar.ptr, ctypes.int);"); this.PostMessage = this.user32dll.declare('PostMessageW', this.WinABI, ctypes.bool, ctypes.size_t, ctypes.unsigned_int, ctypes.size_t, ctypes.size_t); this.loaded = true; }catch(e){ alert(e.message); } }, //возвращает список окон корневого уровня - без параметра parent_hWnd, иначе - окон, дочерних от данного WindowsList: function(parent_hWnd, selector){ if (parent_hWnd==undefined) parent_hWnd = false; if (selector==undefined) selector = false; //список названий оконных дескрипторов - заполняемый коллбеком EnumWindowsCallback var wnames = []; var self = this; var EnumWindowsCallback = function(hwnd, lParam) { try{ var result = true; //wnames.push(self.GetWindowTextLength(hwnd)); var cl_buf = new new ctypes.ArrayType(ctypes.jschar, 255); self.GetClassName(hwnd, cl_buf, 255); var tit_buf = new new ctypes.ArrayType(ctypes.jschar, 255); self.GetWindowText(hwnd, tit_buf, 255); //if (clss.indexOf('mozilla')!=-1||clss.indexOf('firefox')!=-1||clss.indexOf('gecko')!=-1){ var ni = wnames.length; var is_selector = true; if (typeof selector.classname != 'undefined'){ if (cl_buf.readString().toLocaleLowerCase().indexOf(selector.classname)==-1){ is_selector = false; } } if (typeof selector.title != 'undefined'){ if (tit_buf.readString().toLocaleLowerCase().indexOf(selector.title)==-1){ is_selector = false; } } if (is_selector){ wnames.push({classname: cl_buf.readString(),title: tit_buf.readString(), wnd: hwnd, i: ni}); } //в lParam можно вернуть окно }catch(e){ alert(e.message); return false; } return true; }; //создание указателя на коллбэк ф-ю var callback_ptr = this.EnumWindowsProc.ptr(EnumWindowsCallback); //создаем переменную, адрес которой будет передан в калбэк-функцию var wnd = ctypes.size_t(0); //типизация оказалась строгая, приходится приводить типы в явном виде с ctypes.cast if (parent_hWnd){ this.EnumChildWindows(parent_hWnd, callback_ptr, ctypes.cast(wnd.address(), ctypes.size_t)); }else{ this.EnumWindows(callback_ptr, ctypes.cast(wnd.address(), ctypes.size_t)); } return wnames; }, //возвращает дерево окон - от родителя parent_hWnd, либо окон топ-уровня WindowsTree: function(base_selector, parent_hWnd){ if (base_selector==undefined) base_selector = false; if (parent_hWnd==undefined) parent_hWnd = false; var list = this.WindowsList(parent_hWnd, base_selector); var mywin_arr = Array(); for(var i=0;i<list.length;i++){ list[i].childs = this.WindowsTree(false,list[i].wnd); mywin_arr.push(list[i]); } return mywin_arr; }, //эмулирует щелчок мыши через PostMessage SendMouseEvent: function(wnd, event, x, y, params){ var params_code = 0; try{ if (params == undefined) params = false; else { for(var i=0;i<params.length;i++){ if (params[i]=='MK_CONTROL'){ params_code = params_code | 0x0008; }else if (params[i]=='MK_LBUTTON'){ params_code = params_code | 0x0001; }else if (params[i]=='MK_MBUTTON'){ params_code = params_code | 0x0010; }else if (params[i]=='MK_RBUTTON'){ params_code = params_code | 0x0002; }else if (params[i]=='MK_SHIFT'){ params_code = params_code | 0x0004; } } } var evt_code = 0; if (event == 'WM_MOUSEMOVE'){ evt_code = 0x0200; }else if (event == 'WM_LBUTTONDOWN'){ evt_code = 0x0201; }else if (event == 'WM_LBUTTONUP'){ evt_code = 0x0202; }else if (event == 'WM_RBUTTONDOWN'){ evt_code = 0x0204; }else if (event == 'WM_RBUTTONUP'){ evt_code = 0x0205; }else if (event == 'WM_MBUTTONDOWN'){ evt_code = 0x0207; }else if (event == 'WM_MBUTTONUP'){ evt_code = 0x0208; } var coords = (y << 16) | (x & 0xFFFF); this.PostMessage(wnd, evt_code,params_code,coords); }catch(e){ alert(e.message); } } } YBWindows.load(); мы можем посмотреть все окна вот так(вывод в фаербаг): Выделить код Код:content.document.defaultView.wrappedJSObject.console.log(YBWindows.WindowsList());//список окон content.document.defaultView.wrappedJSObject.console.log(YBWindows.WindowsTree());//дерево окон найти главные окна фаерфокса вот так: Выделить код Код:content.document.defaultView.wrappedJSObject.console.log(YBWindows.WindowsTree({classname: 'mozillawindow', title: 'mozilla'})); отправить в первое главное окно щелчок вот так: Выделить код Код:var hwnd = YBWindows.WindowsList({classname: 'mozillawindow', title: 'mozilla'})[0].wnd; YBWindows.SendMouseEvent(hwnd, 'WM_LBUTTONDOWN',350,400); YBWindows.SendMouseEvent(hwnd, 'WM_LBUTTONUP',350,400); щелчок обрабатывается флешом, мало того такая отправка сообщений работает на свёрнутых окнах. Единственное что не получилось - это отправлять щелчок на определённую вкладку, ибо Starting in Gecko 2.0 (Firefox 4 / Thunderbird 3.3 / SeaMonkey 2.1), only the top level browser window has an HWND. https://developer.mozilla.org/en-US/docs/Code_snippets/Finding_Window_Handles но это не критично. Помогла статья с хабра http://habrahabr.ru/post/111044/ . Ещё впилю потом в обёртку работу на линуксах дабы не рушить кроссплатформенность, и симуляция клавиатурных событий аналогично мышовых. Гидролизер, благодарю |
SunnyDay > 25-02-2013 14:44:10 |
По просьбе орец выкладываю рабочий код кормёжки флеша событиями: обновлённый класс работы с windows (linux пока не заморачивал..) Выделить код Код:var YBOSWrapper = { loaded: false, //объявление windows-типов CallBackABI: false, WinABI: false, EnumWindowsProc: false, //windows-функции EnumWindows: false, EnumChildWindows: false, PostMessage: false, load: function () { try{ eval('Components.utils.import("resource://gre/modules/ctypes.jsm")'); this.user32dll = ctypes.open("user32.dll"); /* Linux ctypes.open("libc.so.6"); Most other Unixes libc = ctypes.open("libc.so"); */ if (ctypes.size_t.size == 8) { this.CallBackABI = ctypes.default_abi; this.WinABI = ctypes.default_abi; } else { this.CallBackABI = ctypes.stdcall_abi; this.WinABI = ctypes.winapi_abi; } //объявляем тип коллбека this.EnumWindowsProc = ctypes.FunctionType(this.CallBackABI, ctypes.bool, [ctypes.size_t, ctypes.size_t]); //объявляем методы user32.dll для работы с окнами и для отправки событий this.EnumWindows = this.user32dll.declare('EnumWindows', this.WinABI, ctypes.bool, this.EnumWindowsProc.ptr, ctypes.size_t); this.EnumChildWindows = this.user32dll.declare('EnumChildWindows', this.WinABI, ctypes.bool, ctypes.size_t, this.EnumWindowsProc.ptr, ctypes.size_t); eval("this.GetClassName = this.user32dll.declare('GetClassNameW', this.WinABI, ctypes.int, ctypes.size_t, ctypes.jschar.ptr, ctypes.int);"); eval("this.GetWindowText = this.user32dll.declare('GetWindowTextW', this.WinABI, ctypes.int, ctypes.size_t, ctypes.jschar.ptr, ctypes.int);"); this.PostMessage = this.user32dll.declare('PostMessageW', this.WinABI, ctypes.bool, ctypes.size_t, ctypes.unsigned_int, ctypes.size_t, ctypes.size_t); }catch(e){ alert(e.message); } }, //возвращает список окон корневого уровня - без параметра parent_hWnd, иначе - окон, дочерних от данного WindowsList: function(parent_hWnd, selector){ if (parent_hWnd==undefined) parent_hWnd = false; if (selector==undefined) selector = false; //список названий оконных дескрипторов - заполняемый коллбеком EnumWindowsCallback var wnames = []; var self = this; var EnumWindowsCallback = function(hwnd, lParam) { try{ var result = true; //wnames.push(self.GetWindowTextLength(hwnd)); var cl_buf = new new ctypes.ArrayType(ctypes.jschar, 255); self.GetClassName(hwnd, cl_buf, 255); var tit_buf = new new ctypes.ArrayType(ctypes.jschar, 255); self.GetWindowText(hwnd, tit_buf, 255); //if (clss.indexOf('mozilla')!=-1||clss.indexOf('firefox')!=-1||clss.indexOf('gecko')!=-1){ var ni = wnames.length; var is_selector = true; if (typeof selector.classname != 'undefined'){ if (cl_buf.readString().toLocaleLowerCase().indexOf(selector.classname)==-1){ is_selector = false; } } if (typeof selector.title != 'undefined'){ if (tit_buf.readString().toLocaleLowerCase().indexOf(selector.title)==-1){ is_selector = false; } } if (is_selector){ wnames.push({classname: cl_buf.readString(),title: tit_buf.readString(), wnd: hwnd, i: ni}); } //в lParam можно вернуть окно }catch(e){ alert(e.message); return false; } return true; }; //создание указателя на коллбэк ф-ю var callback_ptr = this.EnumWindowsProc.ptr(EnumWindowsCallback); //создаем переменную, адрес которой будет передан в калбэк-функцию var wnd = ctypes.size_t(0); //типизация оказалась строгая, приходится приводить типы в явном виде с ctypes.cast if (parent_hWnd){ this.EnumChildWindows(parent_hWnd, callback_ptr, ctypes.cast(wnd.address(), ctypes.size_t)); }else{ this.EnumWindows(callback_ptr, ctypes.cast(wnd.address(), ctypes.size_t)); } return wnames; }, //возвращает дерево окон - от родителя parent_hWnd, либо окон топ-уровня WindowsTree: function(base_selector, parent_hWnd){ if (base_selector==undefined) base_selector = false; if (parent_hWnd==undefined) parent_hWnd = false; var list = this.WindowsList(parent_hWnd, base_selector); var mywin_arr = Array(); for(var i=0;i<list.length;i++){ list[i].childs = this.WindowsTree(false,list[i].wnd); mywin_arr.push(list[i]); } return mywin_arr; }, //эмулирует щелчок мыши через PostMessage SendMouseEvent: function(wnd, event, x, y, params){ var params_code = 0; try{ if (params == undefined) params = false; else { for(var i=0;i<params.length;i++){ if (params[i]=='MK_CONTROL'){ params_code = params_code | 0x0008; }else if (params[i]=='MK_LBUTTON'){ params_code = params_code | 0x0001; }else if (params[i]=='MK_MBUTTON'){ params_code = params_code | 0x0010; }else if (params[i]=='MK_RBUTTON'){ params_code = params_code | 0x0002; }else if (params[i]=='MK_SHIFT'){ params_code = params_code | 0x0004; } } } var evt_code = 0; if (event == 'WM_MOUSEMOVE'){ evt_code = 0x0200; }else if (event == 'WM_LBUTTONDOWN'){ evt_code = 0x0201; }else if (event == 'WM_LBUTTONUP'){ evt_code = 0x0202; }else if (event == 'WM_RBUTTONDOWN'){ evt_code = 0x0204; }else if (event == 'WM_RBUTTONUP'){ evt_code = 0x0205; }else if (event == 'WM_MBUTTONDOWN'){ evt_code = 0x0207; }else if (event == 'WM_MBUTTONUP'){ evt_code = 0x0208; } var coords = (y << 16) | (x & 0xFFFF); this.PostMessage(wnd, evt_code,params_code,coords); }catch(e){ alert(e.message); } } } рабочий код для отправки щелчка мышки: Выделить код Код:... //находим окно // !если ифрейм - берём документ родителя var hwnd = this.hwnd_in_cache(owdoc); if (!hwnd){ var ffwindows = this.oswrapper.WindowsList(false,{classname: 'mozillawindow', title: 'mozilla'}); for(var i=0;i<ffwindows.length;i++){ var tit = ffwindows[i].title; if (tit.indexOf(owdoc.title.substring(0, 10))!=-1){ hwnd = ffwindows[i].wnd; this.hwnd_cache[i] = {document: owdoc, hwnd: hwnd}; break; } } } //переброс на активную вкладку if (!hwnd){ return false; } // ! logger если не нашли окно this.oswrapper.SendMouseEvent(hwnd, 'WM_LBUTTONDOWN',x+document_offset.x,y+document_offset.y); var self = this; setTimeout(function(){ self.oswrapper.SendMouseEvent(hwnd, 'WM_LBUTTONUP',x+document_offset.x,y+document_offset.y); // this.dispatch oncomplete event },100+Math.random()*200); клавишные события я только тестовый код пробовал, уже потерял.. Потом второй способ событий во флеш - через PreloadSwf, он оказался для меня лучше: as3: Выделить код Код://конструктор public function PreloadSwf():void { //trace(root.name); addEventListener("allComplete", allComplete); .... ExternalInterface.addCallback("Simulate", this.Simulate); } private function allComplete(e:Event):void { removeEventListener("allComplete", allComplete); var info:LoaderInfo = e.target as LoaderInfo; trace(info.url, "is being monitored"); var domain:String = getDomainFromURL(info.url) //info.url. if (domain!=""){ flash.system.Security.allowDomain(domain); } MonitoredSWFs.push(info); } private function findSWF():LoaderInfo{ for each (var li:LoaderInfo in MonitoredSWFs){ if (li.url.indexOf(monitoredDfl)==li.url.length-monitoredDfl.length){ return li; } } return null; } .... public function Simulate(x:Number,y:Number):String{ // var stg:Stage = findSWF().content.stage; var under_pt:Array = stg.getObjectsUnderPoint(new Point(x,y)); var rets:String = ""; var bubbles:Boolean = true; //under_pt[5] if (!under_pt.length){return "not found";} var uo:DisplayObject = under_pt[under_pt.length - 1]; //for each (var uo:DisplayObject in monitored){ rets+=RemovePackageFromClassname(getQualifiedClassName(uo)) + "-"+uo.name+", v="+(uo.visible?"1":"0")+"\n"; uo.dispatchEvent(new MouseEvent(MouseEvent.MOUSE_MOVE, bubbles, false, x-5, y-5)); uo.dispatchEvent(new MouseEvent(MouseEvent.MOUSE_OVER, bubbles, false, x, y)); setTimeout(function(tmo:DisplayObject):void{ tmo.dispatchEvent(new MouseEvent(MouseEvent.MOUSE_DOWN, bubbles, false, x, y)); },50,uo); setTimeout(function(tmo:DisplayObject):void{ tmo.dispatchEvent(new MouseEvent(MouseEvent.CLICK, bubbles, false, x, y)); },100,uo); setTimeout(function(tmo:DisplayObject):void{ tmo.dispatchEvent(new MouseEvent(MouseEvent.MOUSE_UP, bubbles, false, x, y)); },150,uo); setTimeout(function(tmo:DisplayObject):void{ tmo.dispatchEvent(new MouseEvent(MouseEvent.MOUSE_OUT, bubbles, false, x+5, y+5)); },250,uo); //} return rets; } вмонтировать PreloadSwf надо через правку [винда-папка-пользователя]/файла mm.cfg добавить строчку например PreloadSwf=C:\Users\goncharov\Adobe Flash Builder 4.6\fltest\bin-debug\PreloadSwf.swf далее всё просто - в JS коде плагина document_with_sfw.getElementsByTagName('EMBED')[0].Simulate(20, 30); кликнет по локальным координатам флешки x:20 y:30 - работает даже если браузер свёрнут и вкладка не активна, поэтому я оставил этот способ, хоть он и требует Flash дебаг версии для инъекции PreloadSwf . |
Орец > 25-02-2013 20:25:24 |
SunnyDay |