?? html_dialog.htm
字號:
<p align=center>VC7 HTML Dialog開發實例講解
<p align=center>作者:聞怡洋 <a href="mailto:wyy_cq@copathway.com">wyy_cq@copathway.com</a>
<a href="http://www.vchelp.net/">http://www.vchelp.net/</a>
<p align=center>未得到作者同意,不允許任何形式的轉載
<p>開發環境:VS7,Windows XP,Windows 2K
<p>在VS7中添加了一種新的對話框類:CDHtmlDialog,顧名思義就是能夠顯示DHTML內容的對話框,但不同與以前的CHTMLView不同的是添加了對DHTML的支持,能夠響應各種DHTML的事件,而且能夠方便的得到網頁上的各種內容和輸入。在這以前要完成這些功能必須通過復雜的COM接口來完成,而現在MS MFC已經為我們做好了這一切。
<p>在下面我會按照下面的順序講解CDHtmlDialog的用法。但本文也只能對DHTML對話框的功能進行部分的講解,更多更全的說明需要大家自己摸索和查找資料。本文的目的是在于講解如何得到和設置網頁上的各種元素的值,如何處理事件。
<p>此外在閱讀本文前你必須對HTML和DHTML有所了解。
<ul>
<li><a href=#step1>CDHtmlDialog類的成員函數</a></li>
<li><a href="#step2">CDHtmlDialog事件處理映射宏</a></li>
<li><a href=#step3>CDHtmlDialog類的各種DDX幫助宏</a></li>
<li><a href=#step4>一個簡單的例子</a></li>
<!--<li><a href=step5>講解MS提供的Scheduler Sample(Demonstrates HTML-Based Dialog Boxes)</a></li>-->
</ul>
<p align="center"><a name=step1></a><strong>類成員函數介紹</strong>
<p align=left><strong>構造函數</strong></p>
<pre>
CDHtmlDialog( );
CDHtmlDialog(
LPCTSTR lpszTemplateName,
LPCTSTR szHtmlResID,
CWnd *pParentWnd = NULL
);
CDHtmlDialog(
UINT nIDTemplate,
UINT nHtmlResID = 0,
CWnd *pParentWnd = NULL
);
</pre>
<p>你可以看到和CDialog不同的就在于第二個參數,表示在對話框創建時是否自動加載HTML,這里必須說明的是HTML必須以資源的形式存放,這個參數指明的是資源的ID或名稱。
<p><img src=html_rs.gif>
<p>或者你可以利用
<pre>
BOOL LoadFromResource(
LPCTSTR lpszResource
);
BOOL LoadFromResource(
UINT nRes
);
</pre>
<p>將HTML內容在后期進行裝載。
<p align="left"><strong>頁面瀏覽</strong>
<p>此外一些函數如:OnNavigateComplete,OnBeforeNavigate,Navigate等用于頁面轉換的函數,在以前的CHtmlView中就有這里就不再作講解。
<p align=left><strong>得到當前URL</strong>
<pre>
void GetCurrentUrl(
CString& szUrl
);
</pre>
<p align=left><strong>得到網頁中的DHTML元素的指定接口</strong>
<pre>
HRESULT GetElementInterface(
LPCTSTR szElementId,
REFIID riid,
void** ppvObj
);
</pre>
<p>第一個參數指定,第二個參數指定接口ID,第三個參數返回接口指針。
<p align="left"><strong>得到網頁中的DHTML元素的IHTMLElement接口</strong>
<pre>
HRESULT GetElement(
LPCTSTR szElementId,
IHTMLElement **pphtmlElement
);
相當于調用 GetElementInterface(szElementId,IHTMLElement,pphtmlElement);
</pre>
<p>這個函數非常的重要,因為如果要得到DHTML的內容就必須通過頁面上的各個元素的屬性來得到,例如:對于Input type=text的屬性value就是輸入的值,對于p的屬性innerText就是段落中的內容。
<p>函數的第二個參數就是元素的名稱。
<p>函數的第二個參數,是一個指向指針的指針,通過它得到IHTMLElement的接口。函數返回值是HRESULT其值的定義符合COM中對返回值的定義。(如果你不了解,可以簡單的檢測返回值是否等于S_OK)
<p align="left"><strong>得到元素的innerText和innerHTML的屬性</strong>
<pre>
innerHTML屬性:
BSTR GetElementHtml(
LPCTSTR szElementId
);
innerText屬性:
BSTR GetElementText(
LPCTSTR szElementId
);
相當于調用IHTMLElement接口的gett_innerHTML和get_innerText方法</pre>
<p>與之對應的是設置元素的innerText和InnerHTML屬性:
<pre>
innerHTML屬性:
void SetElementHtml(
LPCTSTR szElementId,
BSTR bstrText
);
innerText屬性:
void SetElementText(
LPCTSTR szElementId,
BSTR bstrText
);
相當于調用IHTMLElement接口的put_innerHTML和put_innerText方法</pre>
<p align="left"><strong>示范代碼</strong>
<p>假設頁面上的代碼為:<p id=p2>test</p>,執行下面代碼可以顯示原來的內容和將新內容設置為:abcdefg
<pre>
CComPtr<IHTMLElement> spP1;
HRESULT hr = S_OK;
// Use the template overload
hr = GetElementInterface("p2", &spP1);
// 或者 hr = GetElement("p2", &spP1);
// 或者 hr = GetElementInterface("p2", IID_IHTMLElement, reinterpret_cast<void**>(&spP1));
if(S_OK == hr)
{
BSTR bStr;
spP1->get_innerHTML(&bStr);
CString szTemp;
szTemp = bStr;
AfxMessageBox(szTemp);
CString strTable="abcdefg";
BSTR bstrTable = strTable.AllocSysString();
spP1->put_innerHTML(bstrTable);
}
或者利用SetElementHtml和SetElementText來進行設置:
BSTR bStr;<br> bStr = GetElementHtml("p2");<br> CString szTemp;<br> szTemp = bStr;<br> AfxMessageBox(szTemp);<br> CString strTable="ABCDEFG";<br> BSTR bstrTable = strTable.AllocSysString();<br> //spP1->put_innerHTML(bstrTable);<br> SetElementHtml("p2",bstrTable);
</pre>
<p align="center"><a name=step2 id="step2"></a> <strong>事件處理映射宏</strong>
<p><strong>基本格式</strong></p>
<pre>
BEGIN_DHTML_EVENT_MAP(className )
DHTML_EVENT_ONCLICK(elemName, memberFxn ) //處理onclick事件
DHTML_EVENT_ONFOCUS(elemName, memberFxn ) //處理onfocus事件
DHTML_EVENT_ONKEYDOWN(elemName, memberFxn ) //處理onkeydown事件
DHTML_EVENT_ONMOUSEMOVE(elemName, memberFxn ) //處理mousemove事件
DHTML_EVENT_ONMOUSEOUT(elemName, memberFxn ) //處理mousemoveout事件
等等………
END_DHTML_EVENT_MAP()
</pre>
<p>更詳細的說明可以查閱MSDN中DHTML Event Map Macros部分。MSDN中對可以處理的事件進行了詳細的說明。DHTML中的事件與Windows中消息不是同一個概念,雖然映射宏的形式很相同。
<p><strong>添加映射處理代碼</strong>
<p>我在VC7中沒有發現自動添加各種事件映射的方法,只能通過手工添加代碼的方式。
<pre>
定義事件處理函數:
函數原型為:HRESULT urClass::OnXXXXX(IHTMLElement* /*pElement*/)
添加消息映射:
BEGIN_DHTML_EVENT_MAP(urClass)
DHTML_EVENT_ONCLICK(_T("id name"), OnXXXXX)
END_DHTML_EVENT_MAP()
下面是一段示范代碼:
// mydlg.h
class CmydhtmlDlg : public CDHtmlDialog
{
// 構造
public:
CmydhtmlDlg(CWnd* pParent = NULL); // 標準構造函數
// 對話框數據
enum { IDD = IDD_MYDHTML_DIALOG, IDH = IDR_HTML_MYDHTML_DIALOG };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
HRESULT OnButtonOK(IHTMLElement *pElement);
HRESULT OnButtonCancel(IHTMLElement *pElement);
HRESULT OnButtonTest1(IHTMLElement *pElement);
HRESULT OnButtonTest2(IHTMLElement *pElement);
HRESULT OnButtonTest3(IHTMLElement *pElement);
HRESULT OnSelectTest1(IHTMLElement *pElement);
HRESULT OnDivMouseMove1(IHTMLElement *pElement);
HRESULT OnDivMouseOut1(IHTMLElement *pElement);
//mydlg.cpp
BEGIN_DHTML_EVENT_MAP(CmydhtmlDlg)
DHTML_EVENT_ONCLICK(_T("ButtonOK"), OnButtonOK)
DHTML_EVENT_ONCLICK(_T("ButtonCancel"), OnButtonCancel)
DHTML_EVENT_ONCLICK(_T("Test1"), OnButtonTest1)
DHTML_EVENT_ONCLICK(_T("Test2"), OnButtonTest2)
DHTML_EVENT_ONCLICK(_T("Test3"), OnButtonTest3)
DHTML_EVENT_ONCHANGE(_T("s1"), OnSelectTest1)
DHTML_EVENT_ONMOUSEMOVE(_T("d1"), OnDivMouseMove1 )
DHTML_EVENT_ONMOUSEOUT(_T("d1"), OnDivMouseOut1 )
END_DHTML_EVENT_MAP()
HRESULT CmydhtmlDlg::OnButtonOK(IHTMLElement* /*pElement*/)
{
OnOK();
return S_OK;
}
HRESULT CmydhtmlDlg::OnButtonCancel(IHTMLElement* /*pElement*/)
{
OnCancel();
return S_OK;
}
HRESULT CmydhtmlDlg::OnButtonTest1(IHTMLElement* /*pElement*/)
{
AfxMessageBox("test1 button clicked");
return S_OK;
}
HRESULT CmydhtmlDlg::OnSelectTest1(IHTMLElement* /*pElement*/)
{
TRACE("select1 changed\n");
return S_OK;
}
HRESULT CmydhtmlDlg::OnDivMouseMove1(IHTMLElement* /*pElement*/)
{
TRACE("div1 mouse move\n");
return S_OK;
}
HRESULT CmydhtmlDlg::OnDivMouseOut1(IHTMLElement* /*pElement*/)
{
TRACE("div1 mouse out\n");
return S_OK;
}
</pre>
<p align="center"><strong><a name=step3 id="step3"></a>各種DDX幫助宏 </strong>
<p><strong>DDX宏介紹 </strong>
<p>如同CDialog類一樣,CHtmlDialog也提供各種DDX幫助宏來與HTML頁面上的控件交換數據。
<p>遺憾的是VS7中無法為CDHTMLDialog 的子類自動添加DDX變量,必須通過手工添加。
<p><strong>設置innerText和innerHTML屬性</strong>
<pre>DDX_DHtml_ElementInnerText(
CDataExchange* dx,
LPCTSTR name,
CString& var
)
和
DDX_DHtml_ElementInnerHtml(
CDataExchange* dx,
LPCTSTR name,
CString& var
)
相當與前面提到的設置和獲取innerText,innerHTML屬性。
</pre>
<p><strong>獲取和設置控件中的值</strong>
<p>在DHTML中利用“對象名程.value”可以得到控件中輸入的值,利用DDX也同樣可以得到。
<pre>
DDX_DHtml_ElementValue(
CDataExchange* dx,
LPCTSTR name,
var
)
用于在控件和對象之間交換數據。
</pre>
<p>使用方法
<p>假設HTML文件中代碼如下
<pre><p id="p4"><b>p4 for ddx</b></p>
<input type="text" ID="input1" size="20" value="input1 for ddx" NAME="input1">
<input type="text" ID="input2" size="20" value="101" NAME="input2">
在H文件中添加變量定義:
public: //DDX
CString m_szP4,m_szInput1;
int m_iInput2;
在類的構造函數中賦初值:
CmydhtmlDlg::CmydhtmlDlg(CWnd* pParent /*=NULL*/)
: CDHtmlDialog(CmydhtmlDlg::IDD, CmydhtmlDlg::IDH, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
m_szP4 = "test for p4";
m_szInput1= "test for input1";
m_iInput2 = 101;
}
在CPP文件中的void CmydhtmlDlg::DoDataExchange(CDataExchange* pDX)函數中添加代碼:
void CmydhtmlDlg::DoDataExchange(CDataExchange* pDX)
{
CDHtmlDialog::DoDataExchange(pDX);
//// for html ddx
DDX_DHtml_ElementInnerHtml(pDX,"p4",m_szP4); //對應 p4
DDX_DHtml_ElementValue(pDX,"input1",m_szInput1); //對應 input1
DDX_DHtml_ElementValue(pDX,"input2",m_iInput2); //對應 input2
}
使用是與CDialog一樣利用UpdateData。
HRESULT CmydhtmlDlg::OnButtonTest4(IHTMLElement* /*pElement*/)
{
UpdateData();
TRACE("p4=%s\n",m_szP4);
CString szTemp=m_szP4;
m_szP4 =m_szInput1;
m_szInput1=szTemp; //對換p4和input1中內容
m_iInput2 ++; //將input2中數字加一
UpdateData(FALSE);
return S_OK;
}
</pre>
<div align="center">
<p><a name=step4 id="step4"></a><strong>一個簡單的例子</strong> </p>
<p align="left">最后介紹一下如何利用VC7創建一個利用CDHtmlDialog的工程。</p>
<p align="left">首先創建工程,進行如下設置:<br>
<img src=create_prj.gif><br>
在資源管理中修改HTML文件:<br>
<img src=edit_html.gif><br>
最后添加自己的代碼。我提供的例子中所使用的函數在上面都已經提到。大家可以下載這份<a href=html_dialog.zip>例子</a>去進行一定的參考</p>
<p align="right"> </p>
<p align="right"> </p>
<p align="right">聞怡洋 2002-09-10</p>
<p align="right">wyy_cq@copathway.com </p>
<p align="right"><a href="http://www.vchelp.net/">http://www.vchelp.net/</a></p>
<p align="left"></p>
</div>
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -