[CoolQ开发] VC开发基本使用方法 附示例代码(重复你说的话)

发布于 27 天前  74 次阅读


CoolQ官方放出的VC开发只给了SDK和简单的注释,这导致很多初学者看到这非常懵逼。。。我正好开始学习使用VC++制作CoolQ的插件,顺便放上我的学习经验和教程。如果您在阅读文章的过程中有任何疑问或建议,欢迎在底下的评论框中留言哦!由于我也是初学,我会从最基础的开始讲,一起学习一起进步吧!如果文章有任何不正确的解释请各位大佬及时帮助修正,感谢感谢!
正文开始啦~~~

下载SDK和配置开发环境

这个不用我多说了,官方文档中都有十分详细的了。为了方便直接点开这篇文章的朋友,我放上一个官方提供的Demo的GitHub地址,估计也算是SDK吧。。。(地址在这里)
至于开发环境,使用VisualStudio任意版本均可的哦!这个你们自己去Microsoft官网下载Communicate版本吧,毕竟免费的就不赘述了。

SDK文件内容概述

CQPdemo.sln - 示例项目,可以直接在此基础上编写应用

您可以编译为 com.example.democ.dll,与 CQPdemo/com.example.democ.json 一起放置在 酷Q 的 app 目录下测试

CQPdemo/com.example.democ.json - 样例应用的对应信息文件,包含应用的基础信息、事件列表等,请放置在 酷Q 的 app 目录下(无需使用的事件、菜单、权限请在此删除)

CQPdemo/cqp.h - 酷Q SDK 头文件,通常无需修改

CQPdemo/CQP.lib - CQP.dll 的动态连接 .lib 文件,便于 C、C++ 等调用 酷Q 的方法。

扫雷(很多人掉的坑)

一定要开启开发者模式,否则编译的dll库不会被载入;
程序里的appid、dll文件名、json文件名一定要一致,否则载入失败。
每次编译、更新dll之后都要重启酷Q,否则加载的还是原来的库,新增功能不生效。

开启开发者模式

打开酷Q目录下的 conf\CQP.cfg 文件,并在文件末尾插入以下两行,即可开启开发者模式。

您可以使用“Notepad++”、“记事本”等文本编辑器编辑本文件。
如果本文件不存在,您可以先启动一次 酷Q,本文件将自动被生成。
[Debug]
DeveloperMode=1
开启开发者模式后,酷Q将新增以下功能,帮助您进行开发:

错误信息将会详细显示。
支持载入、打包未打包应用。(开启开发者模式后才能载入开发中的应用)
在应用窗口,按住shift并单击“重启酷Q”,可以快速重载应用(而无需重启)。

以上内容转自官方,我觉得不用多说什么了。。。毕竟这玩意真的没啥功能没啥好说的了

先讲讲打包应用

正好翻到官方文档,先讲讲打包应用,由于编译出来生成的是DLL文件,所以你们编译完自动运行的同学会收到“无法启动xxx不是有效的Win32程序”之类的错误,不要慌,在Release文件夹里面就可以找到编译出来的dll文件了,把dll文件和根目录的json文件一起放进CoolQ的app目录下(记得开启开发者模式),然后在应用管理里面开启应用就可以了。
但是,这并不是一个发行版本,毕竟不能让每一个人都为了你这个软件去开启开发者模式吧。。。所以我们需要打包你开发的插件

开发完成后,您可以打包应用,将应用与他人分享。

阅读 Pro/开发/基础信息,编辑应用的 .json 文件及 .dll 的文件名,修改 appid、应用名称、应用作者等信息。
在 .json 文件中,移除不必要的菜单、权限。
启动酷Q,悬浮窗右键->应用->应用目录->应用管理,选中你的应用,点击右下角的开发按钮,选择打包。
将生成的 cpk 文件发布到 应用发布 板块,与社群分享您开发的应用吧!
继续转官方文档,这玩意真心没啥好说的。。。

技术活开始的操作

首先,打开sln文件,在Source Files下又一个appmain.cpp文件,这个文件就是我们开发的插件的主要源代码文件了。由于这个SDK真心槽点满满,所以要想知道这玩意怎么用真心需要好好翻阅一下header Files中的注释来看懂他了。

详细的文件解释-appmain.h

我按字母表顺序说明一下每个文件的用途
首先打开Header Files目录,其中appmain.h中主要记载的是app的识别信息,有安卓开发经验的朋友就会知道每个包都有一个包名用作识别,这个CQAPPID和安卓的管理机制很相似,不能与其他插件的APPID相同,如果某用户装了两个一模一样的包名的插件,CoolQ就会报错了咯。(就是那个com.example.democ这玩意,可以随便修改)
关于APPID的建议:可以按照安卓的使用方法,例如你的网站或者企业名字是 geekdt.com 那么你开发了一个叫做123的插件,APPID就叫做com.geekdt.123 就是网站倒着写然后加上.插件名 没个人网站的个人开发者可以尝试com.昵称或用户名.插件名 依照这样一个规范就能非常有效的避免出现上述APPID相同的尴尬现象。
其实官方对此也有很详细的解释,了解更多详情请访问官网(链接在这里)

详细的文件解释-cqp.h

还是在Header Files目录,cqp.h详细记载了我们能用到的酷Q调用方法,这就是CoolQ在很多地方写的所谓的“调用酷Q方法发送或处理”,这个在之后的插件开发中会遇到
看到文件中写的CQAPI......这行了吗,上面有详细(应该详细吧)的注释,我以发送私聊消息为例来解释一下使用方法,在后面我会以实际代码来解释每一条的用法,这里只做简单介绍。
首先,我们实际能用到的部分只有这些:CQ_sendPrivateMsg(int32_t AuthCode, int64_t QQID, const char *msg);
这段是拿来看的,或者拿来改的,在appmain.cpp文件中可以直接把它当一个函数来用,填写参数即可使用
例如我可以写CQ_sendPrivateMsg(ac, qq号写着, 消息写这);来发送一条消息。
完整示例:CQ_sendPrivateMsg(ac, 1040898055, "有人刚刚说了一句话");
但是这里一定一定切记要注意各种参数的类型,我表示掉进这个坑好几次了,数据类型一错CoolQ直接崩掉了,再此建议初学者一定要写一个功能测试一下,以免出现打断代码排查错误,毕竟CoolQ查错步骤真心挺多的哎。。。

详细的文件解释-appmain.cpp

这个是主要的源代码的地方,肯定要多讲几句,由于stdafx.h和targetver.h两个文件真心没啥用(至少暂时我这么觉得),就暂时先不讲,毕竟我们现将基础的快速入门先。
打开这个文件,可以看到有很多个Type的注释,这是每一个事件请求,当收到一个事件请求,例如私聊消息的事件请求的时候,就会触发一个相对应的Type的CQEVENT,在这个EVENT中可以写下收到这个事件请求时候做出的动作。例如本文以sendback为例,声明了一个sendback函数,把这个函数需要的条件返回一下,例如我需要返回QQ号和对方发送的消息,可以直接写sendback(fromQQ, msg); 然后再协商sendback函数的详细操作
void sendback(int64_t fromQQ,const char *msg)<br /> {<br /> char head[6000] = "你刚才说:";//有人问为什么我数组大小写6000,因为QQ消息有最大限制字数,所以这个值一定要超过或等于最大限制字数,否则会出错这个大家都懂。。。比如内存不可写之类的奇奇怪怪的现象,我们都懂,不多加赘述<br /> strcat(head, msg);//把“你刚才说:”和对方发的消息连接在同一个字符数组中<br /> const char *fullbackMessage = (char*)head;//转类型,这就是我掉的坑。。。类型一定要转啊!!!要不这玩意崩溃了没给你错误信息的<br /> CQ_sendPrivateMsg(ac, fromQQ, fullbackMessage);//这个在讲cqp.h里面讲过了。。。下面我复制过来有需要的同学对照看一下<br /> }
首先,我们实际能用到的部分只有这些:CQ_sendPrivateMsg(int32_t AuthCode, int64_t QQID, const char *msg);
这段是拿来看的,或者拿来改的,在appmain.cpp文件中可以直接把它当一个函数来用,填写参数即可使用
例如我可以写CQ_sendPrivateMsg(ac, qq号写着, 消息写这);来发送一条消息。
完整示例:CQ_sendPrivateMsg(ac, 1040898055, "有人刚刚说了一句话");
但是这里一定一定切记要注意各种参数的类型,我表示掉进这个坑好几次了,数据类型一错CoolQ直接崩掉了,再此建议初学者一定要写一个功能测试一下,以免出现打断代码排查错误,毕竟CoolQ查错步骤真心挺多的哎。。。

完整的源代码

因为我其他文件都没改,只改了appmain.cpp,所以只放上这个文件咯,其他的和SDK默认文件一样的哎。。。
由于写的功能十分简单,没写注释了。。。重难点也都在文章中写出来了,有任何不懂或者不理解的同学再下方评论处写下你的疑问哦!

/*
* CoolQ Demo for VC++ 
* Api Version 9
* Written by Coxxs & Thanks for the help of orzFly
*/

#include "stdafx.h"
#include "string"
#include "cqp.h"
#include "appmain.h" //应用AppID等信息,请正确填写,否则酷Q可能无法加载

using namespace std;

int ac = -1; //AuthCode 调用酷Q的方法时需要用到
bool enabled = false;

//Function
void sendback(int64_t fromQQ, const char *msg);


/* 
* 返回应用的ApiVer、Appid,打包后将不会调用
*/
CQEVENT(const char*, AppInfo, 0)() {
    return CQAPPINFO;
}


/* 
* 接收应用AuthCode,酷Q读取应用信息后,如果接受该应用,将会调用这个函数并传递AuthCode。
* 不要在本函数处理其他任何代码,以免发生异常情况。如需执行初始化代码请在Startup事件中执行(Type=1001)。
*/
CQEVENT(int32_t, Initialize, 4)(int32_t AuthCode) {
    ac = AuthCode;
    return 0;
}


/*
* Type=1001 酷Q启动
* 无论本应用是否被启用,本函数都会在酷Q启动后执行一次,请在这里执行应用初始化代码。
* 如非必要,不建议在这里加载窗口。(可以添加菜单,让用户手动打开窗口)
*/
CQEVENT(int32_t, __eventStartup, 0)() {

    return 0;
}


/*
* Type=1002 酷Q退出
* 无论本应用是否被启用,本函数都会在酷Q退出前执行一次,请在这里执行插件关闭代码。
* 本函数调用完毕后,酷Q将很快关闭,请不要再通过线程等方式执行其他代码。
*/
CQEVENT(int32_t, __eventExit, 0)() {

    return 0;
}

/*
* Type=1003 应用已被启用
* 当应用被启用后,将收到此事件。
* 如果酷Q载入时应用已被启用,则在_eventStartup(Type=1001,酷Q启动)被调用后,本函数也将被调用一次。
* 如非必要,不建议在这里加载窗口。(可以添加菜单,让用户手动打开窗口)
*/
CQEVENT(int32_t, __eventEnable, 0)() {
    enabled = true;
    return 0;
}


/*
* Type=1004 应用将被停用
* 当应用被停用前,将收到此事件。
* 如果酷Q载入时应用已被停用,则本函数*不会*被调用。
* 无论本应用是否被启用,酷Q关闭前本函数都*不会*被调用。
*/
CQEVENT(int32_t, __eventDisable, 0)() {
    enabled = false;
    return 0;
}


/*
* Type=21 私聊消息
* subType 子类型,11/来自好友 1/来自在线状态 2/来自群 3/来自讨论组
*/
CQEVENT(int32_t, __eventPrivateMsg, 24)(int32_t subType, int32_t sendTime, int64_t fromQQ, const char *msg, int32_t font) {

    //如果要回复消息,请调用酷Q方法发送,并且这里 return EVENT_BLOCK - 截断本条消息,不再继续处理  注意:应用优先级设置为"最高"(10000)时,不得使用本返回值
    //如果不回复消息,交由之后的应用/过滤器处理,这里 return EVENT_IGNORE - 忽略本条消息
    sendback(fromQQ, msg);
    return EVENT_BLOCK;
}


/*
* Type=2 群消息
*/
CQEVENT(int32_t, __eventGroupMsg, 36)(int32_t subType, int32_t sendTime, int64_t fromGroup, int64_t fromQQ, const char *fromAnonymous, const char *msg, int32_t font) {

    return EVENT_IGNORE; //关于返回值说明, 见“_eventPrivateMsg”函数
}


/*
* Type=4 讨论组消息
*/
CQEVENT(int32_t, __eventDiscussMsg, 32)(int32_t subType, int32_t sendTime, int64_t fromDiscuss, int64_t fromQQ, const char *msg, int32_t font) {

    return EVENT_IGNORE; //关于返回值说明, 见“_eventPrivateMsg”函数
}


/*
* Type=101 群事件-管理员变动
* subType 子类型,1/被取消管理员 2/被设置管理员
*/
CQEVENT(int32_t, __eventSystem_GroupAdmin, 24)(int32_t subType, int32_t sendTime, int64_t fromGroup, int64_t beingOperateQQ) {

    return EVENT_IGNORE; //关于返回值说明, 见“_eventPrivateMsg”函数
}


/*
* Type=102 群事件-群成员减少
* subType 子类型,1/群员离开 2/群员被踢 3/自己(即登录号)被踢
* fromQQ 操作者QQ(仅subType为2、3时存在)
* beingOperateQQ 被操作QQ
*/
CQEVENT(int32_t, __eventSystem_GroupMemberDecrease, 32)(int32_t subType, int32_t sendTime, int64_t fromGroup, int64_t fromQQ, int64_t beingOperateQQ) {

    return EVENT_IGNORE; //关于返回值说明, 见“_eventPrivateMsg”函数
}


/*
* Type=103 群事件-群成员增加
* subType 子类型,1/管理员已同意 2/管理员邀请
* fromQQ 操作者QQ(即管理员QQ)
* beingOperateQQ 被操作QQ(即加群的QQ)
*/
CQEVENT(int32_t, __eventSystem_GroupMemberIncrease, 32)(int32_t subType, int32_t sendTime, int64_t fromGroup, int64_t fromQQ, int64_t beingOperateQQ) {

    return EVENT_IGNORE; //关于返回值说明, 见“_eventPrivateMsg”函数
}


/*
* Type=201 好友事件-好友已添加
*/
CQEVENT(int32_t, __eventFriend_Add, 16)(int32_t subType, int32_t sendTime, int64_t fromQQ) {

    return EVENT_IGNORE; //关于返回值说明, 见“_eventPrivateMsg”函数
}


/*
* Type=301 请求-好友添加
* msg 附言
* responseFlag 反馈标识(处理请求用)
*/
CQEVENT(int32_t, __eventRequest_AddFriend, 24)(int32_t subType, int32_t sendTime, int64_t fromQQ, const char *msg, const char *responseFlag) {

    //CQ_setFriendAddRequest(ac, responseFlag, REQUEST_ALLOW, "");

    return EVENT_IGNORE; //关于返回值说明, 见“_eventPrivateMsg”函数
}


/*
* Type=302 请求-群添加
* subType 子类型,1/他人申请入群 2/自己(即登录号)受邀入群
* msg 附言
* responseFlag 反馈标识(处理请求用)
*/
CQEVENT(int32_t, __eventRequest_AddGroup, 32)(int32_t subType, int32_t sendTime, int64_t fromGroup, int64_t fromQQ, const char *msg, const char *responseFlag) {

    //if (subType == 1) {
    //  CQ_setGroupAddRequestV2(ac, responseFlag, REQUEST_GROUPADD, REQUEST_ALLOW, "");
    //} else if (subType == 2) {
    //  CQ_setGroupAddRequestV2(ac, responseFlag, REQUEST_GROUPINVITE, REQUEST_ALLOW, "");
    //}

    return EVENT_IGNORE; //关于返回值说明, 见“_eventPrivateMsg”函数
}

/*
* 菜单,可在 .json 文件中设置菜单数目、函数名
* 如果不使用菜单,请在 .json 及此处删除无用菜单
*/
CQEVENT(int32_t, __menuA, 0)() {
    MessageBoxA(NULL, "这是menuA,在这里载入窗口,或者进行其他工作。", "" ,0);
    return 0;
}

CQEVENT(int32_t, __menuB, 0)() {
    MessageBoxA(NULL, "这是menuB,在这里载入窗口,或者进行其他工作。", "" ,0);
    return 0;
}
void sendback(int64_t fromQQ,const char *msg)
{
    char head[6000] = "你刚才说:";
    strcat(head, msg);
    const char *fullbackMessage = (char*)head;
    CQ_sendPrivateMsg(ac, fromQQ, fullbackMessage);
}

全文完:)


Hope to be a free geek forever.