[C++实战qqHelper]C++打造qq消息一键群发工具

物联网时代,微信和qq带给我们生活诸多便利。如今办公学习交流通讯已经越来越离不开微信和qq了。但是目前仍存在一些缺陷,比如如果想某条消息发给全部好友,必须得一个一个的发送。尤其是节假日发送节日祝福时该缺陷越发明显。微信针对此现象推出了群发功能,但qq目前还没有该功能。因此此次借此小程序练习C++,用C++打造qq聊天一键群发功能。该小程序还在完善中。目前只能作用于电脑Windows操作系统,并且电脑聊天界面发送按钮需切换到按Enter直接发送,不要选择Ctrl+Enter。当前仅有发送功能,因此消息的对象是所有好友。之后有时间会陆续添加暂停,继续等操作。

具体代码以及实现过程在代码中逐条说明。这里就不具体说明了。

QQmessage.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#pragma once
class QQmessage
{
public:
QQmessage();
~QQmessage();

//类的入口
static QQmessage *Instance()
{
static QQmessage object;

return &object;
}

//入口函数
void Start(const wchar_t *msg);

private:
//开始线程
static unsigned int WINAPI RunThreadproc(void* param);

//发送主函数
void SendAll();

//找到QQ窗口
HWND FindQQWindow();

//模拟按键
void PressKey(BYTE vkey);

//发送消息
void SendMsg();

//添加文本到剪贴板
void AddTextToClipboard();

private:
CString m_msg;
};

QQmessage.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#include "stdafx.h"
#include "QQmessage.h"

QQmessage::QQmessage()
{
}

QQmessage::~QQmessage()
{
}

//入口函数
void QQmessage::Start(const wchar_t *msg)
{
m_msg = CString(msg); //输入的文本

_beginthreadex(NULL, 0, QQmessage::RunThreadproc, NULL, 0, NULL);
}

//开始线程
unsigned int QQmessage::RunThreadproc(void* param)
{
QQmessage::Instance()->SendAll();
return 0;
}

//发送主函数
void QQmessage::SendAll()
{
int errorTimes = 0; //打开对话框错误的次数!
//把text复制到剪贴板
AddTextToClipboard();

//技术到家. 做项目能力.
while (errorTimes<= 4)
{
HWND hQQWnd = FindQQWindow();
HWND hFrontWnd = GetForegroundWindow();

if (hQQWnd != hFrontWnd)
{
if (!SetForegroundWindow(hQQWnd))
{
MessageBox(NULL, L"没有找到QQ窗口", NULL, NULL);
break;
}
}
if (errorTimes == 0)
{
PressKey(VK_TAB);
PressKey(VK_TAB);
}
PressKey(VK_DOWN);
PressKey(VK_RETURN);

HWND hCurFrontWnd = GetForegroundWindow();
if (hCurFrontWnd == hQQWnd) //
{
++errorTimes;
continue;
}

errorTimes = 0;
SendMsg();
}
}

//找到QQ窗口
HWND QQmessage::FindQQWindow()
{
HWND hWnd = FindWindow(L"TXGuiFoundation",L"QQ"); //Find Window //获取QQ的窗口!!!

//辅助工具就是这么做的
return hWnd;
}

//模拟按键
void QQmessage::PressKey(BYTE vkey)
{
keybd_event(vkey, 0, 0, 0); //按下(0)和弹起(KEYEVENTF_KEYUP)
Sleep(100);
keybd_event(vkey, 0, KEYEVENTF_KEYUP, 0); //敲击TAB
Sleep(100);
}

//发送消息 16GU盘
void QQmessage::SendMsg()
{
//粘贴 + 发送
keybd_event(VK_CONTROL, 0, 0, 0); //按下(0)和弹起(KEYEVENTF_KEYUP)
Sleep(100);
keybd_event(0x56, 0, 0, 0); //按下(0)和弹起(KEYEVENTF_KEYUP)
Sleep(100);

keybd_event(0x56, 0, KEYEVENTF_KEYUP, 0); //敲击TAB
Sleep(100);
keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0); //敲击TAB
Sleep(100); //你好 鲜花刷起来!

//发送
PressKey(VK_RETURN);
PressKey(VK_ESCAPE);
}

//添加文本到剪贴板
void QQmessage::AddTextToClipboard()
{
//1.把文本拷贝到全局变量!
int memLen = m_msg.GetLength() * sizeof(wchar_t) + 2;

HANDLE hGloBal = GlobalAlloc(GHND,memLen); //malloc calloc relloc

void* memAddr = GlobalLock(hGloBal);

ZeroMemory(memAddr, memLen);

memcpy(memAddr, (const void*)m_msg.GetBuffer(), memLen);

GlobalUnlock(hGloBal);

//操作剪贴板! 怎么把大象装进冰箱!
OpenClipboard(NULL);
EmptyClipboard();
SetClipboardData(CF_UNICODETEXT, hGloBal);
CloseClipboard();
}

QQHelperDlg.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

// QQHelperDlg.h : 头文件
//

#pragma once


// CQQHelperDlg 对话框
class CQQHelperDlg : public CDialogEx
{
// 构造
public:
CQQHelperDlg(CWnd* pParent = NULL); // 标准构造函数

// 对话框数据
#ifdef AFX_DESIGN_TIME
enum { IDD = IDD_QQHELPER_DIALOG };
#endif

protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持


// 实现
protected:
HICON m_hIcon;

// 生成的消息映射函数
virtual BOOL OnInitDialog();
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
DECLARE_MESSAGE_MAP()
public:
CString m_Msg;
afx_msg void OnBnClickedButton1();
};

QQHelperDlg.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167

// QQHelperDlg.cpp : 实现文件
//

#include "stdafx.h"
#include "QQHelper.h"
#include "QQHelperDlg.h"
#include "afxdialogex.h"
#include "QQmessage.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// 用于应用程序“关于”菜单项的 CAboutDlg 对话框

class CAboutDlg : public CDialogEx
{
public:
CAboutDlg();

// 对话框数据
#ifdef AFX_DESIGN_TIME
enum { IDD = IDD_ABOUTBOX };
#endif

protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持

// 实现
protected:
DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialogEx(IDD_ABOUTBOX)
{
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()


// CQQHelperDlg 对话框



CQQHelperDlg::CQQHelperDlg(CWnd* pParent /*=NULL*/)
: CDialogEx(IDD_QQHELPER_DIALOG, pParent)
, m_Msg(_T(""))
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CQQHelperDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Text(pDX, IDC_EDIT1, m_Msg);
}

BEGIN_MESSAGE_MAP(CQQHelperDlg, CDialogEx)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_BUTTON1, &CQQHelperDlg::OnBnClickedButton1)
END_MESSAGE_MAP()


// CQQHelperDlg 消息处理程序

BOOL CQQHelperDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();

// 将“关于...”菜单项添加到系统菜单中。

// IDM_ABOUTBOX 必须在系统命令范围内。
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);

CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
BOOL bNameValid;
CString strAboutMenu;
bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
ASSERT(bNameValid);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}

// 设置此对话框的图标。 当应用程序主窗口不是对话框时,框架将自动
// 执行此操作
SetIcon(m_hIcon, TRUE); // 设置大图标
SetIcon(m_hIcon, FALSE); // 设置小图标

// TODO: 在此添加额外的初始化代码

return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
}

void CQQHelperDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialogEx::OnSysCommand(nID, lParam);
}
}

// 如果向对话框添加最小化按钮,则需要下面的代码
// 来绘制该图标。 对于使用文档/视图模型的 MFC 应用程序,
// 这将由框架自动完成。

void CQQHelperDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // 用于绘制的设备上下文

SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

// 使图标在工作区矩形中居中
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;

// 绘制图标
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialogEx::OnPaint();
}
}

//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CQQHelperDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}


//发送
void CQQHelperDlg::OnBnClickedButton1()
{
// TODO: 在此添加控件通知处理程序代码
UpdateData(TRUE);

QQmessage::Instance()->Start(m_Msg.GetBuffer());//m_Msg实例编辑框的变量 文字
}

QQHelper.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

// QQHelper.h : PROJECT_NAME 应用程序的主头文件
//

#pragma once

#ifndef __AFXWIN_H__
#error "在包含此文件之前包含“stdafx.h”以生成 PCH 文件"
#endif

#include "resource.h" // 主符号


// CQQHelperApp:
// 有关此类的实现,请参阅 QQHelper.cpp
//

class CQQHelperApp : public CWinApp
{
public:
CQQHelperApp();

// 重写
public:
virtual BOOL InitInstance();

// 实现

DECLARE_MESSAGE_MAP()
};

extern CQQHelperApp theApp;

QQHelper.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105

// QQHelper.cpp : 定义应用程序的类行为。
//

#include "stdafx.h"
#include "QQHelper.h"
#include "QQHelperDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// CQQHelperApp

BEGIN_MESSAGE_MAP(CQQHelperApp, CWinApp)
ON_COMMAND(ID_HELP, &CWinApp::OnHelp)
END_MESSAGE_MAP()


// CQQHelperApp 构造

CQQHelperApp::CQQHelperApp()
{
// 支持重新启动管理器
m_dwRestartManagerSupportFlags = AFX_RESTART_MANAGER_SUPPORT_RESTART;

// TODO: 在此处添加构造代码,
// 将所有重要的初始化放置在 InitInstance 中
}


// 唯一的一个 CQQHelperApp 对象

CQQHelperApp theApp;


// CQQHelperApp 初始化

BOOL CQQHelperApp::InitInstance()
{
// 如果一个运行在 Windows XP 上的应用程序清单指定要
// 使用 ComCtl32.dll 版本 6 或更高版本来启用可视化方式,
//则需要 InitCommonControlsEx()。 否则,将无法创建窗口。
INITCOMMONCONTROLSEX InitCtrls;
InitCtrls.dwSize = sizeof(InitCtrls);
// 将它设置为包括所有要在应用程序中使用的
// 公共控件类。
InitCtrls.dwICC = ICC_WIN95_CLASSES;
InitCommonControlsEx(&InitCtrls);

CWinApp::InitInstance();


AfxEnableControlContainer();

// 创建 shell 管理器,以防对话框包含
// 任何 shell 树视图控件或 shell 列表视图控件。
CShellManager *pShellManager = new CShellManager;

// 激活“Windows Native”视觉管理器,以便在 MFC 控件中启用主题
CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows));

// 标准初始化
// 如果未使用这些功能并希望减小
// 最终可执行文件的大小,则应移除下列
// 不需要的特定初始化例程
// 更改用于存储设置的注册表项
// TODO: 应适当修改该字符串,
// 例如修改为公司或组织名
SetRegistryKey(_T("应用程序向导生成的本地应用程序"));

CQQHelperDlg dlg;
m_pMainWnd = &dlg;
INT_PTR nResponse = dlg.DoModal();
if (nResponse == IDOK)
{
// TODO: 在此放置处理何时用
// “确定”来关闭对话框的代码
}
else if (nResponse == IDCANCEL)
{
// TODO: 在此放置处理何时用
// “取消”来关闭对话框的代码
}
else if (nResponse == -1)
{
TRACE(traceAppMsg, 0, "警告: 对话框创建失败,应用程序将意外终止。\n");
TRACE(traceAppMsg, 0, "警告: 如果您在对话框上使用 MFC 控件,则无法 #define _AFX_NO_MFC_CONTROLS_IN_DIALOGS。\n");
}

// 删除上面创建的 shell 管理器。
if (pShellManager != NULL)
{
delete pShellManager;
}

#ifndef _AFXDLL
ControlBarCleanUp();
#endif

// 由于对话框已关闭,所以将返回 FALSE 以便退出应用程序,
// 而不是启动应用程序的消息泵。
return FALSE;
}

stdafx.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
// stdafx.h : 标准系统包含文件的包含文件,
// 或是经常使用但不常更改的
// 特定于项目的包含文件

#pragma once

#ifndef VC_EXTRALEAN
#define VC_EXTRALEAN // 从 Windows 头中排除极少使用的资料
#endif

#include "targetver.h"

#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // 某些 CString 构造函数将是显式的

// 关闭 MFC 对某些常见但经常可放心忽略的警告消息的隐藏
#define _AFX_ALL_WARNINGS

#include <afxwin.h> // MFC 核心组件和标准组件
#include <afxext.h> // MFC 扩展


#include <afxdisp.h> // MFC 自动化类


#ifndef _AFX_NO_OLE_SUPPORT
#include <afxdtctl.h> // MFC 对 Internet Explorer 4 公共控件的支持
#endif
#ifndef _AFX_NO_AFXCMN_SUPPORT
#include <afxcmn.h> // MFC 对 Windows 公共控件的支持
#endif // _AFX_NO_AFXCMN_SUPPORT

#include <afxcontrolbars.h> // 功能区和控件条的 MFC 支持


#ifdef _UNICODE
#if defined _M_IX86
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"")
#elif defined _M_X64
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"")
#else
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
#endif
#endif

stdafx.cpp

1
2
3
4
5
6

// stdafx.cpp : 只包括标准包含文件的源文件
// QQHelper.pch 将作为预编译头
// stdafx.obj 将包含预编译类型信息

#include "stdafx.h"

Resource.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ 生成的包含文件。
// 供 QQHelper.rc 使用
//
#define IDM_ABOUTBOX 0x0010
#define IDD_ABOUTBOX 100
#define IDS_ABOUTBOX 101
#define IDD_QQHELPER_DIALOG 102
#define IDR_MAINFRAME 128
#define IDC_EDIT1 1000
#define IDC_BUTTON1 1001

// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 130
#define _APS_NEXT_COMMAND_VALUE 32771
#define _APS_NEXT_CONTROL_VALUE 1002
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

targetver.h

1
2
3
4
5
6
7
8
#pragma once

// 包括 SDKDDKVer.h 将定义可用的最高版本的 Windows 平台。

// 如果要为以前的 Windows 平台生成应用程序,请包括 WinSDKVer.h,并将
// 将 _WIN32_WINNT 宏设置为要支持的平台,然后再包括 SDKDDKVer.h。

#include <SDKDDKVer.h>

资源文件


文章结束了,但我们的故事还在继续
坚持原创技术分享,您的支持将鼓励我继续创作!