文章目录 CMake+大漠插件的应用开发——处理dm.dll,免注册调用大漠插件 简介 环境 项目结构 配置编译环境 编码-直接调用 dll 编码-生成tlh文件,便于提示
CMake+大漠插件的应用开发——处理dm.dll,免注册调用大漠插件
简介
网上有一种使用方式是:利用QT 的dumpcpp.exe 工具对dm.dll 处理,生成xxx.h 和xxx.cpp 文件再使用。 不过我发现这种使用时有些问题,同时生成的文件也不太通用(只能QT用),所以换了另一种方式。 方法参考自 Visual C++免注册调用大漠插件-CSDN博客 在下一篇CMake+QT+大漠插件的桌面应用开发中将会给出利用QT和大漠插件结合开发桌面应用的例子
环境
版本/规范 备注 平台 win32 操作系统为Windows10 CMake 3.27.8 CLion自带 C++ 17 11也行 Toolchain VisualStudio 2022 只用其工具链,记先安装好 DM 7.2353 大漠插件 CLion 2023.3.2 你也可以用其他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
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 在 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
# define DM_LIB_PATH L "./external/dm.dll" using namespace std;
Idmsoft * GetDmObject ( ) ;
Idmsoft * initialDMAndRegVIP ( ) ;
void doCaptureWindow ( Idmsoft & pDm, long hwnd) ; # endif
# 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 ; } 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; 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 ( ) ;
}
# include <iostream> # include "dmutil.h" int main ( ) { std:: cout << "Hello, World!" << std:: endl; Idmsoft * pDm = initialDMAndRegVIP ( ) ; _bstr_t hwnds = pDm-> EnumWindow ( 0 , L"dm" , L"" , 1 + 4 + 8 + 16 ) ; std:: cout << ( char * ) hwnds << std:: endl; 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 文件
# 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
,写的是绝对路径,需要我们改成相对路径,方便以后直接一起拿到其他项目使用
# include ".\dm.tli" # pragma pack ( pop)