CDHtmlDialog可以方便的將網(wǎng)頁嵌入對話框,使得在程序設(shè)計中人機界面(DHTML網(wǎng)頁)與控制邏輯(CDialog)可以很好的分離,下面是一些實用技術(shù)與技巧。
1.將數(shù)據(jù)驗證任務(wù)完全交給JavaScript,Dialog只做有意義的事。
<input type="button" id="button1" onclick="if(validate()); window.event.cancelBubble=true;" /> 這樣,事件由IE處理之后,就不會將該事件傳給其他事件句柄處理了,因為IE先于CDHtmlDialog處理該事件。
2.從CDHtmlDialog調(diào)用網(wǎng)頁中JavaScript函數(shù)的方法。
其中pDoc指針參數(shù)可通過CDHtmlDialog::GetDHtmlDocument(&pDoc)函數(shù)獲得;
strFunctionName指示函數(shù)名;
dispParams為傳給函數(shù)的參數(shù)列表,其使用方法請查閱MSDN相關(guān)文檔;
varResult為函數(shù)返回值;
exceptInfo為JavaScript函數(shù)執(zhí)行時拋出的異常;
nArgErr返回第一個出錯的參數(shù)的下標(biāo),由于參數(shù)列表中參數(shù)的邏輯順序為JavaScript函數(shù)定義的參數(shù)的順序的逆序,所以應(yīng)特別注意該返回值所指示的具體位置。
HRESULT CallJSFunction(IHTMLDocument2* pDoc2,
CString strFunctionName,
DISPPARAMS dispParams,
VARIANT* varResult,
EXCEPINFO* exceptInfo,
UINT* nArgErr )
{
IDispatch *pDispScript = NULL;
HRESULT hResult;
hResult = pDoc2->get_Script(&pDispScript);
if(FAILED(hResult))
{
return S_FALSE;
}
DISPID dispid;
CComBSTR objbstrValue = strFunctionName;
BSTR bstrValue = objbstrValue.Copy();
OLECHAR *pszFunct = bstrValue ;
hResult = pDispScript->GetIDsOfNames(IID_NULL,
&pszFunct,
1,
LOCALE_SYSTEM_DEFAULT,
&dispid);
if (S_OK != hResult)
{
pDispScript->Release();
return hResult;
}
varResult->vt = VT_VARIANT;
hResult = pDispScript->Invoke(dispid,
IID_NULL, LOCALE_USER_DEFAULT,
DISPATCH_METHOD,
&dispParams,
varResult,
exceptInfo,
nArgErr);
pDispScript->Release();
return hResult;
}
3.CDHtmlDialog中JavaScript通過external調(diào)用C++方法。
<1>讓CDHtmlDialog對象自身支持自動化
EnableAutomation(); //只要是從CCmdTarget派生下來的類都可以支持
//可以放在CMyDHTMLDialog::CMyDHTMLDialog()中調(diào)用
<2>將自身暴露給Script引擎:
SetExternalDispatch(GetIDispatch(TRUE)); //將瀏覽器控件的擴展接口設(shè)置為對話框自身的IDispatch
//放在CMyDHTMLDialog::OnInitDialog中調(diào)用
<3>聲明DISPATCH_MAP(MyDHTMLDialog.h)
<4>定義DISPATCH映射(MyDHTMLDialog.cpp)
BEGIN_DISPATCH_MAP(CMyDHtmlDialog, CDHtmlDialog)
DISP_FUNCTION(CMyDHTMLDialog, "Func1", Func1, VT_EMPTY, VTS_NONE)
// example:
// DISP_FUNCTION(CMyDHTMLDialog,"Func2",TestFunc,VT_BOOL,VTS_BSTR VTS_I4 VTS_I4)
// ^return, ^parameters type list
//每個方法都需要在這里添加映射
END_DISPATCH_MAP()
<5>函數(shù)實現(xiàn)
void CMyDHTMLDialog::Func1()
{
AfxMessageBox(_T("Func1 called!"));
<6>調(diào)用示例
<INPUT id="Button1" type="button" value="Button1" name="Button1" onclick="external.Func1();">