Как обработать событие ActiveX в Javascript
-
02-07-2019 - |
Вопрос
Это своего рода продолжение ответа здесь.
У меня есть пользовательский элемент управления ActiveX, который вызывает событие ("ReceiveMessage" с параметром "msg"), которое должно быть обработано Javascript в веб-браузере.Исторически мы могли использовать следующий синтаксис только для IE для выполнения этого в разных проектах:
function MyControl::ReceiveMessage(msg)
{
alert(msg);
}
Однако, находясь внутри макета, в котором скрыт элемент управления, Javascript не может найти элемент управления.В частности, если мы поместим это на обычную HTML-страницу, это будет работать нормально, но если мы поместим это на ASPX-страницу, обернутую <Form>
тег, мы получаем ошибку "MyControl не определен".Мы попробовали следующие варианты:
var GetControl = document.getElementById("MyControl");
function GetControl::ReceiveMessage(msg)
{
alert(msg);
}
...но это приводит к ошибке Javascript "GetControl не определен".
Как правильно обработать событие, отправляемое из элемента управления ActiveX?Прямо сейчас мы заинтересованы только в том, чтобы это заработало в IE.Это должен быть пользовательский элемент управления ActiveX для того, что мы делаем.
Спасибо.
Решение
Я смог заставить это работать, используя следующий формат блока скрипта, но мне все еще интересно, является ли это лучшим способом:
<script for="MyControl" event="ReceiveMessage(msg)">
alert(msg);
</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);
}
Хорошо, но если вы используете C # (.NET 2.0) с унаследованным UserControl (ActiveX)...Единственный способ заставить это работать - это "Расширить" функциональность обработчика события:http://www.codeproject.com/KB/dotnet/extend_events.aspx?display=Print
Приведенная выше ссылка на проект от нашего друга Mr.Вернер Виллемсенс спас мой проект.Если вы этого не сделаете, 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 и другие элементы безопасности, чтобы заставить его работать лучше.
Если у вас на странице есть элемент ActiveX с идентификатором 'MyControl', то синтаксис вашего обработчика javascript следующий:
function MyControl::ReceiveMessage(msg)
{
alert(msg);
}
Я обнаружил, что этот код работает в теге формы.В этом примере callback - это параметр функции, передаваемый 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 и прослушивания их событий.Мне удалось заставить что-то подобное сработать:
//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().
Элемент управления ActiveX <object>
элемент уже должен быть добавлен в документ;в противном случае IE не найдет элемент, и вы просто получите ошибки скрипта.
Я думаю, что пример MyControl::ReceiveMessage не работает, потому что элемент управления ActiveX предоставляется с другим именем или в другой области видимости.
В примере GetControl::ReceiveMessage я полагаю, что определение функции анализируется до установки ссылки GetControl, таким образом, оно не ссылается на допустимый объект и не может привязать функцию к объекту.
Я бы решил эту проблему, используя отладчик MS script и пытаясь определить, существует ли ссылка по умолчанию для элемента управления с другим именем или в другой области видимости (возможно, как дочерний элемент формы).Если вы сможете определить правильную ссылку для элемента управления, вы сможете правильно привязать функцию к Automagic ::метод, указанный в статье MSDN.
Еще одна мысль, ссылка может быть основана на имени объекта, а не на идентификаторе, поэтому попробуйте установить оба :)