⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 html_dialog.htm

📁 浅谈HTML对话框的实现的Visual C++源代码
💻 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>假设页面上的代码为:&lt;p id=p2&gt;test&lt;/p&gt;,执行下面代码可以显示原来的内容和将新内容设置为:abcdefg 
<pre>
	CComPtr&lt;IHTMLElement&gt; spP1;
	HRESULT hr = S_OK;

	// Use the template overload
	hr = GetElementInterface("p2", &spP1);
// 或者 hr = GetElement(&quot;p2&quot;, &amp;spP1);
// 或者 hr = GetElementInterface(&quot;p2&quot;, IID_IHTMLElement, reinterpret_cast&lt;void**&gt;(&amp;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(&quot;p2&quot;);<br>	CString szTemp;<br>	szTemp = bStr;<br>	AfxMessageBox(szTemp);<br>	CString strTable=&quot;ABCDEFG&quot;;<br>	BSTR bstrTable = strTable.AllocSysString();<br>	//spP1-&gt;put_innerHTML(bstrTable);<br>	SetElementHtml(&quot;p2&quot;,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&amp; 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>&lt;p id=&quot;p4&quot;&gt;&lt;b&gt;p4 for ddx&lt;/b&gt;&lt;/p&gt;
&lt;input type=&quot;text&quot; ID=&quot;input1&quot; size=&quot;20&quot; value=&quot;input1 for ddx&quot; NAME=&quot;input1&quot;&gt;
&lt;input type=&quot;text&quot; ID=&quot;input2&quot; size=&quot;20&quot; value=&quot;101&quot; NAME=&quot;input2&quot;&gt;

在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()-&gt;LoadIcon(IDR_MAINFRAME);
		m_szP4 = &quot;test for p4&quot;;
		m_szInput1= &quot;test for input1&quot;;
		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">&nbsp;</p>
  <p align="right">&nbsp;</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 + -