日历归档 |
|
<< < 2024 - 11 > >> | Su | Mo | Tu | We | Th | Fr | Sa | | | | | | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 |
|
|
|
About Me |
|
|
ZhangSichu |
|
Male |
|
32 |
|
ZhangSichu@gmail.com |
|
ZhangSichu@hotmail.com |
|
ZhangSichu.com |
|
weibo.com/zhangsichu |
|
|
|
个人推荐 |
|
|
|
|
分类归档 |
|
|
|
|
My Friends |
|
|
|
|
HTML对话框的实现[转载]
|
开发环境:VS7,Windows XP,Windows 2K
在VS7中添加了一种新的对话框类:CDHtmlDialog,顾名思义就是能够显示DHTML内容的对话框,但不同与以前的CHTMLView不同的是添加了对DHTML的支持,能够响应各种DHTML的事件,而且能够方便的得到网页上的各种内容和输入。在这以前要完成这些功能必须通过复杂的COM接口来完成,而现在MS MFC已经为我们做好了这一切。
在下面我会按照下面的顺序讲解CDHtmlDialog的用法。但本文也只能对DHTML对话框的功能进行部分的讲解,更多更全的说明需要大家自己摸索和查找资料。本文的目的是在于讲解如何得到和设置网页上的各种元素的值,如何处理事件。
此外在阅读本文前你必须对HTML和DHTML有所了解。
CDHtmlDialog类的成员函数 CDHtmlDialog事件处理映射宏 CDHtmlDialog类的各种DDX帮助宏 一个简单的例子 类成员函数介绍
构造函数
CDHtmlDialog( ); CDHtmlDialog( LPCTSTR lpszTemplateName, LPCTSTR szHtmlResID, CWnd *pParentWnd = NULL ); CDHtmlDialog( UINT nIDTemplate, UINT nHtmlResID = 0, CWnd *pParentWnd = NULL );
你可以看到和CDialog不同的就在于第二个参数,表示在对话框创建时是否自动加载HTML,这里必须说明的是HTML必须以资源的形式存放,这个参数指明的是资源的ID或名称。
或者你可以利用
BOOL LoadFromResource( LPCTSTR lpszResource ); BOOL LoadFromResource( UINT nRes );
将HTML内容在后期进行装载。
页面浏览
此外一些函数如:OnNavigateComplete,OnBeforeNavigate,Navigate等用于页面转换的函数,在以前的CHtmlView中就有这里就不再作讲解。
得到当前URL
void GetCurrentUrl( CString& szUrl );
得到网页中的DHTML元素的指定接口
HRESULT GetElementInterface( LPCTSTR szElementId, REFIID riid, void** ppvObj );
第一个参数指定,第二个参数指定接口ID,第三个参数返回接口指针。
得到网页中的DHTML元素的IHTMLElement接口
HRESULT GetElement( LPCTSTR szElementId, IHTMLElement **pphtmlElement ); 相当于调用 GetElementInterface(szElementId,IHTMLElement,pphtmlElement);
这个函数非常的重要,因为如果要得到DHTML的内容就必须通过页面上的各个元素的属性来得到,例如:对于Input type=text的属性value就是输入的值,对于p的属性innerText就是段落中的内容。
函数的第二个参数就是元素的名称。
函数的第二个参数,是一个指向指针的指针,通过它得到IHTMLElement的接口。函数返回值是HRESULT其值的定义符合COM中对返回值的定义。(如果你不了解,可以简单的检测返回值是否等于S_OK)
得到元素的innerText和innerHTML的属性
innerHTML属性: BSTR GetElementHtml( LPCTSTR szElementId ); innerText属性: BSTR GetElementText( LPCTSTR szElementId ); 相当于调用IHTMLElement接口的gett_innerHTML和get_innerText方法 与之对应的是设置元素的innerText和InnerHTML属性:
innerHTML属性: void SetElementHtml( LPCTSTR szElementId, BSTR bstrText ); innerText属性: void SetElementText( LPCTSTR szElementId, BSTR bstrText ); 相当于调用IHTMLElement接口的put_innerHTML和put_innerText方法 示范代码
假设页面上的代码为:<p id=p2>test</p>,执行下面代码可以显示原来的内容和将新内容设置为:abcdefg
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; bStr = GetElementHtml("p2"); CString szTemp; szTemp = bStr; AfxMessageBox(szTemp); CString strTable="ABCDEFG"; BSTR bstrTable = strTable.AllocSysString(); //spP1->put_innerHTML(bstrTable); SetElementHtml("p2",bstrTable);
事件处理映射宏
基本格式
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()
更详细的说明可以查阅MSDN中DHTML Event Map Macros部分。MSDN中对可以处理的事件进行了详细的说明。DHTML中的事件与Windows中消息不是同一个概念,虽然映射宏的形式很相同。
添加映射处理代码
我在VC7中没有发现自动添加各种事件映射的方法,只能通过手工添加代码的方式。
定义事件处理函数: 函数原型为: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; }
各种DDX帮助宏
DDX宏介绍
如同CDialog类一样,CHtmlDialog也提供各种DDX帮助宏来与HTML页面上的控件交换数据。
遗憾的是VS7中无法为CDHTMLDialog 的子类自动添加DDX变量,必须通过手工添加。
设置innerText和innerHTML属性
DDX_DHtml_ElementInnerText( CDataExchange* dx, LPCTSTR name, CString& var ) 和 DDX_DHtml_ElementInnerHtml( CDataExchange* dx, LPCTSTR name, CString& var ) 相当与前面提到的设置和获取innerText,innerHTML属性。
获取和设置控件中的值
在DHTML中利用“对象名程.value”可以得到控件中输入的值,利用DDX也同样可以得到。
DDX_DHtml_ElementValue( CDataExchange* dx, LPCTSTR name, var ) 用于在控件和对象之间交换数据。
使用方法
假设HTML文件中代码如下
<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; }
一个简单的例子
最后介绍一下如何利用VC7创建一个利用CDHtmlDialog的工程。
首先创建工程,进行如下设置:
在资源管理中修改HTML文件:
最后添加自己的代码。我提供的例子中所使用的函数在上面都已经提到。大家可以下载这份例子去进行一定的参考
|
|
#re:HTML对话框的实现[转载] 3/25/2024 8:30:14 AM 江振磊
|
|
|
|
|
|