/**********************************************************************************************
*QQ2010模拟登陆之思路与分析
*作者:裴具才
*QQ:592123987
*发表时间:2010/10/1
*说明:文章只做学习交流使用,请勿用于非法用途,否者,后果自负。
**********************************************************************************************/
QQ2010模拟登陆的大致思路:
1、使用EnumWindows函数遍历桌面窗口,获取QQ2010登陆框的句柄。
HWND hWnd;//全局变量保存QQ登陆框句柄
BOOL CALLBACK EnumWindowsProc(HWND hwnd,LPARAM lParam)
{
CString Str=_T("");
int Strlen=::GetWindowTextLength(hwnd)+1;
::GetWindowText(hwnd,Str.GetBuffer(Strlen),Strlen);
Str.LockBuffer();
if (Str=="QQ2010"&&::FindWindowEx(hwnd,NULL,"ATL:30A44018",NULL)&&::FindWindowEx(hwnd,NULL,"Edit",NULL))
hWnd=hwnd;
return true;
}
2、取得QQ用户名句柄,模拟输入QQ号,方法很多,不再多说。如:发送 WM_SETTEXT、WM_CHAR或WM_PASTE消息的任何一个都行。
void CMyDlg::SendQQ(HWND hWnd,CString str)
{
//方法一:
::SetFocus(hWnd);
::PostMessage(hWnd,WM_CLEAR,0,0);
CopyStrToClipboard(str);//复制QQ号到剪贴板
::PostMessage(hWnd,WM_PASTE,0,0);
//方法二:
// ::PostMessage(hWnd,WM_CLEAR,0,0);
// for(int i=0;i<str.GetLength();i++)
// ::SendMessage(hWnd,WM_CHAR,(WPARAM)str.GetAt(i),0);
}
3、取得QQ密码框句柄,模拟输入QQ密码,这一步是最关键,使用SendInput模拟输入密码。一般的模拟输入方法不行。
void CMyDlg::SendInput(char ch)
{
LPINPUT key=new INPUT;
key->type = INPUT_KEYBOARD;
key->ki.wVk = ch;
key->ki.time=0;
key->ki.wScan=0;
key->ki.dwFlags=0;
key->ki.dwExtraInfo = KEYEVENTF_KEYUP;
::SendInput(1, key, sizeof(INPUT));
::Sleep(1);
delete key;
key=NULL;
}
void CMyDlg::SendPassword(HWND hWnd,CString str)
{
::SetFocus(hWnd);
for(int i=0;i<str.GetLength()+5;i++)
SendInput(VK_BACK);//清空原来密码框中的内容
for(i=0;i<str.GetLength();i++)
SendInput((char)str.GetAt(i));
}
4、登陆的方法:使用模拟按下Enter键登陆。
//模拟按下Enter键登陆QQ
::PostMessage(QQhwnd,WM_KEYDOWN,(WPARAM)VK_RETURN,NULL);//QQhwnd用户名的句柄
::PostMessage(QQhwnd,WM_KEYUP,(WPARAM)VK_RETURN,NULL);
其他:
自动查找QQ路径:通过注册表获得QQ的安装路径,如果有已运行的QQ,可枚举进程列表得到,QQ的路径,当然还有其他方法。
/**********************************************************************************************
*函数名称:GetQQPath()
*函数参数:void
*函数类型:CString
*函数功能:返回QQ的安装路径
**********************************************************************************************/
CString CMyDlg::GetQQPath()
{
HKEY hKey;
DWORD lRead;
::RegOpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE//Tencent//PlatForm_Type_List//3",&hKey);
::RegQueryValueEx(hKey, "TypePath", 0, NULL, NULL, &lRead);
CString qqPath="";
::RegQueryValueEx(hKey, "TypePath", 0, NULL, (BYTE*)qqPath.GetBuffer(lRead), &lRead);
qqPath.LockBuffer();
::RegCloseKey(hKey);
return qqPath;
}
QQ的启动:使用ShellExecute函数启动QQ。
QQ模拟登陆实现模块代码:
void CMyDlg::OnButton1()
{
// TODO: Add your control notification handler code here
ShowWindow(SW_HIDE);
HWND parenthwnd=0;
HWND childhwnd=0;
HWND QQhwnd=0;//用来保存QQ用户名的句柄
CString QQ="";//该变量保存QQ号
CString password="";//该变量保存QQ密码
GetDlgItem(IDC_EDIT_QQ)->GetWindowText(QQ);
GetDlgItem(IDC_EDIT_PSW)->GetWindowText(password);
password.MakeUpper();
::ShellExecute(NULL,"open",QQPath,NULL,NULL,SW_SHOW); //启动QQ
while(!parenthwnd)
{
::EnumWindows(EnumWindowsProc,NULL);
parenthwnd=hWnd;
hWnd=NULL;
}
QQhwnd=::FindWindowEx(parenthwnd,NULL,"ATL:30A44018",NULL);
SendQQ(QQhwnd,QQ);
SendPassword(::FindWindowEx(parenthwnd,NULL,"Edit",NULL),password);//模拟输入QQ密码
::Sleep(20);
//模拟按下Enter键登陆QQ
::PostMessage(QQhwnd,WM_KEYDOWN,(WPARAM)VK_RETURN,NULL);
::PostMessage(QQhwnd,WM_KEYUP,(WPARAM)VK_RETURN,NULL);
exit( 1 );//退出本程序 //::PostMessage(m_hWnd,WM_CLOSE,0,0);
}