昌平石家庄网站建设,外贸网站建设的好处,百度直播推广,国家建设部网站平台文章目录 CMakeQT大漠插件的桌面应用开发说明环境项目结构配置编译环境代码 CMakeQT大漠插件的桌面应用开发
说明
在CMake大漠插件的应用开发——处理dm.dll#xff0c;免注册调用大漠插件中已经说明了如何免注册调用大漠插件#xff0c;以及做了几个简单的功能调用#x… 文章目录 CMakeQT大漠插件的桌面应用开发说明环境项目结构配置编译环境代码 CMakeQT大漠插件的桌面应用开发
说明
在CMake大漠插件的应用开发——处理dm.dll免注册调用大漠插件中已经说明了如何免注册调用大漠插件以及做了几个简单的功能调用查找窗口、截图下面来利用QT做一个简单的窗口查找、截图的桌面工具应用功能点如下 点击“注册”选项完成大漠插件的注册。用户在文本框输入窗口标题后点击“查询”按钮可对包含该标题的窗口进行查询。提供表格展示查询到的窗口信息。点击“截图”按钮对选中的窗口进行截图并保存。 界面如下 目前主窗口的UI操作和大漠的调用是在一个线程里面的当大漠调用时间过长时会出现UI界面卡顿的现象下一篇将会给出如何处理这种问题的示例。
环境
版本/规范备注平台win32操作系统为Windows10CMake3.27.8CLion自带C17ToolchainVisualStudio 2022只用其工具链记得先安装好QT5.12.12安装时选择msvc2017不要64位的DM7.2353CLion2023.3.2你也可以用其他IDE工具
启动IDE时记得以管理员模式启动
项目结构
新建一个项目 qt_dm_demo_x_01将下载好的 dm.dll 文件以及处理好的 dm.tlh、dm.tli 文件放置到项目的 external 目录下 注dm.tlh、dm.tli 文件的生成请参考 CMake大漠插件的应用开发——处理dm.dll免注册调用大漠插件
qt_dm_demo_x_01 # 项目目录
--|cmake-build-debug-visual-studio # 工程构建目录存临时生成的文件
--|--|...
--|external # 引入第三方库文件的所在的文件夹
--|--|dm.dll # 大漠插件的dll
--|--|dm.tlh
--|--|dm.tli
--CMakeLists.txt # CMake脚本文件
--dmutil.cpp # 大漠的功能封装工具
--dmutil.h # 大漠的功能封装工具
--main.cpp # 程序入口
--mymainwindow.cpp # 主窗口
--mymainwindow.h # 主窗口
--mymainwindow.ui # 主窗口的UI文件
--strutils.cpp # 字符串工具
--strutils.h # 字符串工具配置编译环境
配置工具链 和CMake大漠插件的应用开发——处理dm.dll免注册调用大漠插件中保持一致即可 CMakeLists.txt 文件
cmake_minimum_required(VERSION 3.27)
project(qt_dm_demo_x_01)set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} /utf-8)set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)set(CMAKE_PREFIX_PATH C:/Qt/Qt5.12.12/5.12.12/msvc2017)find_package(Qt5 COMPONENTSCoreGuiWidgetsREQUIRED)add_executable(${PROJECT_NAME} main.cppstrutils.cpp strutils.hdmutil.cpp dmutil.hmymainwindow.cpp mymainwindow.h mymainwindow.ui
)target_link_libraries(${PROJECT_NAME}Qt5::CoreQt5::GuiQt5::Widgets
)target_compile_definitions(${PROJECT_NAME} PRIVATE-DWIN32# -D_DEBUG-D_WINDOWS-D_UNICODE-DUNICODE
)message(STATUS CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE})if (WIN32 AND NOT DEFINED CMAKETOOLCHAIN_FILE)set(DEBUG_SUFFIX)if (MSVC AND CMAKE_BUILD_TYPE MATCHES Debug)set(DEBUG_SUFFIX d)endif ()set(QT_INSTALL_PATH ${CMAKE_PREFIX_PATH})if (NOT EXISTS ${QT_INSTALL_PATH}/bin)set(QT_INSTALL_PATH ${QT_INSTALL_PATH}/..)if (NOT EXISTS ${QT_INSTALL_PATH}/bin)set(QT_INSTALL_PATH ${QT_INSTALL_PATH}/..)endif ()endif ()if (EXISTS ${QT_INSTALL_PATH}/plugins/platforms/qwindows${DEBUG_SUFFIX}.dll)add_custom_command(TARGET ${PROJECT_NAME} POST_BUILDCOMMAND ${CMAKE_COMMAND} -E make_directory$TARGET_FILE_DIR:${PROJECT_NAME}/plugins/platforms/)add_custom_command(TARGET ${PROJECT_NAME} POST_BUILDCOMMAND ${CMAKE_COMMAND} -E copy${QT_INSTALL_PATH}/plugins/platforms/qwindows${DEBUG_SUFFIX}.dll$TARGET_FILE_DIR:${PROJECT_NAME}/plugins/platforms/)endif ()foreach (QT_LIB Core Gui Widgets)add_custom_command(TARGET ${PROJECT_NAME} POST_BUILDCOMMAND ${CMAKE_COMMAND} -E copy${QT_INSTALL_PATH}/bin/Qt5${QT_LIB}${DEBUG_SUFFIX}.dll$TARGET_FILE_DIR:${PROJECT_NAME})endforeach (QT_LIB)
endif ()# 拷贝资源文件 dm.dll
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/external DESTINATION ${CMAKE_CURRENT_BINARY_DIR})代码
dmutil.h
#ifndef DM_DEMO_X_DMUTIL_H
#define DM_DEMO_X_DMUTIL_H#include string
#include vector// #import ./external/dm.dll no_namespace
#include ./external/dm.tlh#define DM_LIB_PATH L./external/dm.dllusing namespace std;struct MyWindow {long hwnd;wstring title;long processId;
};/*** 注册dm.dll获取大漠实例* return 大漠实例*/
Idmsoft *GetDmObject();/*** 初始化大漠插件并注册用户VIP* return 大漠实例*/
Idmsoft *initialDMAndRegVIP();/*** 获取匹配的窗口* param baseVec 保存window的容器* param pDm 大漠插件* param title 窗口标题中的字段模糊匹配* param processName 进程名称精确匹配不区分大小写默认不会根据进程名筛选窗口*/
void getMatchedWindows(vectorMyWindow baseVec, Idmsoft *pDm, const wstring title, const wstring processName L);#endif //DM_DEMO_X_DMUTIL_H
dmutil.cpp记得填入自己的 注册码 和 附加码
#include iostream
#include sstream
#include string_view
#include vector
#include dmutil.h
#include strutils.husing 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 getMatchedWindows(vectorMyWindow baseVec, Idmsoft *pDm, const wstring title, const wstring processName) {// 获取匹配的窗口句柄_bstr_t hwnds;if (!processName.empty()) {hwnds pDm-EnumWindowByProcess(processName.c_str(), title.c_str(), L, 1 8 16);} else {hwnds pDm-EnumWindow(0, title.c_str(), L, 1 4 8 16);}// 拆分找到的多个窗口句柄string content(hwnds);vectorstring_view hwndStrVec splitSV(content, ,);// 装入容器vectorbaseVec.reserve(hwndStrVec.size());for (const string_view element : hwndStrVec) {long curHwnd viewToInt(element);// 获取窗口titleconst _bstr_t curTitle pDm-GetWindowTitle(curHwnd);// const _bstr_t className pDm-GetWindowClass(curHwnd);long processId pDm-GetWindowProcessId(curHwnd);baseVec.push_back({curHwnd, {curTitle}, processId});}}strutils.h
#ifndef DM_DEMO_X_STRUTILS_H
#define DM_DEMO_X_STRUTILS_H#include string
#include string_view
#include iostream
#include vectorusing namespace std;/*** 按分隔符拆分字符串内容为vectorstring_view更加高效* param content 待分隔的字符串* param delim 分隔符默认为空格* return vector容器*/
vectorstring_view splitSV(string_view content, string_view delim );/*** string_view 转 int失败时抛出异常* param content 字符串内容view* return int值*/
int viewToInt(string_view content);#endif //DM_DEMO_X_STRUTILS_H
strutils.cpp
#include sstream
#include string
#include vector
#include charconv#include strutils.hvectorstring_view splitSV(string_view content, string_view delim) {vectorstring_view output;size_t first 0;while (first content.size()) {const auto second content.find_first_of(delim, first);if (first ! second)output.emplace_back(content.substr(first, second - first));if (second string_view::npos)break;first second 1;}return output;
}int viewToInt(string_view content) {int num;auto result std::from_chars(content.data(), content.data() content.size(), num);if (result.ec std::errc::invalid_argument) {throw std::runtime_error(Could not convert.);}return num;
}
mymainwindow.ui
?xml version1.0 encodingUTF-8?
ui version4.0classMyMainWindow/classwidget classQMainWindow nameMyMainWindowproperty namegeometryrectx0/xy0/ywidth400/widthheight300/height/rect/propertyproperty namewindowTitlestring窗口查询程序/string/propertywidget classQWidget namecentralwidgetlayout classQVBoxLayout nameverticalLayoutitemlayout classQHBoxLayout namehorizontalLayoutitemspacer namehorizontalSpacerproperty nameorientationenumQt::Horizontal/enum/propertyproperty namesizeHint stdset0sizewidth40/widthheight20/height/size/property/spacer/itemitemwidget classQLabel namelabelproperty namefontfontweight75/weightboldtrue/bold/font/propertyproperty nametextstring窗口标题/string/property/widget/itemitemwidget classQLineEdit nameedtTitleproperty nameminimumSizesizewidth200/widthheight0/height/size/property/widget/itemitemwidget classQPushButton namebtnQueryproperty nametextstring模糊查询/string/property/widget/itemitemspacer namehorizontalSpacer_3property nameorientationenumQt::Horizontal/enum/propertyproperty namesizeHint stdset0sizewidth40/widthheight20/height/size/property/spacer/itemitemwidget classQPushButton namebtnCaptureproperty nametextstring截图选中行/string/property/widget/itemitemspacer namehorizontalSpacer_2property nameorientationenumQt::Horizontal/enum/propertyproperty namesizeHint stdset0sizewidth40/widthheight20/height/size/property/spacer/item/layout/itemitemwidget classQTableWidget nametableWidget//item/layout/widgetwidget classQMenuBar namemenubarproperty namegeometryrectx0/xy0/ywidth400/widthheight21/height/rect/propertywidget classQMenu namemenuOperationproperty nametitlestring菜单/string/propertyaddaction nameactionReg//widgetaddaction namemenuOperation//widgetwidget classQStatusBar namestatusbar/action nameactionRegproperty nametextstring注册DM/string/property/action/widgetresources/connections/
/ui
mymainwindow.h
#ifndef QT_DM_DEMO_X_MYMAINWINDOW_H
#define QT_DM_DEMO_X_MYMAINWINDOW_H#include QMainWindow#include dmutil.hQT_BEGIN_NAMESPACE
namespace Ui { class MyMainWindow; }
QT_END_NAMESPACEclass MyMainWindow : public QMainWindow {
Q_OBJECT
public:explicit MyMainWindow(QWidget *parent nullptr);~MyMainWindow() override;public:void showInfo(const QString message, const QString title 提示);void showWarn(const QString message, const QString title 告警);/*** 注册大漠* param pDm 大漠插件待赋值*/void doRegDM(Idmsoft **pDm);/*** 查询匹配的窗口* param pDm 大漠插件* param title 窗口标题模糊查询*/void doFindWindow(Idmsoft *pDm, const QString title);/*** 对窗口截图* param pDm 大漠插件* param hwnd 窗口句柄*/void doCaptureWindow(Idmsoft *pDm, long hwnd);public slots:void showMessageBox(bool result, const QString message);void showTableView(bool result, const QString msg, const vectorMyWindow windowVec);private:Ui::MyMainWindow *ui;Idmsoft *pCommonDm nullptr;
};#endif //QT_DM_DEMO_X_MYMAINWINDOW_Hmymainwindow.cpp // You may need to build the project (run Qt uic code generator) to get ui_MyMainWindow.h resolved#include QFont
#include QHeaderView
#include QMessageBox
#include QPushButton
#include QAction
#include QString
#include QTableWidgetItem
#include QObject
#include QVector
#include iostream
#include mymainwindow.h
#include ui_MyMainWindow.husing namespace std;MyMainWindow::MyMainWindow(QWidget *parent) :QMainWindow(parent), ui(new Ui::MyMainWindow) {ui-setupUi(this);// Init ViewssetFixedSize(1280, 720);ui-tableWidget-setColumnCount(3);ui-tableWidget-setHorizontalHeaderLabels(QStringList() 进程ID 句柄 标题);ui-tableWidget-horizontalHeader()-setStretchLastSection(true); // 最后一列自动铺满表格// ui-tableWidget-horizontalHeader()-setSectionResizeMode(1, QHeaderView::Stretch);ui-tableWidget-horizontalHeader()-setHighlightSections(false);ui-tableWidget-horizontalHeader()-setStyleSheet(QHeaderView::section{background:gray;});ui-tableWidget-setSelectionMode(QAbstractItemView::SingleSelection);QFont font ui-tableWidget-horizontalHeader()-font();font.setBold(true);ui-tableWidget-horizontalHeader()-setFont(font);ui-tableWidget-setStyleSheet(QTableWidget::item:hover { background-color: lightblue; });ui-tableWidget-setEditTriggers(QAbstractItemView::NoEditTriggers); // 禁止编辑ui-tableWidget-setSelectionBehavior(QAbstractItemView::SelectRows); // 选中整行// Init Listener// 注册大漠connect(ui-actionReg, QAction::triggered, [this]() {ui-actionReg-setEnabled(false);this-doRegDM(this-pCommonDm);ui-actionReg-setEnabled(true);});// 查找窗口connect(ui-btnQuery, QPushButton::clicked, [this]() {ui-btnQuery-setEnabled(false);this-doFindWindow(this-pCommonDm, ui-edtTitle-text());ui-btnQuery-setEnabled(true);});// 截图connect(ui-btnCapture, QPushButton::clicked, [this]() {ui-btnCapture-setEnabled(false);// 获取选中行的句柄列的字段const QListQTableWidgetItem * selectedItems ui-tableWidget-selectedItems();if (selectedItems.size() 2) {QTableWidgetItem *item selectedItems.at(1);const QString hwnd item-data(Qt::DisplayRole).toString();bool res false;long hwndL hwnd.toLong(res, 0);cout res endl;if (res) {this-doCaptureWindow(this-pCommonDm, hwndL);} else {this-showWarn(选中行的窗口句柄解析异常);}} else {this-showWarn(请选中列表中的其中一行);}ui-btnCapture-setEnabled(true);});}MyMainWindow::~MyMainWindow() {delete ui;
}void MyMainWindow::showInfo(const QString message, const QString title) {QMessageBox::information(this, title, message);
}void MyMainWindow::showWarn(const QString message, const QString title) {QMessageBox::critical(this, title, message);
}void MyMainWindow::showMessageBox(const bool result, const QString message) {if (result) {this-showInfo(message);} else {this-showWarn(message);}
}void MyMainWindow::showTableView(bool result, const QString msg, const vectorMyWindow windowVec) {if (result) {auto rowNum windowVec.size();ui-tableWidget-setRowCount(rowNum);for (int i 0; i rowNum; i) {const MyWindow item windowVec[i];ui-tableWidget-setItem(i, 0, new QTableWidgetItem(QString::number(item.processId)));ui-tableWidget-setItem(i, 1, new QTableWidgetItem(QString::number(item.hwnd)));ui-tableWidget-setItem(i, 2, new QTableWidgetItem(QString::fromStdWString(item.title)));}} else {this-showWarn(msg);}
}void MyMainWindow::doRegDM(Idmsoft **pDm) {cout Initial DM ............ endl;*pDm initialDMAndRegVIP();if (*pDm nullptr) {cout Initial DM Failed endl;showMessageBox(false, DM 注册失败);return;}cout Initial DM Successful endl;cout endl;showMessageBox(true, DM 注册完成);
}void MyMainWindow::doFindWindow(Idmsoft *pDm, const QString title) {vectorMyWindow windowVec;if (pDm nullptr) {cout this-pCommonDm nullptr endl;this-showTableView(false, 请先在菜单中完成注册, windowVec);return;}// 找一下title包含findStr的窗口并打印信息getMatchedWindows(windowVec, pDm, title.toStdWString());if (windowVec.empty()) {cout can not find such window endl;this-showTableView(false, 没有找到包含该标题的窗口, windowVec);return;}this-showTableView(true, 成功, windowVec);
}void MyMainWindow::doCaptureWindow(Idmsoft *pDm, long hwnd) {if (pDm nullptr) {cout this-pCommonDm nullptr endl;this-showMessageBox(false, 请先在菜单中完成注册);return;}// 绑定窗口句柄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;this-showMessageBox(false, 截图失败);} else {cout capture success endl;this-showMessageBox(true, QString::fromStdWString(L截图成功保存地址为 filename));}// 取消置顶窗口pDm-SetWindowState(hwnd, 9);} else {cout DM BindWindow failed endl;this-showMessageBox(false, 绑定窗口异常);}pDm-UnBindWindow();
}main.cpp
#include QApplication
#include iostream
#include mymainwindow.h
using namespace std;int main(int argc, char *argv[]) {setlocale(LC_ALL, chs);QApplication a(argc, argv);MyMainWindow mainWindow;mainWindow.show();return QApplication::exec();
}