VC++通用HOOK ExtTextOutW获取QQ聊天内容

Home / C++ MrLee 2015-6-7 10011

原来写的HOOK住QQ取聊天内容,还有简单的回复,测试是OK的。现在直接贴上代码……
#include 
#include 
#include 
#include "QMsgSender.h"
#pragma comment(lib,"GDI32.lib")
#pragma comment(lib,"SHELL32.lib")
#pragma comment(lib,"USER32.lib")
#define FILESIZE 1024*1024
#define FILENAME "TEXT_CACHE"

#define QQ_STYLE 0x960F0000
#define QQ_EDIT_LEFT 0
#define QQ_EDIT_TOP 0
#define QQ_EDIT_RIGHT 539    // QQ RIGHT
#define QQ_EDIT_BOTTOM 518	//QQ BOTTOM
struct QQ_Time
{
	char _name[MAX_PATH];
	char _date[MAX_PATH];
	char _time[MAX_PATH];
};
typedef QQ_Time QTime;
#define LOG_NAME "c:\\hookapi.log"
//////////定义要跳转函数的函数类型及函数指针
//------------------------inline hook SetForegroundWindow-------------------------
BOOL WINAPI MySetForegroundWindow(HWND hWnd);
typedef BOOL (WINAPI *PFNSetForegroundWindow)(HWND);
//---------------inline hook Shell_NotifyIconW--------------------------
BOOL WINAPI MyShell_NotifyIconW(DWORD dwMessage,PNOTIFYICONDATAW lpdata);
typedef BOOL (WINAPI *PFNMyShell_NotifyIconW)(DWORD,PNOTIFYICONDATAW);
//------------------------inline hook ShowWindow-------------------------
BOOL WINAPI MyShowWindow(HWND hWnd,int nCmdShow);
typedef BOOL (WINAPI *PFNShowWindow)(HWND,int);
//------------------------inline hook ExtTextOutW---------------------------------
BOOL WINAPI MyExtTextOutW(HDC hdc,int X,int Y,UINT fuOptions,CONST RECT* lprc,LPCWSTR lpString,UINT cbCount,CONST INT* lpDx);
typedef BOOL (WINAPI *PFNExtTextOutW)(HDC hdc,int X,int Y,UINT fuOptions,CONST RECT* lprc,LPCWSTR lpString,UINT cbCount,CONST INT* lpDx);
////////申明要用的函数
void Process_Attach();
void Process_Detach();
void AppendText(char *text);
void WriteLog(char *fmt,...);
void ResetLog();
char* WCharToChar(const wchar_t *wstr);
wchar_t* CharToWChar(const char *str);
void ParseQQMsgTime(char *_time_,QTime *qTime);
HANDLE t001();
HANDLE t002();
HANDLE t003();
HANDLE t004();
HANDLE t005();
HANDLE t006();
HANDLE t007();
HANDLE t008();
HANDLE t009();
static int IndexOf(char *str1,const char *str2)
{
	char tmp[MAX_PATH];
	strncpy_s(tmp,MAX_PATH,str1,strlen(str1));
	char *pSplit = NULL;
	char *pNext = NULL;
	int nCount = 0;
	pSplit = strtok_s(tmp,str2,&pNext);
	if(pSplit != NULL)
		nCount = strlen(pSplit);
	return nCount;
}
static int LastIndexOf(char *str1,const char *str2)
{
	char tmp[MAX_PATH];
	strncpy_s(tmp,MAX_PATH,str1,strlen(str1));
	char *pSplit = NULL;
	char *pNext = NULL;
	int nCount = 0;
	int _length = strlen(str2);
	pSplit = strtok_s(tmp,str2,&pNext);
	int pLength = 0;
	while(pSplit != NULL)
	{
		pLength = strlen(pSplit) + _length;//符号的长度
		pSplit = strtok_s(NULL,str2,&pNext);
		if(pSplit != NULL)
			nCount += pLength;
	}
	return nCount - 1;
}
// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "stdafx.h"
#include "dllmain.h"
char szOldSetForegroundWindow[5] = {0};
char szJmpMySetForegroundWindow[5] = {(char)0xe9};
PFNSetForegroundWindow pSetForegroundWindow = NULL;
char szOldShell_NotifyIconW[5] = {0};
char szJmpMyShell_NotifyIconW[5] = {(char)0xE9};
PFNMyShell_NotifyIconW pShell_NotifyIconW = NULL;
char szOldShowWindow[5] = {0};
char szJmpMyShowWindow[5] = {(char)0xE9};
PFNShowWindow pShowWindow = NULL;
char szOldExtTextOutW[5] = {0};
char szJmpMyExtTextOutW[5] = {(char)0xE9};
PFNExtTextOutW pExtTextOutW= NULL;
HWND g_hWnd = NULL;//弹出的窗口句柄
int qq_msg_bottom = 0;//最后一条消息的底部坐标
char qq_last_time[MAX_PATH] = {0};//最后一条消息时间(先时间后内容)
BOOL qq_format = FALSE;//是否是QQ聊天内容格式
BOOL g_getText = FALSE;//控制是否取QQ内容
BOOL g_getTextDone = FALSE;//是否取完消息准备放到向量中等待发送
HANDLE hEvent = NULL;//同步ExtTextOutW函数
char appName[MAX_PATH];//加载程序的名字 QQ.exe和TMQQ.exe
char tempMsg[QQ_MSG_LENGTH];
CQMsgSender g_msgSender;//消息发送器
#pragma data_seg(".sdata")
HANDLE g_hFile = NULL;//共享内存块
#pragma data_seg()
#pragma comment(linker,"/SECTION:.sdata,RWS")
void Process_Attach()
{
	//ResetLog();
	//WriteLog("Process_Attach\r\n");
	g_hFile = CreateFileMappingA(INVALID_HANDLE_VALUE,0,PAGE_READWRITE, 0,FILESIZE,FILENAME);
	//inline hook ExtTextOutW 得到聊天内容,和聊天对象QQ号
	DWORD dwJmpAddr = 0;
	HMODULE hModule = LoadLibrary("Gdi32.Dll");
	pExtTextOutW = (PFNExtTextOutW)GetProcAddress(hModule, "ExtTextOutW");
	if(pExtTextOutW != NULL)
	{
		dwJmpAddr = (DWORD)MyExtTextOutW - (DWORD)pExtTextOutW - 5;
		memcpy(szJmpMyExtTextOutW + 1, &dwJmpAddr, 4);
		FreeLibrary(hModule);
		ReadProcessMemory(INVALID_HANDLE_VALUE, pExtTextOutW, szOldExtTextOutW, 5, NULL);//读出原来的前5个字节
		WriteProcessMemory(INVALID_HANDLE_VALUE, pExtTextOutW, szJmpMyExtTextOutW, 5, NULL);//写入我们处理后的5个字节        
	}
	//inline hook Shell_NotifyIconW  得到本机QQ信息
	/*dwJmpAddr = 0;
	hModule = LoadLibrary("Shell32.Dll");
	pShell_NotifyIconW = (PFNMyShell_NotifyIconW)GetProcAddress(hModule, "Shell_NotifyIconW");
	if(pShell_NotifyIconW != NULL)
	{
		dwJmpAddr = (DWORD)MyShell_NotifyIconW - (DWORD)pShell_NotifyIconW - 5;
		memcpy(szJmpMyShell_NotifyIconW + 1, &dwJmpAddr, 4);
		FreeLibrary(hModule);
		ReadProcessMemory(INVALID_HANDLE_VALUE, pShell_NotifyIconW, szOldShell_NotifyIconW, 5, NULL);//读出原来的前5个字节
		WriteProcessMemory(INVALID_HANDLE_VALUE, pShell_NotifyIconW, szJmpMyShell_NotifyIconW, 5, NULL);//写入我们处理后的5个字节
	}
	//inline hook SetForegroundWindow
	dwJmpAddr = 0;
	hModule = LoadLibrary("User32.Dll");
	pSetForegroundWindow = (PFNSetForegroundWindow)GetProcAddress(hModule, "SetForegroundWindow");
	if(pSetForegroundWindow)
	{
		dwJmpAddr = (DWORD)MySetForegroundWindow - (DWORD)pSetForegroundWindow - 5;
		memcpy(szJmpMySetForegroundWindow + 1, &dwJmpAddr, 4);
		FreeLibrary(hModule);
		ReadProcessMemory(INVALID_HANDLE_VALUE, pSetForegroundWindow, szOldSetForegroundWindow, 5, NULL);//读出原来的前5个字节
		WriteProcessMemory(INVALID_HANDLE_VALUE, pSetForegroundWindow, szJmpMySetForegroundWindow, 5, NULL);//
	}*/
	//inline hook ShowWindow
	dwJmpAddr = 0;
	hModule = LoadLibrary("User32.Dll");
	pShowWindow = (PFNShowWindow)GetProcAddress(hModule, "ShowWindow");
	if(pShowWindow != NULL)
	{
		dwJmpAddr = (DWORD)MyShowWindow - (DWORD)pShowWindow - 5;
		memcpy(szJmpMyShowWindow + 1, &dwJmpAddr, 4);
		FreeLibrary(hModule);
		ReadProcessMemory(INVALID_HANDLE_VALUE, pShowWindow, szOldShowWindow, 5, NULL);//读出原来的前5个字节
		WriteProcessMemory(INVALID_HANDLE_VALUE, pShowWindow, szJmpMyShowWindow, 5, NULL);//写入我们处理后的5个字节
	}
	hEvent = CreateEventA(NULL,FALSE,TRUE,NULL);
	g_msgSender.StartThread();
}
void Process_Detach()
{
	//WriteLog("Process_Detach\r\n");
	g_msgSender.StopThread();
	if(pExtTextOutW != NULL)
		WriteProcessMemory(INVALID_HANDLE_VALUE, pExtTextOutW, szOldExtTextOutW, 5, NULL);
	if(pShell_NotifyIconW != NULL)
		WriteProcessMemory(INVALID_HANDLE_VALUE, pShell_NotifyIconW, szOldShell_NotifyIconW, 5, NULL);
	if(pShowWindow != NULL)
		WriteProcessMemory(INVALID_HANDLE_VALUE, pShowWindow, szOldShowWindow, 5, NULL);
	if(pSetForegroundWindow != NULL)
		WriteProcessMemory(INVALID_HANDLE_VALUE, pSetForegroundWindow, szOldSetForegroundWindow, 5, NULL);
	if(hEvent != NULL)
		CloseHandle(hEvent);
	if(g_hFile != NULL)
	{
		char* ptr = (char*) MapViewOfFile(g_hFile,FILE_MAP_ALL_ACCESS,0,0,FILESIZE);
		memset(ptr,0,FILESIZE);
		CloseHandle(g_hFile);
	}
}
BOOL APIENTRY DllMain(HMODULE hModule,DWORD  ul_reason_for_call,LPVOID lpReserved)
{
	switch (ul_reason_for_call)
	{
	case DLL_PROCESS_ATTACH:
		GetModuleFileName(NULL,appName,sizeof(appName));
		if(strstr(appName,"QQ.exe") != NULL 
			|| strstr(appName,"TM.exe") != NULL)//是QQ或者TM
			Process_Attach();
		break;
	case DLL_THREAD_ATTACH:
		break;
	case DLL_THREAD_DETACH:
		break;
	case DLL_PROCESS_DETACH:
		if(strstr(appName,"QQ.exe") != NULL 
			|| strstr(appName,"TM.exe") != NULL)//是QQ或者TM
			Process_Detach();
		break;
	}
	return TRUE;
}
BOOL WINAPI MySetForegroundWindow(HWND hWnd)
{
	char szClassName[MAX_PATH]={0};
	GetClassName(hWnd,szClassName,MAX_PATH);
	if(_stricmp(szClassName,"TXGuiFoundation")==0)
	{  
		long lstyle = GetWindowLong(hWnd,GWL_STYLE);
		if(lstyle == QQ_STYLE)
		{
			char szTitle[MAX_PATH]={0};
			GetWindowText(hWnd,szTitle,MAX_PATH);
		}
	}
	WriteProcessMemory(INVALID_HANDLE_VALUE, pSetForegroundWindow, szOldSetForegroundWindow, 5, NULL);    
	BOOL bRet = SetForegroundWindow(hWnd);
	WriteProcessMemory(INVALID_HANDLE_VALUE, pSetForegroundWindow, szJmpMySetForegroundWindow, 5, NULL);
	return bRet;
}
BOOL WINAPI MyShell_NotifyIconW(DWORD dwMessage,PNOTIFYICONDATAW lpdata)
{
	if(g_hWnd != lpdata->hWnd && wcslen(lpdata->szTip) > 10)
	{  
		char *szTip = WCharToChar(lpdata->szTip);
		WriteLog(szTip);
		WriteLog("\r\n");
		g_hWnd = lpdata->hWnd;
		delete[] szTip;
	}
	WriteProcessMemory(INVALID_HANDLE_VALUE, pShell_NotifyIconW, szOldShell_NotifyIconW, 5, NULL);  
	BOOL bRet = Shell_NotifyIconW(dwMessage,lpdata);
	WriteProcessMemory(INVALID_HANDLE_VALUE, pShell_NotifyIconW, szJmpMyShell_NotifyIconW, 5, NULL);
	return bRet;
}
BOOL WINAPI MyShowWindow(HWND hWnd,int nCmdShow)
{
	//为了,如果有多个QQ聊天窗口同时弹出,就慢慢的显示,这样QQ聊天对象和QQ号不会混淆
	//判断是否是QQ聊天窗口
	char szClassName[MAX_PATH]={0};
	GetClassName(hWnd,szClassName,MAX_PATH);
	if(_stricmp(szClassName,"TXGuiFoundation")==0)
	{  
		long lstyle = GetWindowLong(hWnd,GWL_STYLE);
		if(lstyle == QQ_STYLE)
		{
			//弹出来的是QQ聊天窗口 cmd:9显示 0是关闭 SW_RESTORE=9
			if(nCmdShow == SW_RESTORE)
			{
				g_getText = TRUE;
				g_hWnd = hWnd;
			}
			else
			{
				g_getText = FALSE;
				g_hWnd = NULL;
			}
		}
	}
	WriteProcessMemory(INVALID_HANDLE_VALUE, pShowWindow, szOldShowWindow, 5, NULL);  
	BOOL bRet = ShowWindow(hWnd,nCmdShow);    
	WriteProcessMemory(INVALID_HANDLE_VALUE, pShowWindow, szJmpMyShowWindow, 5, NULL);
	return bRet;
}
BOOL WINAPI MyExtTextOutW(HDC hdc,int X,int Y,UINT fuOptions,CONST RECT* lprc,LPCWSTR lpString,UINT cbCount,CONST INT* lpDx)
{
	WaitForSingleObject(hEvent,INFINITE);
	/*if(cbCount > 0 && lprc != NULL)
	{
		char *pstr = new char[cbCount*2+1];//unicode字符2个char(字节)加上一个结束符\0
		int len = WideCharToMultiByte(CP_ACP, 0, lpString, cbCount, pstr, cbCount*2, NULL, NULL);
		pstr[len] = 0;//最后一个\0结束符
		WriteLog("0.%s   [%d,%d,%d,%d]\r\n",pstr,lprc->left,lprc->top,lprc->right,lprc->bottom);
		delete[] pstr;
	}*/
	BOOL bRet = FALSE;
	//取QQ聊天消息内容
	if(cbCount>0 && g_getText && lprc != NULL && lprc->left>=QQ_EDIT_LEFT&&lprc->right<=QQ_EDIT_RIGHT
		&&lprc->top>=QQ_EDIT_TOP&&lprc->bottom<=QQ_EDIT_BOTTOM)
	{
		int _length = cbCount<<1;
		char *pstr = new char[_length+1];//unicode字符2个char(字节)加上一个结束符\0
		int len = WideCharToMultiByte(CP_ACP, 0, lpString, cbCount, pstr, _length, NULL, NULL);
		pstr[len] = 0;//最后一个\0结束符
		//////////用坐标的问题/////////
		/*当其它坐标也符合QQ窗口坐标的时候,也会绘制进来
		所以导致有乱码或者其它界面的内容也被抓进来。只能根据
		内容里面的昵称和时间的格式确定内容是QQ聊天内容而不是其它窗口的内容*/
		int firstIndex = IndexOf(pstr,":");
		int lastIndex = LastIndexOf(pstr,":");
		int offset = lastIndex-firstIndex;
		//检测聊天内容是不是时间 如
		//昵称  22:40:33
		//昵称 2013/12/5 22:34:37
		//根据聊天时间格式来确定是聊天内容
		if((firstIndex != -1)&&(lastIndex != -1)&&(offset == 3))
		{
			if(strlen(qq_last_time) == 0)
			{
				//复制第一条聊天纪录
				strcpy_s(qq_last_time,MAX_PATH,pstr);
				qq_format = TRUE;
				g_getTextDone = FALSE;
				qq_msg_bottom = lprc->bottom;
			}
			else if(strcmp(qq_last_time,pstr) == 0)
			{
				//检测到重复的时间文字证明内容结束
				memset(qq_last_time,0,sizeof(char)*MAX_PATH);
				qq_format = FALSE;
				g_getText = FALSE;
				g_getTextDone = TRUE;
			}
			//写入聊天内容的时间
			if (g_getText)
			{
				//昵称和时间
				//AppendText(pstr);
				//AppendText("-");
			}
		}
		else if(qq_format && g_getText)
		{
			if (qq_msg_bottom < lprc->bottom)
			{
				qq_msg_bottom = lprc->bottom;
				//QQ聊天纪录
				//AppendText(pstr);
				//AppendText("|");
				strcat_s(tempMsg,QQ_MSG_LENGTH,pstr);
			}
		}
		delete[] pstr;
	}
	WriteProcessMemory(INVALID_HANDLE_VALUE, pExtTextOutW, szOldExtTextOutW, 5, NULL);
	bRet = ExtTextOutW(hdc,X,Y,fuOptions,lprc,lpString,cbCount,lpDx);
	WriteProcessMemory(INVALID_HANDLE_VALUE, pExtTextOutW, szJmpMyExtTextOutW, 5, NULL);
	SetEvent(hEvent);//要放在上面,不然无响应,下面的SEND没有完成
	if(g_getTextDone)
	{
		g_getTextDone = FALSE;
		QMsg msg;
		msg.Init(g_hWnd,tempMsg);
		memset(tempMsg,0,QQ_MSG_LENGTH);
		g_msgSender.AddMsg(msg);
		g_msgSender.NotifyThread();//唤醒线程工作
	}
	return bRet; 
}
char* WCharToChar(const wchar_t *wstr)
{
	//第四个参数-1表示求长度
	int _length = WideCharToMultiByte(CP_OEMCP, 0, wstr, -1, NULL, 0, NULL, FALSE);
	char *pstr = new char[_length+1];
	_length = WideCharToMultiByte(CP_OEMCP, 0, wstr, -1, pstr, _length, NULL, FALSE);
	pstr[_length] = 0;
	return pstr;
}
wchar_t* CharToWChar(const char *str)
{
	//第四个参数-1表示求长度
	int _length = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
	wchar_t *pwText = new wchar_t[_length+1];
	_length = MultiByteToWideChar(CP_ACP,0,str,-1,pwText,_length);
	pwText[_length] = 0;
	return pwText;
}
void ResetLog()
{
	DeleteFileA(LOG_NAME);
}
void AppendText(char *text)
{
	char* ptr = (char*) MapViewOfFile(g_hFile,FILE_MAP_ALL_ACCESS,0,0,FILESIZE);
	strcat_s(ptr,FILESIZE,text);
	UnmapViewOfFile(ptr);
}
void WriteLog(char *fmt,...)
{
	char temp[1024];
	HANDLE hFile = CreateFileA(LOG_NAME, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
	if(hFile == NULL)
		return;
	//设置文件中进行读写的当前位置
	_llseek((HFILE)hFile,0, SEEK_END);
	DWORD dw;
	va_list args;
	va_start(args,fmt);
	vsprintf_s(temp,fmt,args);
	va_end(args);
	WriteFile(hFile, temp, strlen(temp), &dw, NULL);
	//将一系列的字符和数值输入到缓冲区
	/*wsprintfA(temp, "\n");
	WriteFile(hFile, temp, strlen(temp), &dw, NULL);*/
	_lclose((HFILE)hFile);
}
void ParseQQMsgTime(char *_time_,QTime *qTime)
{
	//copy会覆盖原来内存,不用使用memset
	char tmp[MAX_PATH];
	strncpy_s(tmp,MAX_PATH,_time_,strlen(_time_));
	char *pSplit = NULL;
	char *pNext = NULL;
	int nCount = 0;
	const char *delim = " ";
	pSplit = strtok_s(tmp,delim,&pNext);
	while(pSplit != NULL)
	{
		nCount++;
		if(nCount == 1)
		{
			strncpy_s(qTime->_name,MAX_PATH,pSplit,strlen(pSplit));
		}
		else if(nCount == 2)
		{
			if(strlen(pNext) == 0)
				strncpy_s(qTime->_time,MAX_PATH,pSplit,strlen(pSplit));
			else
				strncpy_s(qTime->_date,MAX_PATH,pSplit,strlen(pSplit));
		}
		else if(nCount == 3)
		{
			strncpy_s(qTime->_time,MAX_PATH,pSplit,strlen(pSplit));
		}
		pSplit = strtok_s(NULL,delim,&pNext);
	}
}
HANDLE t001(){ExtTextOutA(NULL,0,0,0,NULL,NULL,0,NULL); return (HANDLE)0x12345678;}
HANDLE t002(){TextOutA(NULL,0,0,0,NULL); return (HANDLE)0x23456781;}
HANDLE t003(){TextOutW(NULL,0,0,0,NULL); return (HANDLE)0x34567812;}
HANDLE t004(){SendMessageA(NULL,NULL,NULL,NULL); return (HANDLE)0x45678123;}
HANDLE t005(){SendMessageW(NULL,NULL,NULL,NULL); return (HANDLE)0x56781234;}
HANDLE t006(){::AdjustWindowRect(NULL,0,FALSE); return (HANDLE)0x67812345;}
HANDLE t007(){g_getText = TRUE; return (HANDLE)0x00321263;}
HANDLE t008(){BeginPaint(NULL,NULL); return (HANDLE)0x78123456;}
HANDLE t009(){EndPaint(NULL,NULL); return (HANDLE)0x81234567;}
结构体
#pragma once
#include 
#define QQ_BTN_SEND_X 333
#define QQ_BTN_SEND_Y 500
#define QQ_MSG_LENGTH 10240
struct QQ_Msg
{
	char _recvMsg[QQ_MSG_LENGTH];//接收的信息用于查询最佳回复内容用
	char _sendMsg[QQ_MSG_LENGTH];//用于发送给别人
	HWND _hWnd;
	QQ_Msg()
	{
		_hWnd = NULL;
	}
	void Init(HWND hWnd,char *msg)
	{
		this->_hWnd = hWnd;
		SetMsg(msg);
	}
	void SetMsg(char *msg)
	{
		strcpy_s(_recvMsg,QQ_MSG_LENGTH,msg);
	}
};
typedef QQ_Msg QMsg;
class CQMsgSender
{
public:
	CQMsgSender(void);
	virtual ~CQMsgSender(void);
	static UINT SendMsgThread(LPVOID pVoid);//线程要静态访问权限才行
	void SendMouse(HWND hWnd,WPARAM wParam,LPARAM lParam);
	void SendMsg(HWND hWnd,CHAR *msg);
private:
	bool mRun;
	std::vector g_vmsg;
	HANDLE hSendEvent;
public:
	void StartThread(void);
	void StopThread(void);
	void AddMsg(QMsg _msg);
	void NotifyThread(void);
	LPARAM lParam;
};
#include "StdAfx.h"
#include "QMsgSender.h"

CQMsgSender::CQMsgSender(void)
	: mRun(false)
{
	g_vmsg.reserve(1000);
	lParam = MAKELONG(QQ_BTN_SEND_X,QQ_BTN_SEND_Y);
}

CQMsgSender::~CQMsgSender(void)
{
}

void CQMsgSender::SendMsg(HWND hWnd,CHAR *msg)
{
	int _length = strlen(msg);
	for(int i=0;i<_length;i++)
	{
		WPARAM cChar = (BYTE)msg[i];
		if(cChar > 122)//是占2字节
			cChar = (cChar<<8) | (BYTE)msg[++i];
		SendMessageA(hWnd,WM_IME_CHAR,cChar,NULL);
	}
}
void CQMsgSender::SendMouse(HWND hWnd,WPARAM wParam,LPARAM lParam)
{
	SendMessageA(hWnd,WM_MOUSEMOVE,wParam,lParam);
	SendMessageA(hWnd,WM_LBUTTONDOWN,wParam,lParam);
	SendMessageA(hWnd,WM_LBUTTONUP,wParam,lParam);
	SendMessageA(hWnd,WM_MOUSEMOVE,NULL,MAKELONG(0,0));
}
UINT CQMsgSender::SendMsgThread(LPVOID pVoid)
{
	CQMsgSender *thiz = (CQMsgSender*)pVoid;
	while(thiz->mRun)
	{
		WaitForSingleObject(thiz->hSendEvent,INFINITE);
		if(!thiz->mRun)
			break;//退出线程
		//接收完毕通知关闭窗口
		int _size = thiz->g_vmsg.size();
		for (int i=_size-1;i>=0;i--)
		{
			QMsg msg = thiz->g_vmsg.at(i);
			thiz->g_vmsg.pop_back();
			if(strstr(msg._recvMsg,"你好") != NULL)
			{
				//查找到了回复内容
				strcpy_s(msg._sendMsg,QQ_MSG_LENGTH,"你好,请问有什么可以帮到你的吗?");
			}
			else if(strstr(msg._recvMsg,"在吗") != NULL)
			{
				//查找到了回复内容
				strcpy_s(msg._sendMsg,QQ_MSG_LENGTH,"亲,在的!");
			}
			else
			{
				//查找不到回复内容
				strcpy_s(msg._sendMsg,QQ_MSG_LENGTH,"555,我还不能理解你的意思!");
			}
			thiz->SendMsg(msg._hWnd,msg._sendMsg);
			thiz->SendMouse(msg._hWnd,NULL,thiz->lParam);//发送
			PostMessageA(msg._hWnd,WM_CLOSE,NULL,NULL);
		}
	}
	CloseHandle(thiz->hSendEvent);
	return 0;
}
void CQMsgSender::StartThread(void)
{
	mRun = true;
	hSendEvent = CreateEventA(NULL,FALSE,FALSE,NULL);
	HANDLE threadHandle = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)SendMsgThread,this,0,NULL);
	if(threadHandle != NULL)
		CloseHandle(threadHandle);
}

void CQMsgSender::StopThread(void)
{
	mRun = false;
	SetEvent(hSendEvent);
}
void CQMsgSender::AddMsg(QMsg _msg)
{
	this->g_vmsg.push_back(_msg);
}

void CQMsgSender::NotifyThread(void)
{
	SetEvent(hSendEvent);
}

本文链接:https://www.it72.com/3262.htm

推荐阅读
最新回复 (5)
  • 能不能给一个调用的方法,不知该如何调用咱们这个库程序qq1325670735
  • bsam 2016-7-18
    引用 3
    这个是DLL直接注入的,你看下。先设置目标QQ的句柄。然后取共享内容块。
  • mariMt 2016-8-2
    引用 4
    楼主有源码么? 求一份 谢谢 邮箱 xiangqinin@vip.qq.com
  • DennyLeija 2016-8-3
    引用 5
    源码找不到了。这里已经有核心部分不。可以写出来了。
  • vousetmoi 2016-10-28
    引用 6
    请问可以联系下沟通不?QQ3535515266
返回