分析过程基本到此,可以看出程序启动时,创建系统的钩子,获取Shell的相关消息,再对消息进行判断。发现是旺旺收到的消息的话,就对旺旺的聊天窗口获取IE指针,再从IE里获取聊天的相关信息即可实现了。
3。 创建程序具体再进行分析。
3.1 使用VS2005+MFC创建一个对话框程序(因为使用的都是标准的WindowsAPI,所以本方法和语言无关,Delphi,VB,C#,C++等均可轻松实现)
3.2 在OnInitDialog中实现挂钩,RegisterShellHookWindow 和SetWindowsHookEx,WH_SHELL实现的目的是一样的.
HWND Hwnd = GetSafeHwnd();
msgShellHook = RegisterWindowMessage(L"SHELLHOOK");
RegisterShellHookWindow( Hwnd );
lpPrevWndProc = SetWindowLong( Hwnd , GWL_WNDPROC, long(MyWindowProc) );
static LRESULT CALLBACK MyWindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
ATLTRACE("hwnd:%d,uMsg:%d,wParam:%ld,lParam:%ld\r\n",hwnd,uMsg,wParam,lParam);
return CallWindowProc((WNDPROC)lpPrevWndProc, hwnd, uMsg, wParam, lParam);
}
将Hook到的所有消息输出。
3.3 分析Shell消息:
聊天窗口未打开时收到聊天消息时的输出内容:
hwnd:855962,uMsg:49194,wParam:6,lParam:921510
hwnd:855962,uMsg:874,wParam:0,lParam:0
hwnd:855962,uMsg:49194,wParam:6,lParam:921510
hwnd:855962,uMsg:874,wParam:0,lParam:0
hwnd:855962,uMsg:49194,wParam:1,lParam:921510
hwnd:855962,uMsg:874,wParam:0,lParam:0
hwnd:855962,uMsg:49194,wParam:32774,lParam:921510
hwnd:855962,uMsg:49194,wParam:32774,lParam:921510
hwnd:855962,uMsg:874,wParam:0,lParam:0
hwnd:855962,uMsg:49194,wParam:6,lParam:921510
hwnd:855962,uMsg:874,wParam:0,lParam:0
hwnd:855962,uMsg:49194,wParam:32774,lParam:921510
hwnd:855962,uMsg:49194,wParam:32774,lParam:921510
hwnd:855962,uMsg:1125,wParam:4176056,lParam:0
hwnd:855962,uMsg:273,wParam:67109864,lParam:921390
hwnd:855962,uMsg:307,wParam:-268363765,lParam:921390
hwnd:855962,uMsg:273,wParam:50332648,lParam:921390
hwnd:855962,uMsg:874,wParam:0,lParam:0
hwnd:855962,uMsg:49194,wParam:6,lParam:921510
hwnd:855962,uMsg:874,wParam:0,lParam:0
hwnd:855962,uMsg:49194,wParam:32774,lParam:921510
hwnd:855962,uMsg:49194,wParam:32774,lParam:921510
hwnd:855962,uMsg:874,wParam:0,lParam:0
聊天窗口已打开,收到聊天消息时的输出内容:
hwnd:855962,uMsg:49194,wParam:32774,lParam:921510
hwnd:855962,uMsg:49194,wParam:32774,lParam:921510
hwnd:855962,uMsg:1125,wParam:4176344,lParam:0
hwnd:855962,uMsg:273,wParam:67109864,lParam:921390
hwnd:855962,uMsg:307,wParam:-2113853412,lParam:921390
hwnd:855962,uMsg:273,wParam:50332648,lParam:921390
hwnd:855962,uMsg:874,wParam:0,lParam:0
hwnd:855962,uMsg:49194,wParam:6,lParam:921510
hwnd:855962,uMsg:874,wParam:0,lParam:0
hwnd:855962,uMsg:49194,wParam:32774,lParam:921510
hwnd:855962,uMsg:49194,wParam:32774,lParam:921510
hwnd:855962,uMsg:874,wParam:0,lParam:0
hwnd:855962,uMsg:49194,wParam:6,lParam:921510
hwnd:855962,uMsg:874,wParam:0,lParam:0
hwnd:855962,uMsg:49194,wParam:32774,lParam:921510
hwnd:855962,uMsg:49194,wParam:32774,lParam:921510
hwnd:855962,uMsg:874,wParam:0,lParam:0
使用Spy4Win查看聊天窗口:
可以看出hwnd:855962 是当前程序的窗口。lParam:921510即是旺旺的聊天消息的窗口。
可以发现每次收到消息时,不管聊天窗口是否已经打开。均有uMsg:49194,wParam:32774,lParam:921510的消息触发。
添加代码:
switch( wParam )
{
case 32774:
{
HWND hChat = (HWND)lParam;
char name[255] ={0};
GetClassNameA(hChat,name,255);
//判断聊天窗口是否为旺旺的窗口。
if(strcmp(name,"StandardFrame") == 0)
{
ProcessMsg(hwnd,hChat);
}
}
break;
default:
break;
}
3.4 获取聊天窗口句柄,以及历史记录的窗口句柄,历史记录IE的指针。
在ProcessMsg中,根据旺旺的聊天窗口,找到历史记录(WebBrowser)窗口的句柄:
HWND hFind = ::FindWindowEx(hChat,NULL,L"SplitterBar",NULL);
hFind = ::FindWindowEx(hFind,NULL,L"StandardWindow",NULL);
hFind = ::FindWindowEx(hFind,NULL,L"SimpleBrowser",NULL);
hFind = ::FindWindowEx(hFind,NULL,L"Shell Embedding",NULL);
hFind = ::FindWindowEx(hFind,NULL,L"Shell DocObject View",NULL);
hFind = ::FindWindowEx(hFind,NULL,L"Internet Explorer_Server",NULL);
CComPtr<IHTMLDocument2> spDoc;
LRESULT lRes;
UINT nMsg = ::RegisterWindowMessage( _T("WM_HTML_GETOBJECT") );
::SendMessageTimeout( hFind, nMsg, 0L, 0L, SMTO_ABORTIFHUNG, 1000, (DWORD*)&lRes );
HRESULT hr;
hr = ObjectFromLresult( lRes, IID_IHTMLDocument2, 0, (void**)&spDoc );
if ( SUCCEEDED(hr) )
{
CComPtr<IHTMLElement> spElement;
spDoc->get_body(&spElement);
//处理网页内容。
CComBSTR text;
spElement->get_outerHTML(&text);
wstring strText(text);
}