在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)
屈晓晖