在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 Functional contructor"); } 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); } else m_strURL = lpszURL; CommonConstruct(); } int CMshtmlDialog::DoModal() { file://First get the proc ShowHTMLDialog SHOWHTMLDIALOGFN *pfnShowHTMLDialog; pfnShowHTMLDialog = (SHOWHTMLDIALOGFN*)GetProcAddress(m_hInstMSHTML, TEXT("ShowHTMLDialog")); if (!pfnShowHTMLDialog) return -1; file://Now create a URL Moniker IMoniker* 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 Dialog HRESULT hr = (*pfnShowHTMLDialog)(m_hWndParent, pmk, m_varArgs, pchOptions, m_varReturn); if (FAILED(hr))0 return -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 document Productid.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 dialog CString 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(LPCTSTR lpszOptions),字符串lpszOptions的格式是“dialogWidth: xxx; dialogHeight: xxx”,关于更详细使用方法请参看Internet Client SDK函数ShowModalDialog的描 述。 作者地址: 北京东城区富华大厦A座12层A室富融科技有限公司(100027) 屈晓晖 Email:[email protected]

|