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

文章目录

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

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

简介

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

环境

版本/规范备注
平台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
  • 在 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 "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.mzph.cn/news/618976.shtml

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

相关文章

Navicat连接不上虚拟机中linux的dockers创建的mysql

说明&#xff1a;这个问题可能只是我的个人问题&#xff0c;记录一下吧。当发现这个问题的时候&#xff0c;去网上搜素了一下&#xff0c;搜到的文章基本上都是通过在mysql中设置允许远程访问解决的&#xff0c;然后我也跟着尝试了一下&#xff0c;问题并没有解决。后面就乱七八…

allegro PCB设计心得笔记(二) PCB板框设计心得

Cadence Allegro软件设计PCB板框时&#xff0c;使用Add -> line&#xff0c;在Option选择Board Geometry/Outline&#xff0c;根据PCB需要输入对应坐标&#xff0c;设计好板框。 使用Z-Copy命令设计Route Keepin和Package Keepin时&#xff0c;需要先使用使用Shape -> Co…

【Python】Python语言 3小时速通(有C语言基础版)

python从入门到实践 变量 message"hello world"并不需要指出变量类型 方法 tittle()#以首字母大写的形式输出单词upper()#全部大写输出lower()#全部小写输出存储数据时经常使用lower&#xff0c;因为无法确保数据是大写还是小写 rstrip()#输出删除字符串尾部多余…

YOLOv5涨点改进:多层次特征融合(SDI),小目标涨点明显,| UNet v2,比UNet显存占用更少、参数更少

💡💡💡本文全网独家改进:多层次特征融合(SDI),能够显著提升不同尺度和小目标的识别率 💡💡💡在YOLOv5中如何使用 1)iAFF加入Neck替代Concat; 💡💡💡Yolov5/Yolov7魔术师,独家首发创新(原创),适用于Yolov5、Yolov7、Yolov8等各个Yolo系列,专栏文…

RabbitMQ 的基本概念

一 MQ 的基本概念 1 MQ概述 MQ全称 Message Queue&#xff08;消息队列&#xff09;&#xff0c;是在消息的传输过程中保存消息的容器。多用于分布式系统之间进行通信。消息队列就是所谓的存放消息的队列。 消息队列解决的不是存放消息的队列的⽬的&#xff0c;解决的是通信问…

三、GCC编译:链接

代码准备 main.c extern int shared; extern void func(int *a, int *b); int main(){int a 100;func(&a, &shared);return 0; }func.c int shared 1; int tmp 0; void func(int *a, int *b){tmp *a;*a *b;*b tmp; }静态链接 编译 gcc -static -fno-stack-p…

TypeScript学习笔记、鸿蒙开发学习笔记

变量定义方式 # 变量声明 let msg: string douzi console.log(msg) let num: number 20 console.log(num) let end: boolean true console.log("end" end) let a: any 10 a douzi console.log(a) let p {name:"douzi",age:20} console.log(p.name)…

cmake-将源文件编译为可执行文件

文章目录 准备工作创建cmake文件编译源代码需要的文件不在同一个文件夹的情况 准备工作 首先我们准备三个文件 add.h int add(int a,int b);add.cpp int add(int a,int b) {return ab; }main.cpp #include "add.h" #include <iostream> int main() {in…

Multi-Concept Customization of Text-to-Image Diffusion——【代码复现】

本文是发表于CVPR 2023上的一篇论文&#xff1a;[2212.04488] Multi-Concept Customization of Text-to-Image Diffusion (arxiv.org) 一、引言 本文主要做的工作是对stable-diffusion的预训练模型进行微调&#xff0c;需要的显存相对较多&#xff0c;论文中测试时是在两块GP…

ssh远程登录协议

目录 一、ssh协议定义及特点 &#xff08;一&#xff09;ssh协议简介 &#xff08;二&#xff09;ssh协议的主要特点 二、ssh传输原理 三、sshd服务 &#xff08;一&#xff09;配置文件 &#xff08;二&#xff09;基本用法 1.直接连接 2.连接指定用户 3.指定端口号…

设计模式之策略模式【行为型模式】

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档> 学习的最大理由是想摆脱平庸&#xff0c;早一天就多一份人生的精彩&#xff1b;迟一天就多一天平庸的困扰。各位小伙伴&#xff0c;如果您&#xff1a; 想系统/深入学习某…

十分钟教你在 k8s 中部署一个前后端应用

好多开发人员&#xff0c;尤其是没接触过 k8s 的人员对如何在k8s中部署一个 前后端应用很模糊&#xff0c;不知如何下手&#xff0c;所以本篇讲一下如何快速在 k8s 部署一个前后端应用&#xff0c;让大家对k8s有个快速认识 前置依赖 k8s集群&#xff0c;如果没有安装&#xff0…

什么是RoPE-旋转位置编码?

RoPE位置编码是大模型中最常见的位置编码之一。像是谷歌的PaLM和meta的LLaMA等开源大模型都是RoPE位置编码&#xff0c;那么RoPE有什么特点呢&#xff1f; 本文将介绍如下内容&#xff1a; RoPE旋转位置编码概要什么是位置编码&#xff1f;RoPE及其特点总结 一、RoPE旋转位置…

stm32学习笔记:DMA

每个DMA通道硬件触发源是不一样的&#xff0c;要使用某个外设的硬件触发源&#xff0c;就必须使用它连接的那个通道 12个独立可配置的通道&#xff1a;DMA1(7个通道)&#xff0c;DMA2(5个通道) 每个通道都支持软件触发和特定的硬件触发 C8T6 DMA资源&#xff1a;DMA1 &#xff…

Python自动化我选DrissionPage,弃用Selenium

DrissionPage 是一个基于 python 的网页自动化工具。 它既能控制浏览器&#xff0c;也能收发数据包&#xff0c;还能把两者合而为一。 可兼顾浏览器自动化的便利性和 requests 的高效率。 它功能强大&#xff0c;内置无数人性化设计和便捷功能。 它的语法简洁而优雅&#x…

数据库和表的操作

文章目录 前言一、库的操作创建数据库字符集和校验规则操纵数据库查看数据库显示创建语句修改数据库删除数据库备份和恢复数据库还原查看连接情况 二、表的操作创建表查看表结构修改表修改表名添加一列修改某一列属性删除某一列 删除表 前言 一、库的操作 创建数据库 语法&am…

【Python机器学习】分类器的不确定估计——决策函数

scikit-learn接口的分类器能够给出预测的不确定度估计&#xff0c;一般来说&#xff0c;分类器会预测一个测试点属于哪个类别&#xff0c;还包括它对这个预测的置信程度。 scikit-learn中有两个函数可以用于获取分类器的不确定度估计&#xff1a;decidion_function和predict_pr…

day06

1.八大基本数据类型整型: byte short int long 浮点: double float字符: char布尔: boolean2.声明变量的语法格式数据类型 变量名字 初始化的值; 3.使用for循环打印等腰三角形for (int i 1; i < 4; i) {for (int j 1; j < 4 - i; j) {System.out.print(" &qu…

计算机毕业设计----SSH电子相册管理系统

项目介绍 本项目分为普通用户与管理员两个角色&#xff1b; 管理员角色包含以下功能&#xff1a; 管理员登陆,用户信息管理,登陆密码修改等功能。 用户角色包含以下功能&#xff1a; 用户登陆,个人信息管理,相册管理,上传照片等功能。 环境需要 1.运行环境&#xff1a;最好…

高效办公:在文件夹名称左边插入关键字,提高文件管理效率

在繁忙的工作环境中&#xff0c;经常要处理大量的文件和文件夹。有效的文件管理是一个挑战&#xff0c;大量的文件和文件夹难以找到所需的资料。下面一起来看云炫文件管理器如何在文件夹名称左边批量插入关键字。 文件夹名称左边添加关键字前后对比图。 文件夹名称左边批量插…