本文主要是介绍CMake+大漠插件的应用开发——处理dm.dll,免注册调用大漠插件,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
文章目录
- CMake+大漠插件的应用开发——处理dm.dll,免注册调用大漠插件
- 说明
- 环境
- 项目结构
- 配置编译环境
- 编码-直接调用 dll
- 编码-生成tlh文件,便于提示
CMake+大漠插件的应用开发——处理dm.dll,免注册调用大漠插件
说明
- 网上有一种使用方式是:利用QT的dumpcpp.exe工具对dm.dll处理,生成xxx.h和xxx.cpp文件再使用。
- 不过我发现这种使用时有些问题,同时生成的文件也不太通用(只能QT用),所以换了另一种方式。
- 方法参考自 Visual C++免注册调用大漠插件-CSDN博客
环境
版本/规范 | 备注 | |
---|---|---|
平台 | win32 | 操作系统为Windows10 |
CMake | 3.27.8 | CLion自带 |
C++ | 17 | 11也行 |
Toolchain | VisualStudio 2022 | 只用其工具链,记先安装好 |
DM | 7.2353 | 大漠插件 |
CLion | 2023.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
- 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.h 和 dmutils.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.tlh 和 dm.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.tlh 和 dm.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.tlh 和 dm.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,免注册调用大漠插件的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!