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)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/344486.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Playwright 结合 Selenium Grid - 1.windows 环境使用教程

Playwright 可以连接到运行 Selenium 4 的 Selenium Grid Hub 来启动 Google Chrome 或 Microsoft Edge 浏览器,而不是在本地机器上运行浏览器。 下载Selenium Grid 打开selenium官方https://www.selenium.dev/downloads/下载Selenium Server (Grid) 目前最新版本4.16.1 下…

Windows 项目从0到1的部署

目录 一. 安装jdk 1.1 安装jdk 1.2 配置jdk的环境配置jdk 1.3 配置成功 二. 配置tomcat 2.1 启动tomcat 2.2 防火墙设置 三. 安装MySQL 3.1 安装步骤 3.2 内部连接 3.3 外部连接 四. 部署项目 4.1 项目部署 4.2 修改mysql的用户密码 一. 安装jdk 这里给大家准备好了jdk和…

数据库SELECT语句

文章目录 一、检索数据二、排序检索三、过滤数据四、数据过滤4.1 组合WHERE子句1. AND操作符2. OR操作符3. 计算次序 4.2 IN操作符4.3 NOT操作符 五、用通配符过滤LIKE操作符1. 百分号&#xff08;%&#xff09;通配符2. 下划线&#xff08;_&#xff09;通配符 使用通配符的技…

what is BERT?

BERT Introduction Paper 参考博客 9781838821593_ColorImages.pdf (packt-cdn.com) Bidirectional Encoder Representation from Transformer 来自Transformer的双向编码器表征 基于上下文&#xff08;context-based&#xff09;的嵌入模型。 那么基于上下文&#xff08;…

apache、nginx、php 隐藏版本号

apache、nginx、php 隐藏版本号 针对的系统都是CentOS 1、没配置之前 1.1 Server: Apache/2.4.6 (CentOS) OpenSSL/1.0.2k-fips PHP/7.2.24 mod_wsgi/3.4 Python/2.7.5 1.2 Server: nginx/1.16.0 1.3 X-Powered-By&#xff1a;7.2.24 2、配置信息 不知道具体位置&#xff0c;可…

小程序系列-5.WXML 模板语法

一、数据绑定 1、在 data 中定义页面的数据 动态绑定内容&#xff1a; 动态绑定属性&#xff1a; 2. Mustache 语法的格式 3. Mustache 语法的应用场景 4. 三元运算 5.算数运算 二、 事件绑定 1. 什么是事件&#xff1f; 2. 小程序中常用的事件 3. 事件对象的属性列表 4.…

【Java SE语法篇】6.数组

&#x1f4da;博客主页&#xff1a;爱敲代码的小杨. ✨专栏&#xff1a;《Java SE语法》 ❤️感谢大家点赞&#x1f44d;&#x1f3fb;收藏⭐评论✍&#x1f3fb;&#xff0c;您的三连就是我持续更新的动力❤️ 文章目录 1.数组的基本概念1.1 为什么使用数组&#xff1f;1.…

【期末不挂科-C++考前速过系列P3】大二C++第3次过程考核(20道选择题&12道判断题&2道代码题)【解析,注释】

前言 大家好吖&#xff0c;欢迎来到 YY 滴C考前速过系列 &#xff0c;热烈欢迎&#xff01; 本章主要内容面向接触过C的老铁 主要内容含&#xff1a; 欢迎订阅 YY滴C专栏&#xff01;更多干货持续更新&#xff01;以下是传送门&#xff01; YY的《C》专栏YY的《C11》专栏YY的《…

easyexcel上传校验的方法封装

easyexcel版本3.1.5 使用自定义注解的方式来定义校验的类型&#xff0c;避免冗余代码。 //校验value不能为空&#xff0c;且长度最大为30 RowCheck(value {RowCheckType.EMPTY,RowCheckType.LENGTH},max 30) private String value; 具体代码&#xff1a; 首先定义校验类型…

缓存学习实战篇

缓存练习题&#xff08;用户查询操作&#xff09; public List<ShopType> queryAllType() throws JsonProcessingException {//从缓存中查数据String shopTypeJson stringRedisTemplate.opsForValue().get("cache:shopType");//如果缓存命中&#xff0c;if (S…

短视频账号矩阵剪辑分发系统无人直播技术开发源头

一、全行业独家源头最全面的核心技术 短视频矩阵新玩法是指利用批量自动混剪系统来处理大量短视频&#xff0c;通过智能算法自动进行视频剪辑、场景切换、特效添加等操作&#xff0c;最终生成高质量、精彩纷呈的混剪视频作品的方法和技术。这一方法的出现使得大规模短视频制作…

LangChain 71 字符串评估器String Evaluation衡量在多样化数据上的性能和完整性

LangChain系列文章 LangChain 60 深入理解LangChain 表达式语言23 multiple chains链透传参数 LangChain Expression Language (LCEL)LangChain 61 深入理解LangChain 表达式语言24 multiple chains链透传参数 LangChain Expression Language (LCEL)LangChain 62 深入理解Lang…