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

2024-01-13 02:44

本文主要是介绍CMake+大漠插件的应用开发——处理dm.dll,免注册调用大漠插件,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • CMake+大漠插件的应用开发——处理dm.dll,免注册调用大漠插件
    • 说明
    • 环境
    • 项目结构
    • 配置编译环境
    • 编码-直接调用 dll
    • 编码-生成tlh文件,便于提示

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

说明

  • 网上有一种使用方式是:利用QTdumpcpp.exe工具对dm.dll处理,生成xxx.hxxx.cpp文件再使用。
  • 不过我发现这种使用时有些问题,同时生成的文件也不太通用(只能QT用),所以换了另一种方式。
  • 方法参考自 Visual C++免注册调用大漠插件-CSDN博客

环境

版本/规范备注
平台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脚本文件
--dmutil.cpp                                 # 大漠的功能封装工具
--dmutil.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.cppdmutil.cpp dmutil.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
  • 使用#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 "dmutil.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 "dmutil.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;
}
  • 直接编译运行即可

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

  • 前面的方式,虽然能直接调用dll虽然能通过编译和使用,但IDE没有提示,不太方便。
  • 我们可以利用#import生成的 dm.tlhdm.tli文件,便于IDE做提示。
#import "file:./external/dm.dll" no_namespace
  • 说明:大漠插件是COM组件
    • https://blog.csdn.net/qq_36633275/article/details/108442867
    • https://learn.microsoft.com/zh-cn/cpp/preprocessor/hash-import-directive-cpp?view=msvc-170
    • https://blog.csdn.net/ghgui008/article/details/9090713
  • 在编译后生成的文件中可以找到 dm.tlhdm.tli文件,例如
    • 项目目录/cmake-build-debug-visual-studio/CMakeFiles/dm_demo.dir/dm.tlh
    • 项目目录/cmake-build-debug-visual-studio/CMakeFiles/dm_demo.dir/dm.tli
  • 再注释掉 dmutils.h 中的#import ./external/dm.dll,导入 dm.tlh 文件
// #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)

这篇关于CMake+大漠插件的应用开发——处理dm.dll,免注册调用大漠插件的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/599978

相关文章

Python FastAPI+Celery+RabbitMQ实现分布式图片水印处理系统

《PythonFastAPI+Celery+RabbitMQ实现分布式图片水印处理系统》这篇文章主要为大家详细介绍了PythonFastAPI如何结合Celery以及RabbitMQ实现简单的分布式... 实现思路FastAPI 服务器Celery 任务队列RabbitMQ 作为消息代理定时任务处理完整

C#使用SQLite进行大数据量高效处理的代码示例

《C#使用SQLite进行大数据量高效处理的代码示例》在软件开发中,高效处理大数据量是一个常见且具有挑战性的任务,SQLite因其零配置、嵌入式、跨平台的特性,成为许多开发者的首选数据库,本文将深入探... 目录前言准备工作数据实体核心技术批量插入:从乌龟到猎豹的蜕变分页查询:加载百万数据异步处理:拒绝界面

Spring Boot + MyBatis Plus 高效开发实战从入门到进阶优化(推荐)

《SpringBoot+MyBatisPlus高效开发实战从入门到进阶优化(推荐)》本文将详细介绍SpringBoot+MyBatisPlus的完整开发流程,并深入剖析分页查询、批量操作、动... 目录Spring Boot + MyBATis Plus 高效开发实战:从入门到进阶优化1. MyBatis

Python基于wxPython和FFmpeg开发一个视频标签工具

《Python基于wxPython和FFmpeg开发一个视频标签工具》在当今数字媒体时代,视频内容的管理和标记变得越来越重要,无论是研究人员需要对实验视频进行时间点标记,还是个人用户希望对家庭视频进行... 目录引言1. 应用概述2. 技术栈分析2.1 核心库和模块2.2 wxpython作为GUI选择的优

Springboot处理跨域的实现方式(附Demo)

《Springboot处理跨域的实现方式(附Demo)》:本文主要介绍Springboot处理跨域的实现方式(附Demo),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不... 目录Springboot处理跨域的方式1. 基本知识2. @CrossOrigin3. 全局跨域设置4.

Python中随机休眠技术原理与应用详解

《Python中随机休眠技术原理与应用详解》在编程中,让程序暂停执行特定时间是常见需求,当需要引入不确定性时,随机休眠就成为关键技巧,下面我们就来看看Python中随机休眠技术的具体实现与应用吧... 目录引言一、实现原理与基础方法1.1 核心函数解析1.2 基础实现模板1.3 整数版实现二、典型应用场景2

python+opencv处理颜色之将目标颜色转换实例代码

《python+opencv处理颜色之将目标颜色转换实例代码》OpenCV是一个的跨平台计算机视觉库,可以运行在Linux、Windows和MacOS操作系统上,:本文主要介绍python+ope... 目录下面是代码+ 效果 + 解释转HSV: 关于颜色总是要转HSV的掩膜再标注总结 目标:将红色的部分滤

Python Dash框架在数据可视化仪表板中的应用与实践记录

《PythonDash框架在数据可视化仪表板中的应用与实践记录》Python的PlotlyDash库提供了一种简便且强大的方式来构建和展示互动式数据仪表板,本篇文章将深入探讨如何使用Dash设计一... 目录python Dash框架在数据可视化仪表板中的应用与实践1. 什么是Plotly Dash?1.1

在C#中调用Python代码的两种实现方式

《在C#中调用Python代码的两种实现方式》:本文主要介绍在C#中调用Python代码的两种实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录C#调用python代码的方式1. 使用 Python.NET2. 使用外部进程调用 Python 脚本总结C#调

Python实现自动化接收与处理手机验证码

《Python实现自动化接收与处理手机验证码》在移动互联网时代,短信验证码已成为身份验证、账号注册等环节的重要安全手段,本文将介绍如何利用Python实现验证码的自动接收,识别与转发,需要的可以参考下... 目录引言一、准备工作1.1 硬件与软件需求1.2 环境配置二、核心功能实现2.1 短信监听与获取2.