以前qq2008以前的版本编写自动登录程序都比较简单,可以采用命令行的方式去实现(QQ2008以前版本支持命令行登录),但2009之后的版本不支持命令行登录.本文介绍如何在2009下实现批量登陆.
经过试验,用户名可以采用发送粘贴消息,一串字符输入,而密码只能模拟键盘消息,一个个字符输入.
实现步骤:
1.启动QQ2009
2.获取QQ2009窗口句柄
3.获取QQ2009用户名和密码窗口句柄
4.模拟键盘消息,往用户名,密码窗口发送消息
5.发送回车键消息,模拟点击登录按钮
//获得QQ主窗口句柄
HWND s_QQhWnd = NULL;
BOOL CALLBACK GetQQWindows(HWND hwnd,LPARAM lParam)
{//获取qq窗口
TCHAR szText[128];
if( GetWindowText(hwnd, szText,128) )
{
if(strcmp(szText,_T("QQ2009")) ==0)
{
s_QQhWnd = hwnd;
return FALSE;
}
}
return TRUE;
}
HWND g_USER = NULL;
HWND g_Edit = NULL;
BOOL CALLBACK EnumChildProc(HWND hwnd,LPARAM lParam)
{ //枚举QQ子窗口.用户名和密码框
if (hwnd)
{
char buff[128];
memset(buff,0,128);
GetClassName(hwnd,buff,128);
CString str = buff;
if(str == "ATL:30A4E1D8")
{//用户名框
g_USER = hwnd;
}
if(str == "Editer")
{//密码框
g_Edit = hwnd;
}
}
return TRUE;
}
CString CAutoLoginQQDlg::GetQQexePath()
{//从注册表里查找到qq的安装路径
HKEY pathKey;
RegCreateKey(HKEY_LOCAL_MACHINE,_T("SOFTWARE\\Tencent\\QQ2009"),&pathKey);
int count = 0;
CString strCount;
DWORD dwType = 0;
DWORD dwSize = 0;
LPBYTE dwValue = NULL;
CHAR szpath[512];
RegQueryValueEx(pathKey,"Install",NULL,&dwType,NULL,&dwSize);
RegQueryValueEx(pathKey,"Install",NULL,&dwType,(LPBYTE)&szpath,&dwSize);
CString strpath = szpath;
RegCloseKey(pathKey);
return strpath + "\\bin\\qq.exe";
}
void CAutoLoginQQDlg::LoadQQ(CString strUseName,CString strPassward)
{
s_QQhWnd = NULL;
g_USER = NULL;
CString exePath = GetQQexePath();
ShellExecute(NULL, _T("open"), exePath, NULL,NULL, SW_SHOW);
DWORD starttime = GetTickCount();
DWORD distime = 0;
while(true)
{
Sleep(200);
EnumWindows(GetQQWindows, NULL);
EnumChildWindows(s_QQhWnd, (WNDENUMPROC)EnumChildProc,(LPARAM)NULL);
::SetForegroundWindow(s_QQhWnd);
if(g_USER)
{
//用户名可以采用粘贴板发送粘贴消息来实现
DWORD dwLength = strUseName.GetLength();
HANDLE hGlobalMemory = GlobalAlloc(GHND, dwLength + 1);
LPBYTE lpGlobalMemory = (LPBYTE)GlobalLock(hGlobalMemory);
for (int i = 0; i < strUseName.GetLength(); i++)
*lpGlobalMemory++ = strUseName.GetAt(i);
GlobalUnlock(hGlobalMemory);
HWND hWnd = GetSafeHwnd();
::OpenClipboard(hWnd);
::EmptyClipboard();
::SetClipboardData(CF_TEXT, hGlobalMemory);
::CloseClipboard();
::SendMessage(g_USER,WM_PASTE, 0, 0);
::PostMessage(g_Edit,WM_SETFOCUS,0,0);
SetPassWard(strPassward);
Sleep(200);
::PostMessage(s_QQhWnd,WM_KEYDOWN,VK_RETURN,0);
return;
}
distime = GetTickCount() - starttime;
if(distime >= 5000)
break;
}
}
void CAutoLoginQQDlg::SetPassWard(CString strPass)
{//模拟键盘消息,输入密码
for (int row = 0; row < strPass.GetLength(); row ++)
{
char pChar = strPass.GetAt(row);
SHORT ks = VkKeyScan(pChar);
BYTE key = ks & 0xFF;
keybd_event(key,0,0,0);
keybd_event(key,0,KEYEVENTF_KEYUP,0);
}
}