CMake+大漠插件的应用开发——处理dm.dll,免注册调用大漠插件

CMake+大漠插件的应用开发——处理dm.dll,免注册调用大漠插件

简介

环境

版本/规范备注
平台win32操作系统为Windows10
CMake3.27.8CLion自带
C++1711也行
ToolchainVisualStudio 2022只用其工具链,记先安装好
DM7.2353大漠插件
CLion2023.3.2你也可以用其他IDE工具
  • 启动IDE时,记得以管理员模式启动

项目结构

  • 新建一个项目 dm_demo
  • 将下载好的 dm.dll 文件放置到项目的 external 目录下
dm_demo					                     # 项目目录
--|cmake-build-debug-visual-studio	         # 工程构建目录,存临时生成的文件
--|--|...
--|external					                 # 引入第三方库文件的所在的文件夹
--|--|dm.dll                                 # 大漠插件的dll
--CMakeLists.txt		                     # CMake脚本文件
--dmutils.cpp                                 # 大漠的功能封装工具
--dmutils.h                                   # 大漠的功能封装工具
--main.cpp					                 # 程序入口

配置编译环境

  • 配置工具链
    • Toolchain: VisualStudio 2022
    • Generator: Use default Ninja

image

image.png

  • CMakeLists.txt 文件
cmake_minimum_required(VERSION 3.27)
project(dm_demo)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /utf-8")

add_executable(dm_demo main.cpp
        dmutils.cpp dmutils.h
)

target_compile_definitions(${PROJECT_NAME} PRIVATE
        -DWIN32
        # -D_DEBUG
        -D_WINDOWS
        -D_UNICODE
        -DUNICODE
)

# 拷贝资源文件 dm.dll
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/external DESTINATION ${CMAKE_CURRENT_BINARY_DIR})

编码-直接调用 dll

  • 首先,新建文件 dmutils.hdmutils.cpp
  • 在 dmutils.h 中使用#import导入dll文件
#import "file:./external/dm.dll" no_namespace

  • 接下来便可以在文件内编写大漠相关的函数调用代码,如下
    • 这种方式能通过编译,以及正常执行生成的程序
    • 但是IDE没有提示,会报红。你需要看着大漠插件的文档写调用的方法。
  • dmutils.h
#ifndef DM_DEMO_X_DMUTIL_H
#define DM_DEMO_X_DMUTIL_H

#import "file:./external/dm.dll" no_namespace

// 设置dm.dll的绝对路径;或者配置相对路径,等下将dm.dll拷贝到生成的执行程序旁
// #define DM_LIB_PATH L"C:/Users/xxx/projects/dm/dm_demo/external/dm.dll"
#define DM_LIB_PATH L"./external/dm.dll"

using namespace std;

/**
 * 注册dm.dll,获取大漠实例
 * @return 大漠实例
 */
Idmsoft *GetDmObject();

/**
 * 初始化大漠插件,并注册用户VIP
 * @return 大漠实例
 */
Idmsoft *initialDMAndRegVIP();

/**
 * 截图
 * @param pDm 大漠实例
 * @param hwnd 窗口句柄
 */
void doCaptureWindow(Idmsoft &pDm, long hwnd);

#endif //DM_DEMO_X_DMUTIL_H
  • dmutils.cpp(记得填入自己的 注册码附加码
#include <iostream>
#include <sstream>
#include "dmutils.h"

using namespace std;

Idmsoft *GetDmObject() {
    Idmsoft *m_dm = nullptr;
    bool m_bInit = false;
    typedef HRESULT(_stdcall
    *pfnGCO)(REFCLSID, REFIID, void**);
    pfnGCO fnGCO = nullptr;
    HINSTANCE hdllInst = LoadLibrary(DM_LIB_PATH);
    if (hdllInst == nullptr) {
        cout << "Load library 'dm.dll' failed ! DM_LIB_PATH = " << DM_LIB_PATH << endl;
        return nullptr;
    }
    fnGCO = (pfnGCO) GetProcAddress(hdllInst, "DllGetClassObject");
    if (fnGCO != nullptr) {
        IClassFactory *pcf = nullptr;
        HRESULT hr = (fnGCO)(__uuidof(dmsoft), IID_IClassFactory, (void **) &pcf);
        if (SUCCEEDED(hr) && (pcf != nullptr)) {
            hr = pcf->CreateInstance(nullptr, __uuidof(Idmsoft), (void **) &m_dm);
            if ((SUCCEEDED(hr) && (m_dm != nullptr)) == FALSE) {
                cout << "Create instance 'Idmsoft' failed !" << endl;
                return nullptr;
            }
        }
        pcf->Release();
        m_bInit = true;
    }
    return m_dm;
}

Idmsoft *initialDMAndRegVIP() {
    Idmsoft *pDm = GetDmObject();
    if (pDm == nullptr) {
        cout << "===> dm.dll registration failed !" << endl;
        return nullptr;
    }
    // 注册dm.dll成功,打印版本
    cout << "===> DM version: " << (char *) pDm->Ver() << endl;
    // 注册用户(同一程序下,只需注册一次,后续不用重复注册)
    long regResult = pDm->Reg(L"注册码", L"版本附加信息(附加码)");
    if (regResult != 1) {
        cout << "===> Account registration failed ! code = " << regResult << endl;
        return nullptr;
    }
    cout << "===> Account registration successful ! " << endl;
    // long releaseRes = pDm->ReleaseRef();
    // cout << "===> ReleaseCode = " << releaseRes << endl;

    return pDm;
}

void doCaptureWindow(Idmsoft &pDm, long hwnd) {
    // 绑定窗口句柄
    long dmBind = pDm.BindWindowEx(
            hwnd,
            "normal",
            "normal",
            "normal",
            "",
            0
    );
    if (dmBind == 1) {
        // 恢复并激活指定窗口,置顶窗口,
        pDm.SetWindowState(hwnd, 12);
        pDm.SetWindowState(hwnd, 8);
        pDm.delay(600);
        // 延迟一下截图,存到相对路径
        wstring filename = wstring(L"./capture_window_").append(std::to_wstring(hwnd)).append(L".bmp");
        long retCap = pDm.Capture(0, 0, 2000, 2000, filename.c_str());
        if (retCap != 1) {
            cout << "capture failed" << endl;
        } else {
            cout << "capture success" << endl;
        }
        // 取消置顶窗口
        pDm.SetWindowState(hwnd, 9);
    } else {
        cout << "DM BindWindow failed" << endl;
    }
    pDm.UnBindWindow();
}
  • main.cpp
#include <iostream>

#include "dmutils.h"

int main() {
    std::cout << "Hello, World!" << std::endl;

    Idmsoft *pDm = initialDMAndRegVIP();

    // 查询标题包含dm的窗口
    _bstr_t hwnds = pDm->EnumWindow(0, L"dm", L"", 1 + 4 + 8 + 16);
    std::cout << (char *)hwnds << std::endl;

    // 对句柄为263684的窗口截图
    doCaptureWindow(*pDm, 263684);

    return 0;
}
  • 直接编译运行即可
    • $ cmake -A win32 -B ./build
    • $ cmake --build build

编码-生成tlh文件,便于提示

  • 前面的方式,虽然能直接调用dll虽然能通过编译和使用,但IDE没有提示,不太方便。
  • 我们可以利用#import生成的 dm.tlhdm.tli文件,便于IDE做提示。
#import "file:./external/dm.dll" no_namespace
// #import "file:./external/dm.dll" no_namespace
#include "./cmake-build-debug-visual-studio/CMakeFiles/dm_demo.dir/dm.tlh"
  • 等一会儿,代码中便不再出现红色的警告,并且调用大漠的方法时也有了提示
  • 现在已经可以正常使用了。
  • 不过为了后续方便其他项目使用(不用每次都用#import处理 dm.dll 文件),我们可以将 dm.tlhdm.tli 文件单独拿出来和 dm.dll 放一起,例如
--|external					     # 引入第三方库文件的所在的文件夹
--|--|dm.dll                     # 大漠插件的dll
--|--|dm.tlh
--|--|dm.tli
  • 另外,需要注意的是:生成的 dm.tlh 文件的最后有对 dm.tli 文件的#include,写的是绝对路径,需要我们改成相对路径,方便以后直接一起拿到其他项目使用
//
// Wrapper method implementations
//

// #include "C:\Users\xxx\projects\dm\dm_demo\cmake-build-debug-visual-studio\CMakeFiles\dm_demo.dir\dm.tli"
#include ".\dm.tli"

#pragma pack(pop)
  • 22
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值