Запуск события onChange из C++ IHTMLInputElement
У меня есть html-страница, загруженная в CDialog в приложении MFC, использующем движок IE8, и экземпляр CDHtmlDialog. Html-страница содержит элементы <input> и включает в себя jQuery. В упомянутом jQuery у меня есть такой код:
$(function()
{$
$('#Left').change(function()
{
$('[id$=left]').prop('disabled', ! $(this).is(':checked') );
}).change();
});
, который по существу просто сохраняет некоторые входы и выбирает (выбранный по соглашению id) отключенным или включенным, основываясь на флажке с идентификатором #Left.
Проблема заключается в следующем: Когда я изменяю флажок из кода C++ следующим образом:
// Get pElements checkbox through doc->getElementsByTagName("input")
CComQIPtr<IHTMLInputElement> spInputElement(pElement);
spInputElement->put_checked(true);
Затем событие change не запускает (возможно, чтобы избежать бесконечной рекурсии), и другие входные данные никогда не обновляются. Есть ли способ, которым я могу запустить событие изменения явно из моего C++? Я бы предпочел не требовать, чтобы все флажки имели определенный html-код (например, явный onchange="..."), поскольку это было бы непрактично для технического обслуживания.
4 ответов:
В IE8 событие создается с помощью IHTCDefaultDispatch::createEventObject и запускается с помощью IHTMLElement3::fireEvent.
Для IE9 событие создается с помощью IDocumentEvent:: createEvent и запускается с помощью IEventTarget:: dispatchEvent.
Так что, благодаря Амадею, я все понял. Это код, который работает, так что все остальные могут просто скопировать и вставить его, если им это нужно.
Обратите внимание, что это не вызовет никаких событий, описанных в JQuery, но он получит все те, которые объявлены непосредственно в html какvoid fireOnChangeEvent(IHTMLElement* pElement) { // Create a new event-object IHTMLEventObj* eventObject; IDispatch* dispatch; pElement->get_document(&dispatch); CComQIPtr<IHTMLDocument4, &__uuidof(IHTMLDocument4)> doc = dispatch; dispatch->Release(); VARIANT empty; VariantInit(&empty); doc->createEventObject(&empty, &eventObject); // fire event VARIANT eventref; VariantInit(&eventref); V_VT(&eventref) = VT_DISPATCH; V_DISPATCH(&eventref) = eventObject; VARIANT_BOOL cancellable; CComQIPtr<IHTMLElement3, &__uuidof(IHTMLElement3)> element3 = pElement; BSTR bstrChange = SysAllocString(L"onchange"); element3->fireEvent(bstrChange, &eventref, &cancellable); SysFreeString(bstrChange); }onchange="..."
Возможно, вы можете использовать метод onchange (см. http://msdn.microsoft.com/en-us/library/aa703817 (v=против 85).aspx )?
Обновление:
Нет этот метод, вероятно, не поможет : (он устанавливает свой собственный обработчик для события onchange.
Обновление 2:
Попробуйте дождаться полной загрузки документа, прежде чем запускать какие-либо события ( код можно найти по адресу http://www.codeproject.com/KB/shell/iehelper.aspx?msg=704899 )
Ну, есть более простой способ. Привязать к обработчику щелчка на стороне JS и в C++ сделать что-то вроде этого:
IHTMLElement *pElement; GetElement(L"whateverInputId", &pElement); CString value = _T("123"); COleVariant vValue(value); pElement->setAttribute(L"value", vValue); pElement->click();Я устанавливаю значение выше (у меня есть текстовый ввод), но для вашего флажка, если вы знаете, что он не установлен, вы, вероятно, могли бы просто сделать:
IHTMLElement *pElement; GetElement(L"whateverInputId", &pElement); pElement->click();Не проверял, но для checkbox это, вероятно, даже сработает
onchange.
Comments