<SCRIPT LANGUAGE="JScript">... var oOption = document.createElement("OPTION"); oOption.text="Ferrari"; oOption.value="4"; oSelect.add(oOption); </SCRIPT>
但事实上类似的代码在C++中却不能工作。
2、发现
写文章时测试过脚本调用之后就放在一边了,而真正写程序用到时才发现上面的问题。MFC中有个很好用的类CDHtmlDialog,提供了类似于CDialog的行为用以实现以HTML为表现形式的对话框,像Visual Studio 7/8的的Wizard,添加类等对话框就使用了类似的技术。CDHtmlDialog的核心在于MFC中被用得出神入化的宏,再加上一系列DDX函数来实现HTML content和应用程序的数据的数据交换。比如下面的函数可以实现读取某个能够匹配szId的IHTMLSelectElement中被选中的值,或选中value所指定的那个IHTMLOptionElement。
void CDHtmlDialog::DDX_DHtml_SelectString(LPCTSTR szId, CString& value, BOOL bSave) ...{ CComPtr<IHTMLDocument2> sphtmlDoc; GetDHtmlDocument(&sphtmlDoc); if (sphtmlDoc == NULL) return; COleVariant varEmpty, varIndex; CComPtr<IHTMLSelectElement> spSelect; CComPtr<IDispatch> spdispOption; CComPtr<IHTMLOptionElement> spOption; CComBSTR bstrText; HRESULT hr = S_OK; long lIndex=-1; hr = GetElementInterface(szId, __uuidof(IHTMLSelectElement), (void**) &spSelect); if (spSelect == NULL) return; if (bSave) ...{ // get the selected item value.Empty(); spSelect->get_selectedIndex(&lIndex); if (lIndex >=0) ...{ varIndex = lIndex; spSelect->item(varIndex, varEmpty, &spdispOption); if (spdispOption) ...{ spdispOption->QueryInterface(__uuidof(IHTMLOptionElement), (void**) &spOption); if (spOption) ...{ spOption->get_text(&bstrText); if (bstrText) value = bstrText; } } } } else ...{ bstrText.Attach(value.AllocSysString()); lIndex = Select_FindString(spSelect, bstrText, FALSE); spSelect->put_selectedIndex(lIndex); } }
According to MSDN, “Before you can add an element to a collection, you must create it first by using the IHTMLDocument2::createElement method”. Actually, it does not work. See the detail in codeproject
codeproject 的这篇文章,指的是《How to operate controls in an HTML file, using C++》,其中说到应该使用IHTMLOptionElementFactory来创建IHTMLOptionElement。而IHTMLOptionElementFactory需要从IHTMLWindow2(该文说应该从Document的Script来获得IHTMLWindow2,其实从Document的parentWindow更为直接)的Option来得到,再看MSDN,我们发现同样还有一个IHTMLImageElementFactory接口(从IHTMLWindow2的Image得到)用于创建IHTMLImgElement。看来要么这两个接口有特殊的地方,要么就是历史遗留问题了。因为令人感到奇怪的是MSDN中关于IHTMLDocument2::createElement方法的说明对这两个接口只字不提:
In Microsoft Internet Explorer 4.0, the only new elements you can create are img, area, and option. As of Internet Explorer 5, you can create all elements programmatically, except for frame and iframe. In addition, the properties of these created elements are read/write and can be accessed programmatically. Before you use new objects, you must explicitly add them to their respective collections or to the document. To insert new elements into the current document, use the IHTMLDOMNode::insertBefore or IHTMLDOMNode::appendChild methods. Attributes can be included with the eTag as long as the entire string is valid HTML.