為什么寫這個:
1,像我這么愛干凈的人,當(dāng)然不能容忍和MM聊天的時候,看到一個內(nèi)衣廣告在上面一閃一閃,這不引誘老納么;
2,為什么不用其它外掛?珊瑚蟲已S,再沒用過其它。現(xiàn)有的外掛實現(xiàn)了一些我不想要的功能,看IP也沒必要,聊天的都是熟人。另外,不知道它做了些什么事情;
3,打發(fā)這個無聊的周末。
怎樣實現(xiàn):
1,萬能的HOOK
現(xiàn)在用到的是全局的SHELL HOOK,Hook的是窗口創(chuàng)建完成的消息;
g_hShellHook = SetWindowsHookEx( WH_SHELL,
(HOOKPROC)ShellHook,
g_hInstance,
0);
ShellHook 的實現(xiàn)如下:
static LRESULT CALLBACK ShellHook(UINT nCode, WPARAM wParam, LPARAM lParam)


{
if(nCode < 0)
goto CallOrg;
if( HSHELL_WINDOWCREATED == nCode )

{
if( !isQQWnd( (HWND)wParam ) )
goto CallOrg;
EnumChildWindows( (HWND)wParam, EnumChildProc, (LPARAM)0 );
}
CallOrg:
return CallNextHookEx( g_hShellHook, nCode, wParam, lParam);
}

在收到窗口創(chuàng)建后的消息時,就判斷這個窗口是不是QQ的,這里用到了 GetWindowThreadProcessId ,它返回窗口相關(guān)的進程ID
BOOL isQQWnd(HWND hWnd)


{
if( g_pContext == NULL )
return FALSE;

if( g_dwQQProcessID == 0 )
g_dwQQProcessID = GetQQProcessID();
DWORD dwWndProcessID;
if( GetWindowThreadProcessId( hWnd, &dwWndProcessID ) == 0 )
return FALSE;
return dwWndProcessID == g_dwQQProcessID;

}

然后枚舉它的子窗口,看它的子窗口有沒有廣告控件,有的話就給子控件發(fā)送個WM_CLOSE的消息.
BOOL CALLBACK EnumChildProc(HWND hwnd, LPARAM lParam )


{
DWORD dwID = GetDlgCtrlID( hwnd );
if( dwID == 0x3e9 )

{
HWND hPrarent = GetParent( hwnd );
PostMessage(hwnd, WM_CLOSE, 0, 0 );
Sleep( 10 );
PostMessage(hPrarent, WM_PAINT, 0, 0 );
}
else if( dwID == 0x643f )

{
PostMessage(hwnd, WM_CLOSE, 0, 0 );
}

return TRUE;
}

其中的兩個硬編碼是用 spy++ 分析出來的,可能因為版本的不同,會有差異。所以我不確定能不能關(guān)閉其它版本的QQ廣告。我使用的版本是QQ2008賀歲版。
--------------------------------------------------------------------------
后記:
盡管實現(xiàn)的技術(shù)很簡單,但還是花了我大半天的時間. 寫完之后覺得枚舉子窗口的方式太低效, 或者還有其它高效點的方式。另外還有全局鉤子,可能沒有必要。如果下午周末持續(xù)無聊,我會嘗試改進一下。
QQ的聊天對話框很簡單,不像MSN的對話框,鐵板一塊,用spy++啥都看不到.但是可以用 AccExplorer 分析.想在MSN的對話框上加點東西進去,實現(xiàn)起來很困難。對這方面有研究的同學(xué)不妨與我討論一下實現(xiàn),一起學(xué)習(xí)、進步。
代碼的行數(shù)沒數(shù),有效代碼估計也就百把行吧,呵呵,我承認我是標(biāo)題黨。
附: 源代碼 + bin