目的:加深对IWebBrowser2的理解,整理。方便以后学习和使用。也方便需要这反面的朋友少点弯路。
声明:有些知识点是本人在使用和学习中借助网络搜索到的,所以难免会有雷同,我会尽量标注原著的出处,当然也可能找不到原著的出去了,如果牵扯到版权或者其他的可以通知我,我会跟你一同处理。本文的源码也有部分是来自网络和msdn上面,出处我也会尽量标明。
前言:前段时间,一个大学同学问我,在win下面c++怎么获取web的登陆状态,是哪个用户登陆的,我告诉他可以内嵌webbrowser实现,他叫我帮忙提供一个demo给他,所以我利用空余时间帮忙做了一个win32的程序模拟登陆csdn的demo给他。后面他又说,不要模拟登陆,要用户自己点击登陆,然后c++来获取登陆是否成功,并且是哪个用户在登陆。我说那就得改改程序,给他提了几个点。最后也不知道他们公司的c++程序员 搞定没。后面自己想了一下,觉得有必要把c++与IWebBrowser2的东西整理一下,自己也理一下,所以用了点时间添加了一个demo,并且写这篇博客。
正文
1.开发环境和知识点
代码是使用vs2008编译,是win32的程序(不是mfc)。阅读的时候需要你了解过简单的win32编程,也会一些简单的web基础(html元素的概念),会根据ie浏览器查询你需要的html元素。如果你具备这些 那么阅读和学习这个东西就很简单了。
2.引用和借鉴的url
这个我会尽量列举在这里,找不到出去就没法发了
http://www.tuicool.com/articles/fiq26ve (win32使用iwebbrowser)
https://msdn.microsoft.com/en-us/library/bb508508(VS.85).aspx (html事件监听)
http://bbs.csdn.net/topics/20135139 (IDocHostUIHandler重写)
http://blog.csdn.net/mfcing/article/details/44540683 http://blog.csdn.net/aasmfox/article/details/7016236 (c++与js交互)
http://www.cnblogs.com/jivi/archive/2013/03/28/2985726.html (源码借鉴了 HTMLElementEvents2 的重写)
以上就是我能记住的参考过的url了。下面的文章不在注明具体是那个知识点参照上面的url了。
3.win32模拟登陆csdn程序
原理说明:内嵌一个webbrowser的com组件,指定url就会把页面加载出来(具体原理需要http通信,获取返回值,解析页面,执行js等等),加载之后我们根据html标签的id或者是name或者是tag等查找你需要的IHTMLElement对象(id和name的查找,可以用ie打开url按f12键查找元素,查看html标签具体信息),接下来就是对IHTMLElement的操作,可以输入数据,触发点击事件等。点击之后等待页面跳转或者是重新加载,根据加载的新数据来判断是否登录成功(一般登录成功会跳转页面,有些web会记录cookie等其他信息,这些都需要根据不同的web网站 做不同的判断)
首先,需要一个基于对话框的win32程序,上面有2个按钮(一个模拟登陆按钮,一个导航按钮)和3个输入框(一个输入url,一个输入用户名,一个输入密码)
代码段
int WINAPI _tWinMain(HINSTANCE hInst, HINSTANCE h0, LPTSTR lpCmdLine, int nCmdShow)
{
DialogBox(hInst,MAKEINTRESOURCE(IDD_DIALOG_MAIN),NULL,(DLGPROC)MainDialogProc);
return TRUE;
}
// Windows 事件处理
LRESULT CALLBACK MainDialogProc(HWND hDlg,UINT message,
WPARAM wParam,LPARAM lParam)
{
//消息的处理,我想你要的就是这里了
switch(message)
{
case WM_INITDIALOG:
return DialogInit(hDlg,wParam,lParam);
break;
case WM_COMMAND:
return CommandFun(hDlg,wParam,lParam);
break;
case WM_CLOSE://关闭在这里
EndDialog(hDlg,TRUE);
return TRUE;
break;
}
return FALSE;
}
LRESULT DialogInit(HWND hDlg,WPARAM wParam,LPARAM lParam)
{
RECT rc;
GetClientRect(hDlg, &rc);
HWND hStaticOption = GetDlgItem(hDlg,IDC_STATIC_OPTION);
RECT rc_Option;
GetWindowRect(hStaticOption,&rc_Option);
//
SetDlgItemText(hDlg,IDC_EDIT_URL,_T("https://passport.csdn.net/account/login"));
SetDlgItemText(hDlg,IDC_EDIT_NAME,_T("xxxxxxx"));
SetDlgItemText(hDlg,IDC_EDIT_PWD,_T("xxxxxx"));
//
RECT webRc;
webRc.left = 0;
webRc.top = rc_Option.bottom;
webRc.right = rc.right;
webRc.bottom = rc.bottom;
gWebAutoLogin = new WebAutoLogin(hDlg, webRc);
gWebAutoLogin->Navigate(L"https://www.baidu.com/");
StartWaitWebLoad(hDlg);
return TRUE;
}
LRESULT CommandFun(HWND hDlg,WPARAM wParam,LPARAM lParam)
{
//IDC_CLOSE 是我在对话框中加入的一个按钮的ID 也可以关闭
if (LOWORD(wParam)==IDOK)
{
PostQuitMessage(0);
}
else if (LOWORD(wParam)==IDC_BTN_GO)
{
LoadWeb(hDlg);
}
else if (LOWORD(wParam)==IDC_BTN_LOGIN)
{
SimulateLogin(hDlg);
}
else
{
return FALSE;
}
return TRUE;
}
void LoadWeb(HWND hDlg)
{
wchar_t url[MAX_PATH*2+1] ={0};
GetDlgItemText(hDlg,IDC_EDIT_URL,url,MAX_PATH*2);
std::wstring strUrl;
strUrl.assign(url);
gWebAutoLogin->Navigate(strUrl);
StartWaitWebLoad(hDlg);
}
void SimulateLogin(H