在Web应用开发中经常会用到带有图象、声音和动画的对话框,然而要在VC++中实现这样一个对话框需要做大量的工作。幸运的是,随着Internet Explorer 4.0的出现以及它所使用的新的技术,所有这些工作无须大量的代码就可实现。一种方法是使用web 浏览器控件,但它并不是最好的方法,尤其是对处理模式对话框时;另外一种方法是使用IE4所引入的HTML模式对话框,它驻留在系统的mshtml.dll这个对HTML进行解释的引擎中。虽然有些功能诸如:单击一个链接,对历史记录的管理以及在同一窗口中装入一个链接在这个模式对话框中不能实现,但对于我们几乎所有的时候仅使用一个模式对话框来说已经足够了。如何使用HTML中的模式对话框mshtml.dll中的函数SHOWHTMLDIALOGFN是用来显示一个HTML对话框的,但它需要用于字符串和其它事务转换的COM要素,为了简化所有这些工作,笔者利用一个类来对COM要素进行封装如下:class CMshtmlDialog{public:void SetDlgOptions(LPCTSTR lpszOptions);void SetSize(int x, int y);LPCVARIANT GetReturnVariant();CString GetReturnString();void SetParam(LPCTSTR lpszArgs);void SetParam(VARIANT* pvarArgs);virtual int DoModal();CMshtmlDialog(LPCTSTR lpszURL, BOOL bRes = FALSE, CWnd* pParent = NULL);CMshtmlDialog (UINT nResID, CWnd* pParent = NULL);CMshtmlDialog ( );virtual ~ CMshtmlDialog( ); private:inline void ResourceToURL(LPCTSTR lpszURL);void CommonConstruct();protected:HWND m_hWndParent;CString m_strOptions;COleVariant m_varArgs, m_varReturn;CString m_strURL;HINSTANCE m_hInstMSHTML;}; // CMshtmlDialog类的实现文件. CMshtmlDialog :: CMshtmlDialog (){TRACE0("Warning: Initialization may not be done: Non Functionalcontructor");}CMshtmlDialog::~ CMshtmlDialog(){file://释放Mshtml.dll::FreeLibrary(m_hInstMSHTML);}CMshtmlDialog:: CMshtmlDialog(UINT nResID, CWnd* pParent/*= NULL*/){m_hWndParent = pParent ? pParent->GetSafeHwnd() : NULL;CString strTemp;strTemp.Format("%d", nResID);ResourceToURL(strTemp);CommonConstruct();} CMshtmlDialog::CMshtmlDialog(LPCTSTR lpszURL, BOOL bRes, CWnd* pParent/*=NULL*/){m_hWndParent = pParent ? pParent->GetSafeHwnd() : NULL;if (bRes){ResourceToURL(lpszURL);}elsem_strURL = lpszURL;CommonConstruct();}int CMshtmlDialog::DoModal(){file://First get the proc ShowHTMLDialogSHOWHTMLDIALOGFN *pfnShowHTMLDialog;pfnShowHTMLDialog = (SHOWHTMLDIALOGFN*)GetProcAddress(m_hInstMSHTML,TEXT("ShowHTMLDialog"));if (!pfnShowHTMLDialog)return -1;file://Now create a URL MonikerIMoniker* pmk = NULL;BSTR bstrURL = m_strURL.AllocSysString();CreateURLMoniker(NULL, bstrURL, &pmk);if (!pmk)return -1;TCHAR* pchOptions = m_strOptions.IsEmpty() ? NULL :m_strOptions.GetBuffer(0);file://Now show the HTML DialogHRESULT hr = (*pfnShowHTMLDialog)(m_hWndParent, pmk, m_varArgs, pchOptions,m_varReturn);if (FAILED(hr))0return -1;return 0;}void CMshtmlDialog::CommonConstruct(){m_hInstMSHTML = ::LoadLibrary(TEXT("MSHTML.DLL"));}inline void CMshtmlDialog::ResourceToURL(LPCTSTR lpszURL){HINSTANCE hInstance = AfxGetResourceHandle();ASSERT(hInstance != NULL);LPTSTR lpszModule = new TCHAR[_MAX_PATH];if (GetModuleFileName(hInstance, lpszModule, _MAX_PATH)){m_strURL.Format(_T("res://%s/%s"), lpszModule, lpszURL);}delete []lpszModule;}void CMshtmlDialog::SetParam(VARIANT *pvarArgs){m_varArgs = pvarArgs;}void CMshtmlDialog::SetParam(LPCTSTR lpszArgs){m_varArgs = lpszArgs;}CString CMshtmlDialog::GetReturnString(){ASSERT(m_varReturn.vt == VT_BSTR);CString str = m_varReturn.bstrVal;return str;}LPCVARIANT CMshtmlDialog::GetReturnVariant(){return (LPCVARIANT)m_varReturn;}void CMshtmlDialog::SetSize(int x, int y){m_strOptions.Format("dialogWidth: %d; dialogHeight: %d", x, y);} void CMshtmlDialog::SetDlgOptions(LPCTSTR lpszOptions){m_strOptions = lpszOptions;} 使用CMshtmlDialog的一个简单例子 比如我们要在一个关于对话框里使用这个类,我们所要做工作是写一个HTML文件并把它以IDR_ABOUT_HTM包含进资源文件里。这里列出OnAppAbout的函数如下:void CHDDemoApp::OnAppAbout(){CMshtmlDialog dlg(IDR_ABOUT_HTM, AfxGetMainWnd());dlg.DoModal();}还可以利用构造函数传递字符串资源或要显示的URLs,通过使用HTML中的图形和声音资源就可以在关于对话框中显示一个复杂的效果。 向对话框中传递参数 在有些时候我们不仅仅要显示一个HTML资源,还要从应用程序中向关于对话框传递一些参数进去(比如:产品序列号,许可号等),参数类型可以是string类型,也可以是variant类型,比如我们要在对话框显示产品序列号、用户名称、公司名称和产品的版本号,可以在程序添加如下代码:void CHDDemoApp::OnDemoParam1(){CMshtmlDialog dlg(IDR_ABOUT1_HTM, AfxGetMainWnd());CString str = m_strProductID file://产品序列号+ ";"+ m_strUserName file://用户许可号+ ";" + m_strCompanyName file://公司名称+ ";" + m_strAppVersion;//版本号dlg.SetParam(str);dlg.DoModal( );}在实际显示的HTML主页中我们还必须包含一些javascript或vbscript函数。在HTML中传给CMshtmlDialog的任何参数都可以作为window对象的dialogArguments属性,以javascript为例:function getParameters( ){var args = new Array();args = window.dialogArguments.split(";"); file://Now display in the documentProductid.innerText = args[0];UserName.innerText = args[1];CompanyName.innerText = args[2];AppVersion.innerText = args[3]; } 从对话框中获取返回值 我们已经发现通过结合使用Javascript和C++可以获得更多的信息,那么如何从对话框中传递参数作为我们获得的返回值的结果并传回C++程序呢?作为例子我们还结合Javascript和C++,在利用onunload的处理句柄关闭HTML窗口程序段中我们给出如下的代码:function window_onclose( ){window.returnValue = UserName.value + ";" + CompanyName.value;}只需通过设置返回值的属性就可将该值传回C++程序中。返回值可以是任意的variant变量,然后在C++代码中通过调用函数GetReturnString 或GetReturnVariant来处理这个返回值,如:dlg.DoModal( ); file://Display the dialogCString str = dlg.GetReturnString( );file://Now handle the return value in whatever way设置对话框的尺寸在以上的例子中,对话框尺寸的设置是通过在HTML中使用下列标签来设置的:<HTML style="width: 25em; height: 30em>在ChtmlDialog中提供了一个设置对话框尺寸的简单的方法,这种方法无须在HTML的标签中指定尺寸的大小,而只需调用函数SetDialogSize(int nWidth, int nHeight)即可;还有一个函数也可以用来设置尺寸的大小,也就是SetOptions(LPCTSTRlpszOptions),字符串lpszOptions的格式是“dialogWidth: xxx; dialogHeight: xxx”,关于更详细使用方法请参看Internet Client SDK函数ShowModalDialog的描述。作者地址:北京东城区富华大厦A座12层A室富融科技有限公司(100027)屈晓晖Email:quxiaohui@sohu.com