Это своего рода продолжение ответа здесь.
У меня есть настраиваемый элемент управления ActiveX, который вызывает событие («ReceiveMessage» с параметром «msg»), которое необходимо обработать с помощью Javascript в веб-браузере. Исторически мы могли использовать следующий синтаксис, предназначенный только для IE, для достижения этой цели в разных проектах:
function MyControl::ReceiveMessage(msg)
{
alert(msg);
}
Однако, находясь внутри макета, в котором скрыт элемент управления, Javascript не может найти элемент управления. В частности, если мы поместим это на простую HTML-страницу, он будет работать нормально, но если мы поместим его на страницу ASPX, обернутую тегом <Form>, мы получим ошибку «MyControl is undefined». Мы пробовали варианты следующего:
var GetControl = document.getElementById("MyControl");
function GetControl::ReceiveMessage(msg)
{
alert(msg);
}
... но это приводит к ошибке Javascript «GetControl is undefined».
Как правильно обрабатывать событие, отправляемое из элемента управления ActiveX? Сейчас мы заинтересованы только в том, чтобы это работало в IE. Это должен быть настраиваемый элемент управления ActiveX для того, что мы делаем.
Спасибо.
Я никогда раньше не видел синтаксиса ::, где это задокументировано?
Трудно найти актуальную документацию по нему, но вот ссылка на статью MSDN, в которой это упоминается: msdn.microsoft.com/en-us/library/ms974564.aspx
Стоит отметить, что события подключаются правильно только в том случае, если объект ActiveX создается с использованием тега OBJECT. Если вы создаете их с помощью CreateActiveXObject (), вы можете сделать что-то другое, например: codeproject.com/KB/dotnet/extend_events.aspx?display=Print
Ссылка, на которую вы ссылаетесь, теперь использует HTTPS - (msdn.microsoft.com/en-us/library/ms974564.aspx). Также я спросил и ответил по этому поводу здесь; Я также написал библиотека, чтобы обойти это. (Копия @Rory).



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Мне удалось заставить это работать, используя следующий формат блока скрипта, но мне все еще любопытно, лучший ли это способ:
<script for = "MyControl" event = "ReceiveMessage(msg)">
alert(msg);
</script>
Во многих примерах в Интернете я видел следующий код: <script for = "MyControl" event = "ReceiveMessage"> function ReceiveMessage (msg) {alert (msg); } </script> Несмотря на то, что вышеуказанное будет работать, имейте в виду, что это не сработает, если ваше событие будет запущено несколько раз. Я обнаружил это, когда подключил событие ReceiveMessag к таймеру в элементе управления ActiveX, который сработал после заданного интервала. Каждый раз, когда событие запускается, обработчик будет вызываться, сколько раз событие было запущено. (например: 1-й огонь: 1 раз, 2-й огонь: 2 раза, 3-й огонь: 3 раза). Понятия не имею, почему! Ответы?
Кажется, если вы используете синтаксис :: в теге <script for = "..., тогда он сделает то, что вы говорите - снова подключает событие при каждом его вызове. Если вы просто выполняете сценарий или просто выполняете function :: syntax Я думаю, что он работает нормально (за исключением этого случая нахождения внутри тега FORM).
кому-нибудь из вас удалось заставить это работать для метода, который имеет объект EventArgs в качестве аргумента
неважно, как я понял, каждый тип, "задействованный" в интерфейсе ActiveX, должен быть ComVisible
Начиная с IE 9, этот метод подключения событий работает, если используется тег объекта HTML. Если используется "var ax = new ActiveXObject ('myProgId')", то динамическое подключение событий работает -> "eval ('function ax :: EventInterfaceMethod (args) {return myJavaScriptMethod (args);}'"
@ J.AndrewLaughlin Это работает, потому что с eval объявление функции оценивается после инициализации переменной. См. здесь.
Я думаю, что пример MyControl :: ReceiveMessage не работает, потому что элемент управления ActiveX отображается с другим именем или в другой области.
В примере GetControl :: ReceiveMessage я считаю, что определение функции анализируется до того, как устанавливается ссылка GetControl, поэтому оно не относится к допустимому объекту и не может привязать функцию к объекту.
Я бы атаковал эту проблему, используя отладчик сценария MS и пытаясь определить, существует ли ссылка по умолчанию для элемента управления с другим именем или в другой области (возможно, в качестве дочернего элемента формы). Если вы можете определить правильную ссылку для элемента управления, вы сможете правильно привязать функцию с помощью метода Automagic ::, указанного в статье MSDN.
Еще одна мысль, ссылка может быть основана на имени объекта, а не на идентификаторе, поэтому попробуйте установить оба :)
Если на вашей странице есть элемент ActiveX с идентификатором MyControl, то синтаксис вашего обработчика javascript следующий:
function MyControl::ReceiveMessage(msg)
{
alert(msg);
}
Я не думаю, что это работает, если тег <object> находится внутри формы.
@FrankSchwieterman Этот обработчик ответит, только если MyControl объявлен в глобальной области видимости. Может быть, только объекты вне форм получают свой id в глобальной области видимости?
Хорошо, но если вы используете C# (.NET 2.0) с унаследованным UserControl (ActiveX) ... Единственный способ заставить его работать - "расширить" функциональность обработчика событий: http://www.codeproject.com/KB/dotnet/extend_events.aspx?display=Print
Приведенная выше ссылка на проект от нашего друга г-на Вернера Виллемсенса спасла мой проект. Если вы этого не сделаете, javascript не сможет привязаться к обработчику событий.
Он использовал «расширение» сложным образом из-за выбранного им примера, но если вы сделаете его простым, прикрепив дескриптор непосредственно к самому событию, это тоже сработает. C# ActiveX должен поддерживать "ScriptCallbackObject" для привязки события к функции javascript, как показано ниже:
var clock = new ActiveXObject("Clocks.clock");
var extendedClockEvents = clock.ExtendedClockEvents();
// Here you assign (subscribe to) your callback method!
extendedClockEvents.ScriptCallbackObject = clock_Callback;
...
function clock_Callback(time)
{
document.getElementById("text_tag").innerHTML = time;
}
Конечно, вам нужно реализовать IObjectSafety и другие средства безопасности, чтобы они работали лучше.
Я обнаружил, что этот код работает в теге формы. В этом примере обратный вызов - это параметр функции, переданный с помощью javascript элементу ActiveX, а callbackparam - это параметр события обратного вызова, сгенерированного в элементе управления ActiveX. Таким образом, я использую один и тот же обработчик событий для любых типов событий, а не пытаюсь объявить кучу отдельных обработчиков событий.
<object id = "ActivexObject" name = "ActivexObject" classid = "clsid:15C5A3F3-F8F7-4d5e-B87E-5084CC98A25A"></object>
<script>function document.ActivexObject::OnCallback(callback, callbackparam){callback(callbackparam);}</script>
Раньше я использовал ActiveX в своих приложениях. Я помещаю теги объекта в форму ASP.NET, и у меня работает следующий код JavaScript.
function onEventHandler(arg1, arg2){
// do something
}
window.onload = function(){
var yourActiveXObject = document.getElementById('YourObjectTagID');
if (typeof(yourActiveXObject) === 'undefined' || yourActiveXObject === null){
alert('Unable to load ActiveX');
return;
}
// attach events
var status = yourActiveXObject.attachEvent('EventName', onEventHandler);
}
Вот ссылка MSDN msdn.microsoft.com/en-us/library/ms536343(VS.85).aspx
Прошло некоторое время с тех пор, как я это тестировал, но я считаю, что .attachEvent() работает только в том случае, если элемент управления был создан с использованием статического HTML или, возможно, document.write().
К вашему сведению: attachEvent специфично для IE и не будет работать для Chrome, имя связанного метода для WebKit - addEventListener. И чтобы немного уточнить сообщение camilin87, оба метода работают только для стандартного типа события, то есть onclick, ontouch и т. д. Не работают для настраиваемого имени события ActiveX.
@Taudris attachEvent() работал у меня, когда управление создавалось динамически. У меня есть тег <object>, созданный динамически, а затем я использовал attachEvent() для подключения к событиям ActiveX объекта. Обратите внимание: для режима IE11 attachEvent() недоступен, поэтому, похоже, предоставленный вами динамический метод является единственным вариантом для IE11. Я создал функцию для своего приложения, чтобы использовать attachEvent(), если он доступен, но если нет, используйте метод eval().
@ewh Я отсылаю вас к моим вопрос и отвечать, а также к библиотека, который я написал для регистрации обработчиков с любыми событиями объекта ActiveX.
В моем случае мне нужен был способ динамически создавать элементы управления ActiveX и прослушивать их события. Мне удалось заставить работать что-то вроде этого:
//create the ActiveX
var ax = $("<object></object>", {
classid: "clsid:" + clsid,
codebase: install ? cabfile : undefined,
width: 0,
height: 0,
id: '__ax_'+idIncrement++
})
.appendTo('#someHost');
А затем зарегистрировать обработчик события:
//this function registers an event listener for an ActiveX object (obviously for IE only)
//the this argument for the handler is the ActiveX object.
function registerAXEvent(control, name, handler) {
control = jQuery(control);
//can't use closures through the string due to the parameter renaming done by the JavaScript compressor
//can't use jQuery.data() on ActiveX objects because it uses expando properties
var id = control[0].id;
var axe = registerAXEvent.axevents = registerAXEvent.axevents || {};
axe[id] = axe[id] || {};
axe[id][name] = handler;
var script =
"(function(){"+
"var f=registerAXEvent.axevents['" + id + "']['" + name + "'],e=jQuery('#" + id + "');"+
"function document." + id + "::" + name + "(){"+
"f.apply(e,arguments);"+
"}"+
"})();";
eval(script);
}
Этот код позволяет использовать замыкания и сводит к минимуму область действия eval ().
Элемент <object> элемента ActiveX уже должен быть добавлен в документ; в противном случае IE не найдет элемент, и вы просто получите ошибки сценария.
+1. Хотя в вашем ответе используются jquery-isms, это полезный ответ при работе с динамической страницей. У меня был успех, просто используя метод attachEvent() для объекта, чтобы прикрепить функцию прослушивателя к событию ActiveX. К сожалению, в режиме IE11 attachEvent() больше не поддерживается, поэтому вам придется использовать что-то вроде метода eval(). Стандартный метод addEventListener() не поддерживает типы событий на основе ActiveX.
Чтобы прояснить один момент - getElementById работает нормально. У нас есть ссылка на элемент управления, Javascript просто не любит, когда мы используем синтаксис :: с этой ссылкой.