拓冰建站拓冰建站
首页 / 资讯中心 / 正文

x64dbg 插件开发指南:GuiCloseQWidgetTab 关闭插件 QWidget 标签页

x64dbg 插件开发指南GuiCloseQWidgetTab 关闭插件 QWidget 标签页【免费下载链接】x64dbgAn open-source user mode debugger for Windows. Optimized for reverse engineering and malware analysis.项目地址: https://gitcode.com/gh_mirrors/x6/x64dbg导读GuiCloseQWidgetTab是 x64dbg 为插件开发者提供的 GUI 桥接函数之一用于关闭插件通过GuiAddQWidgetTab添加到主界面标签栏QTabWidget中的 Qt QWidget 标签页。本文以 GuiCloseQWidgetTab.md 为骨架结合 x64dbg 仓库中 bridge 层、GUI 层的真实实现讲解该函数的签名、调用链、与GuiAddQWidgetTab/GuiShowQWidgetTab的配合方式以及插件中正确关闭自定义标签页的完整实战方案。函数签名与作用GuiCloseQWidgetTab属于 x64dbg 插件开发 API 中的 GUI 函数族完整清单见 gui/index.rst其唯一职责是关闭一个由插件添加的 Qt QWidget 标签页。void GuiCloseQWidgetTab(QWidget* qWidget);该函数在 bridgemain.h 中声明供插件链接x64dbg_bridge后直接调用。参数说明参数类型说明qWidgetQWidget*待关闭标签页对应的 Qt QWidget 对象指针。该指针应当是之前通过GuiAddQWidgetTab添加进界面的同一个对象返回值该函数不返回任何值void。它是一条发后即忘fire-and-forget的桥接消息调用后立即返回标签页的实际关闭动作由 GUI 线程异步完成。从桥接层到界面的完整调用链理解GuiCloseQWidgetTab的关键在于它横跨 x64dbg 的调试器进程/线程dbg 侧与GUI 进程/线程gui 侧两层架构。整条调用链如下1. 桥接层发送 GUI 消息插件调用GuiCloseQWidgetTab后实际执行的是 bridgemain.cpp 中的桥接实现BRIDGE_IMPEXP void GuiCloseQWidgetTab(void* qWidget) { _gui_sendmessage(GUI_CLOSE_QWIDGET_TAB, qWidget, nullptr); }注意两点实现细节参数类型在桥接层被降为void*GUI_CLOSE_QWIDGET_TAB消息宏在 bridgemain.h 中的定义即为msg(GUI_CLOSE_QWIDGET_TAB, QWidget*, unused)QWidget*指针以原始指针形式随消息传递_gui_sendmessage将消息投递到 GUI 线程的消息队列因此该调用对调用方线程是安全的但关闭动作本身并不在调用线程同步执行。2. GUI 桥接消息分发为 Qt 信号GUI 侧收到GUI_CLOSE_QWIDGET_TAB消息后在 Bridge.cpp 中将其转换为 Qt 信号case GUI_CLOSE_QWIDGET_TAB: emit closeQWidgetTab((QWidget*)param1); break;对应的信号closeQWidgetTab(QWidget*)声明于 Bridge.h与addQWidgetTab、showQWidgetTab三个信号并列构成插件 QWidget 标签页的完整生命周期接口。3. 主窗口槽真正关闭标签页MainWindow在构造时建立信号与槽的连接MainWindow.cppconnect(Bridge::getBridge(), SIGNAL(closeQWidgetTab(QWidget*)), this, SLOT(closeQWidgetTab(QWidget*)));槽函数实现在 MainWindow.cppvoid MainWindow::closeQWidgetTab(QWidget* qWidget) { for(int i 0; i mTabWidget-count(); i) { if(mTabWidget-widget(i) qWidget) { mTabWidget-DeleteTab(i); break; } } }实现逻辑非常直接遍历主标签控件mTabWidget的全部页面按指针匹配到目标 QWidget 后调用DeleteTab(i)删除对应标签页。从中可以推断出两点使用前提qWidget必须是当前确实存在于标签栏中的指针否则遍历不命中函数静默无操作匹配依据是指针相等mTabWidget-widget(i) qWidget因此传入错误的指针或已失效的指针不会关闭任何标签页也不会产生可见报错。与标签页添加、显示 API 的配合GuiCloseQWidgetTab不是孤立存在的它需要与标签页生命周期中的另外两个桥接函数配合使用函数作用桥接消息GuiAddQWidgetTab将 QWidget 添加为 GUI 的新标签页GUI_ADD_QWIDGET_TABGuiShowQWidgetTab显示标签页并将其置为焦点GUI_SHOW_QWIDGET_TABGuiCloseQWidgetTab关闭移除标签页GUI_CLOSE_QWIDGET_TAB三者均定义于 bridgemain.cpp在 GUI 侧对应 Bridge.h 的三个信号与 MainWindow.cpp 的三个槽。其中GuiAddQWidgetTab的槽实现MainWindow.cpp还揭示了标签页原生名称nativeName的生成规则对理解关闭行为有帮助void MainWindow::addQWidgetTab(QWidget* qWidget) { QString nativeName qWidget-objectName(); if(nativeName.isEmpty()) nativeName qWidget-metaObject()-className(); nativeName Plugin nativeName.replace( , _).replace(, _); WidgetInfo info(qWidget, nativeName); addQWidgetTab(info.widget, info.nativeName); mPluginWidgetList.append(info); }即优先取objectName()为空则退回类名并统一加上Plugin前缀、将空格与等号替换为下划线同时把WidgetInfo记入mPluginWidgetList插件控件清单。插件中的典型使用示例以下是插件在自定义 QWidget 标签页生命周期管理中的典型用法对应 GuiAddQWidgetTab.md 与本文所述 API 的组合#include QWidget #include bridge/bridgemain.h // 1. 创建并添加标签页 QWidget* myTab new QWidget(nullptr); myTab-setObjectName(MyPluginPanel); myTab-setWindowTitle(My Plugin); GuiAddQWidgetTab(myTab); // 添加到 GUI 标签栏 // 2. 需要时将标签页切换到前台 GuiShowQWidgetTab(myTab); // 3. 关闭并移除标签页 GuiCloseQWidgetTab(myTab);在实际插件中关闭动作通常由以下场景触发插件菜单中提供关闭面板入口用户点击后调用GuiCloseQWidgetTab插件窗口自身的关闭按钮重写closeEvent中调用该函数确保标签页从主界面移除插件卸载清理阶段遍历自身维护的 QWidget 列表逐一关闭。脚本 API 中的对应封装GuiCloseQWidgetTab还被封装进 x64dbg 的脚本 API插件或脚本可通过Script::Gui命名空间调用。相关实现位于 _scriptapi_gui.cppSCRIPT_EXPORT void Script::Gui::AddQWidgetTab(void* qWidget) { GuiAddQWidgetTab(qWidget); } SCRIPT_EXPORT void Script::Gui::ShowQWidgetTab(void* qWidget) { GuiShowQWidgetTab(qWidget); } SCRIPT_EXPORT void Script::Gui::CloseQWidgetTab(void* qWidget) { GuiCloseQWidgetTab(qWidget); }注意脚本 API 层参数统一为void*需要调用方自行确保传入的是有效的QWidget*。使用注意事项综合源码实现使用GuiCloseQWidgetTab时有几点需要留意异步性函数通过消息队列异步关闭标签页调用后界面更新存在极短延迟不要在调用后立即假设标签页已不存在指针有效性关闭匹配基于指针相等务必传入与GuiAddQWidgetTab完全相同的指针对象销毁后调用是无害但无效的遍历不命中生命周期归属从 Qt 的对象模型看QWidget 被添加为标签页后由主标签控件接管父子关系DeleteTab移除页面时相应的清理逻辑由 Qt 侧完成插件不应在关闭后再次 delete 同一对象以免双重释放GUI 线程亲和性QWidget 操作要求 GUI 线程上下文而桥接层已负责把消息投递到 GUI 线程因此插件在任意线程调用该函数都是安全的无需自行切换线程无返回值无法通过返回值判断关闭是否成功如需确认结果可自行维护插件侧的控件状态。相关函数与文档本文主题文档GuiCloseQWidgetTab.md配套添加文档GuiAddQWidgetTab.mdGUI 函数族索引gui/index.rst桥接层实现bridgemain.cpp、bridgemain.hGUI 消息分发Bridge.cpp、Bridge.h主窗口槽实现MainWindow.cpp脚本 API 封装_scriptapi_gui.cpp【免费下载链接】x64dbgAn open-source user mode debugger for Windows. Optimized for reverse engineering and malware analysis.项目地址: https://gitcode.com/gh_mirrors/x6/x64dbg创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门