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