以前我们为了编写一个漂亮的程序,需要用VC进行客户区非客户区重绘,需要维护图片载入、GDI绘制、消息处理、重载各种控件……,虽然很多人都是这么做的,包括我最近做的项目中,仍然使用GDI在做很多界面上的事情。但是,目前似乎程序结合Web页面,共同去做些事情仿佛越来越流行。当然,界面编程还是离不开GDI或GDI+,我这里只是记录一些我认为未来在写软件、做项目中可能会使用的一些技术——当然,这种技术已经很多人都在用了,而且肯定用的比我好,希望玩儿的比较溜的多包涵文中的错误和不足。
从今天开始,我计划用1、2个月的时间陆续写一些关于使用ATL/WTL和网页交互的文字,包括使用COM来操作网页元素,以及对网页元素事件的响应。
无论是用MFC/ATL/WTL,无论是Insert一个Microsoft Web Browser的ActiveX控件,还是动态创建了一个Browser实例,甚至是你要直接操作Windows系统的IE,我们首先要做的事情就是获得IE Browser的接口。
我们首先来编写一个WTL的示例程序开始说明。
(未完待续)
2008年1月16日
最近一段时间实在是太忙了,刚刚把新产品的需求分析弄完。下一个产品的需求分析马上又要来了。郁闷。
现在编码的工作基本都交代出去了,自己已经没有多少时间编码了,很多新的技术和细节我已经不擅长了,不知道这是好是坏。不过最近项目管理的事情倒是学到了不少。
废话少说,我还是尽量抽空把这个文章写完。
使用WTL向导做一个标准的对话框程序出来,记得要把Enable ActiveX Control Hosting的选项勾上。然后丢一个Microsoft Web Browser的ActiveX控件上去,ID比方说是IDC_EXPLORER。
想让对话框能够接收WebBrowser控件的事件,需要为对话框增加一些继承类。首先我们定义这样一个东东:
#define WebBrowser IDispEventImpl<IDC_EXPLORER, CMainDlg, &DIID_DWebBrowserEvents2, &LIBID_SHDocVw, 1, 0>
然后添加到对话框的继承列表中,如下:
class CMainDlg : public CAxDialogImpl<CMainDlg>, public CUpdateUI<CMainDlg>,
public CMessageFilter, public CIdleHandler, public WebBrowser
到stdafx.h中添加这几个必要的头文件:
#include <exdisp.h>
#include <exdispid.h>
#include <mshtml.h>
#include <mshtmdid.h>
OK,我们希望处理的是对话框上那个WebBrowser控件的事件,因此,需要维护一个该控件的成员变量:
CComPtr<IWebBrowser2> m_pWeb2;
接下来,选择我们希望处理的网页事件。首先添加消息响应宏,然后添加两个事件,如下:
BEGIN_SINK_MAP(CMainDlg)
SINK_ENTRY_EX(IDC_EXPLORER, DIID_DWebBrowserEvents2, DISPID_DOCUMENTCOMPLETE, OnDocumentComplete)
SINK_ENTRY_EX(IDC_EXPLORER, DIID_DWebBrowserEvents2, DISPID_BEFORENAVIGATE2, OnBeforeNavigate2)
END_SINK_MAP()
我们上面希望处理两个事件:OnBeforeNavigate2和OnDocumentComplete。下面是这两个事件的实现体:
void __stdcall OnDocumentComplete(IDispatch *, VARIANT* )
{
MessageBox(_T("Current document complete!"),_T("Info"),MB_OK|MB_ICONEXCLAMATION);
}
void __stdcall CMainDlg::OnBeforeNavigate2 (
IDispatch* pDisp, VARIANT* URL, VARIANT* Flags, VARIANT* TargetFrameName,
VARIANT* PostData, VARIANT* Headers, VARIANT_BOOL* Cancel )
{
MessageBox(_T("Before navigate!"),_T("Info"),MB_OK|MB_ICONEXCLAMATION);
};
下面我们让对话框启动时,让嵌入的Web Browser ActiveX控件直接打开一个网页,在OnInitDialog中添加下面的代码:
CAxWindow AxWin = GetDlgItem(IDC_EXPLORER);
AxWin.QueryControl(&m_pWeb2);
if (m_pWeb2)
{
WebBrowser::DispEventAdvise(m_pWeb2);
m_pWeb2->Navigate(CComBSTR("http://blog.csdn.net/epubcn/"),NULL,NULL,NULL,NULL);
}
记得在OnDestroy中释放网页事件监控:
if (m_pWeb2)
{
WebBrowser::DispEventUnadvise(m_pWeb2);
m_pWeb2.Release();
}
OK,现在编译运行一下是否会弹出预期的消息对话框。
注:如果运行时发生ATLASSERT(!InlineIsEqualGUID(*m_plibid,GUID_NULL) && "Did you forget to pass the LIBID to CComModule::Init?");错误,请将工程设置中的“ATL使用”改为“动态链接到ATL”即可。
上面是对网页事件的响应。接下来让我们来处理网页上某个元素的事件。比如一个BUTTON的单击、超级链接的点击、一个复选框按钮是否被选中、文本输入框内容的改变和获取等。
(未完待续)