C++/Qt 集成 AutoHotkey

C++/Qt 集成 AutoHotkey

前言

上一篇介绍了AutoHotkey的基本情况和使用,其功能丰富易用,于是搬出我们的老朋友 C++/Qt,将AutoHotkey 集成到 C++/Qt开发环境,使其为我们所用。

AutoHotkey 介绍

上一篇链接: C++ AutoHotkey 开源项目介绍

方案一:子进程启动

上一篇我们介绍了AutoHotkey可以通过命令行启动,于是自然而然的想到了在我们的工程中使用命令行启动AutoHotkey脚本;

编写AutoHotkey脚本

编写一个简单的ahk脚本,如:

cpp 复制代码
MsgBox "hello world!"

准备 AutoHotkey 运行环境

为了方便测试,将需要的依赖和ahk脚本放在了同一路径下,如图:

编写 C++/Qt 代码

创建一个Qt命令行工程用于集成测试,编写代码如下:

cpp 复制代码
#include <QCoreApplication>
#include <QProcess>
#include <QDebug>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    auto executeTerminalCommand = [=](const QString &command)
    {
        QProcess process;
        process.start("cmd", QStringList() << "/c" << command);
        process.waitForStarted();
        process.waitForFinished();

        QString error = QString::fromLocal8Bit( process.readAllStandardError());
        if(!error.isEmpty())
        {
            qDebug() << "error:" + error;
        }

        QString result = QString::fromLocal8Bit( process.readAllStandardOutput() );
        return result;
    };

    executeTerminalCommand("D:/test/AutoHotkey.exe D:/test/hello.ahk");

    return a.exec();
}

以上代码使用QProcess启动cmd,命令行启动了ahk脚本,运行结果如图:

这种方式简单易用,没什么心智负担,但如果你的软件需要分发给其他用户使用,你就必须要打包AutoHotkey.exe 和ahk脚本文件,一眼就被别人看穿的感觉并不愉快,于是我们继续探索其它方案。

方案二:显式动态链接

方案探索

在AutoHotkey项目的README中,看到如下内容:

字面意思不太易于理解,进入 README-LIB.md 链接中继续寻找,发现其并不是所预期的编译为动态库供其它软件链接,而是在ahk中启用另一个ahk以在V2版本的ahk中启用V1版本功能等等,但文档中发现了有趣的线索:

进入 HotKeyIt/ahkdll 链接,查看项目简介:

说明了"为其它编程语言、脚本语言打开了AutoHotkey的世界",正是我们的需求,话不多说,开始验证;

编译动态链接库

下载ahkdll源码到本地,解压后如图:

可以看出是visual studio的工程,不折腾直接使用vs构建;vs打开工程文件(这里我使用的是vs2019),配置切换为releaseDll、x64,右键AutoHotkey项目,点击生成:


在项目的bin/x64w 下,找到了AutoHotkeyDLL.dll:

集成到C++工程

妥善安置 AutoHotkeyDll.dll,编写代码如下(注意动态库路径):

cpp 复制代码
#include <Windows.h>
#include <winuser.h>
#include <iostream>
#include <libloaderapi.h>
#include <comdef.h>

using namespace std;

LPTSTR strToLPTSTR(string str)
{
    _bstr_t bstr(str.c_str());
    return (LPTSTR)bstr;
}

int main()
{
    typedef BOOL (*AhkReady)(void);
    typedef BOOL (*AhkExec)(LPTSTR script);
    typedef UINT_PTR (*AhkDll)(LPTSTR script,LPTSTR p1,LPTSTR p2);

    HINSTANCE handle = LoadLibrary(L"D:\\test\\AutoHotkeyDLL.dll");
    AhkDll ahkdll = (AhkDll)GetProcAddress(handle, "ahkdll");

    AhkReady ahkReady = (AhkReady)GetProcAddress(handle, "ahkReady");
    AhkExec ahkExec = (AhkExec)GetProcAddress(handle, "ahkExec");

    LPTSTR empty = strToLPTSTR("");
    ahkdll(empty, empty, empty);

    ahkReady();

    string script = "MsgBox \"hello world!\"";
    ahkExec(strToLPTSTR(script));

    return 0 ;
}

以上代码显式链接AutoHotkeyDll.dll,定义函数指针调用函数,在程序中以字符串的形式运行ahk脚本,运行结果如图:

关于AutoHotkeyDll.dll中的函数原型

函数原型来自于 ahkdll 项目中 source 文件夹下的 exports.h,如 ahkExec 函数:

总结

两种方案都可方便的将AutoHotkey集成到其它编程语言中,命令行启动、显式动态链接并不是 c++ 或 Qt 的特性,利用AutoHotkey丰富易用的功能及多年积累下的生态,我们可以开发出更多有用的功能。

相关推荐
闻缺陷则喜何志丹6 分钟前
【贪心 字典序 回文 最长公共前缀】LeetCode3734. 大于目标字符串的最小字典序回文排列|分数未知
c++·算法·力扣·贪心·字典序·回文·最长公共前缀
tung tung tung sahur14 分钟前
领略 Rust 抽象之美:自定义迭代器实现全解析
开发语言·后端·rust
ftpeak20 分钟前
《Rust MP4视频技术开发》第八章:生成MP4
开发语言·rust·音视频·mp4
好学且牛逼的马41 分钟前
【SSM框架 | day25 spring IOC 与 DI 注解开发】
java·开发语言
_OP_CHEN1 小时前
C++进阶:(四)set系列容器的全面指南
开发语言·c++·stl·set·multiset·关联式容器·setoj题
不惑_1 小时前
Java 使用 FileOutputStream 写 Excel 文件不落盘?
开发语言·python
十五年专注C++开发1 小时前
Qt-VLC: 一个集成VLC的开源跨平台媒体播放库
开发语言·qt·媒体·libvlc·vlc-qt
郝学胜-神的一滴2 小时前
128天写作之旅:记录与成长的点滴
开发语言·程序人生
superman超哥2 小时前
仓颉语言中流式I/O的设计模式深度剖析
开发语言·后端·设计模式·仓颉
豆浆whisky2 小时前
Go内存管理最佳实践:提升性能的Do‘s与Don‘ts|Go语言进阶(17)
开发语言·后端·golang