明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 1648|回复: 21

ARX wxwidgets 界面开发

[复制链接]
发表于 2025-8-21 14:19:31 | 显示全部楼层 |阅读模式
本帖最后由 橡皮 于 2025-8-22 16:00 编辑

1. wxwidgets 库文件下载(当然可以自己下载源码编译)
  下载链接:Downloads - wxWidgets
   oneDrive:wxWidgets
  官方使用配置说明:How to use wxMSW binaries | wxWidgets

  下载后解压并将文件夹下内容直接拷贝到一块

2. 创建 ARX 项目,配置 wxwidgets 环境
  推荐ARX项目模版一键创建项目直接创建,当然如果愿意可后边将 wxwidgets 配置写到这个模板里边 ,
  这里不再演示创建过程,创建之后,添加上一步 wxwidgets 库文件夹中的属性文件 wxwidgets.props


3. 添加 wxwidgets 主窗口,重写初始化函数
在 arxEntryPoint.cpp 文件中添加如下函数
  1. class TRApp : public wxApp {
  2. public:
  3.   virtual bool OnInit() override
  4.   {
  5.     return true;
  6.   }
  7. };
  8. IMPLEMENT_APP_NO_MAIN(TRApp);

  9. static bool wxStarted = false;
  10. void EnsureWxWidgetsInitialized() {
  11.   if (!wxStarted) {
  12.     int argc = 0;
  13.     char** argv = nullptr;
  14.     wxStarted = true;
  15.     wxEntryStart(argc, argv);
  16.     wxTheApp->CallOnInit();
  17.   }
  18. }

  19. void CleanupWxWidgets() {
  20.   if (wxStarted) {
  21.     wxTheApp->OnExit();
  22.     wxEntryCleanup();
  23.     wxStarted = false;
  24.   }
  25. }
复制代码
并在 ARX 初始化函数中调用(也就是同步初始化创建 wxwidgets 主窗口)
  1.   virtual AcRx::AppRetCode On_kInitAppMsg (void *pkt) {

  2.     AcRx::AppRetCode retCode =AcRxArxApp::On_kInitAppMsg (pkt) ;
  3.    
  4.     EnsureWxWidgetsInitialized();

  5.     return (retCode) ;
  6.   }
复制代码
卸载时同步释放资源
  1.   virtual AcRx::AppRetCode On_kUnloadAppMsg (void *pkt) {
  2.     CleanupWxWidgets();
  3.     AcRx::AppRetCode retCode =AcRxArxApp::On_kUnloadAppMsg (pkt) ;
  4.     return (retCode) ;
  5.   }
复制代码

4. wxwidgets 实例
经过前三步就可以直接使用 wxwidgets 创建 UI 界面了(可以代码创建也可以使用xrc资源文件,这里只展示代码创建的)
a. 直接用 AI 生成了一个简单地如下
  1. #include <wx/wx.h>

  2. // 自定义对话框类
  3. class MyDialog : public wxDialog
  4. {
  5. public:
  6.     // 构造函数
  7.     MyDialog(wxWindow* parent, const wxString& title)
  8.         : wxDialog(parent, wxID_ANY, title, wxDefaultPosition, wxSize(300, 200))
  9.     {
  10.         // 创建垂直布局管理器
  11.         wxBoxSizer* vbox = new wxBoxSizer(wxVERTICAL);
  12.         
  13.         // 添加静态文本
  14.         wxStaticText* text = new wxStaticText(this, wxID_ANY,
  15.             "这是一个简单的 wxWidgets 对话框!\n\n"
  16.             "欢迎使用 wxWidgets 库。",
  17.             wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE);
  18.         
  19.         // 设置文本字体
  20.         wxFont font(12, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD);
  21.         text->SetFont(font);
  22.         
  23.         // 添加文本到布局,设置边距
  24.         vbox->Add(text, 1, wxALL | wxEXPAND, 20);
  25.         
  26.         // 创建水平布局放置按钮
  27.         wxBoxSizer* hbox = new wxBoxSizer(wxHORIZONTAL);
  28.         
  29.         // 添加确定按钮
  30.         wxButton* okBtn = new wxButton(this, wxID_OK, "确定", wxDefaultPosition, wxSize(70, 30));
  31.         hbox->Add(okBtn, 0, wxRIGHT, 10);
  32.         
  33.         // 添加取消按钮
  34.         wxButton* cancelBtn = new wxButton(this, wxID_CANCEL, "取消", wxDefaultPosition, wxSize(70, 30));
  35.         hbox->Add(cancelBtn);
  36.         
  37.         // 将水平布局添加到垂直布局
  38.         vbox->Add(hbox, 0, wxALIGN_CENTER | wxTOP | wxBOTTOM, 10);
  39.         
  40.         // 设置对话框的布局
  41.         SetSizer(vbox);
  42.         
  43.         // 居中显示对话框
  44.         Centre();
  45.     }
  46. };
复制代码

b. 自己也简单做了一个
  1. #pragma once
  2. #include <wx/wx.h>

  3. class MyDialog : public wxDialog {
  4. public:
  5.   MyDialog(wxWindow* parent);

  6. private:
  7.   void OnClose(wxCloseEvent& event);
  8.   void OnOK(wxCommandEvent& event);
  9.   void OnCancel(wxCommandEvent& event);
  10.   void OnCharHook(wxKeyEvent& event);
  11. };


  12. // cpp 文件内容
  13. #include "StdAfx.h"
  14. #include "MyDialog.h"

  15. class CDocLocker
  16. {
  17. public:
  18.   CDocLocker() { acDocManager->lockDocument(acDocManager->curDocument()); }
  19.   ~CDocLocker() { acDocManager->unlockDocument(acDocManager->curDocument()); }
  20. };

  21. MyDialog::MyDialog(wxWindow* parent)
  22.   : wxDialog(parent, wxID_ANY, "My Custom Dialog", wxDefaultPosition, wxSize(400, 200),
  23.     wxDEFAULT_DIALOG_STYLE | wxCLOSE_BOX | wxSTAY_ON_TOP)
  24. {
  25.   // 控件布局
  26.   auto* mainSizer = new wxBoxSizer(wxVERTICAL);
  27.   mainSizer->Add(new wxStaticText(this, wxID_ANY, "Welcome to use custom dialog"), 0, wxALL | wxALIGN_CENTER, 15);

  28.   auto* bSizer1 = new wxBoxSizer(wxHORIZONTAL);
  29.   auto* m_Cancel = new wxButton(this, wxID_CANCEL, wxT("取消"), wxDefaultPosition, wxDefaultSize, 0);
  30.   bSizer1->Add(m_Cancel, 1, wxALIGN_CENTER_VERTICAL | wxALL, 5);

  31.   auto* m_Ok = new wxButton(this, wxID_OK, wxT("确定"), wxDefaultPosition, wxDefaultSize, 0);
  32.   bSizer1->Add(m_Ok, 1, wxALIGN_CENTER_VERTICAL | wxALL, 5);

  33.   mainSizer->Add(bSizer1, 0, wxEXPAND | wxALL, 5);

  34.   SetSizerAndFit(mainSizer);

  35.   // 事件绑定
  36.   m_Ok->Bind(wxEVT_BUTTON, &MyDialog::OnOK, this);
  37.   m_Cancel->Bind(wxEVT_BUTTON, &MyDialog::OnCancel, this);
  38.   Bind(wxEVT_CHAR_HOOK, &MyDialog::OnCharHook, this);
  39.   Bind(wxEVT_CLOSE_WINDOW, &MyDialog::OnClose, this);
  40. }

  41. void MyDialog::OnCancel(wxCommandEvent& WXUNUSED(event)) {
  42.   Show(false); // 或 EndModal(wxID_CANCEL); // 模态对话框
  43. }

  44. void MyDialog::OnOK(wxCommandEvent& WXUNUSED(event)) {
  45.   Show(false);
  46.   acedGetAcadDwgView()->SetFocus();
  47.   CDocLocker docLocker;
  48.   ads_name ent;
  49.   ads_point pt;
  50.   if (acedEntSel(L"\nPick Curve: ", ent, pt) == RTNORM) {
  51.     AcDbObjectId objId;
  52.     AcDbEntity* pEnt = nullptr;
  53.     if (Acad::eOk == acdbGetObjectId(objId, ent)
  54.       && Acad::eOk == acdbOpenObject(pEnt, objId, AcDb::kForWrite))
  55.     {
  56.       pEnt->setColorIndex(pEnt->colorIndex() > 254 ? 1 : pEnt->colorIndex() + 1);
  57.       pEnt->close();
  58.     }
  59.   }
  60.   else {
  61.     acutPrintf(L"\nselect no curve.");
  62.   }
  63. }

  64. void MyDialog::OnClose(wxCloseEvent& WXUNUSED(event)) {
  65.   Show(false); // 或 EndModal(wxID_CANCEL); // 模态对话框
  66. }

  67. void MyDialog::OnCharHook(wxKeyEvent& event) {
  68.   if (event.GetKeyCode() == WXK_ESCAPE) {
  69.     Show(false); // 或 EndModal(wxID_CANCEL); // 模态对话框
  70.     return;
  71.   }
  72.   event.Skip();
  73. }

使用过程和 ARX 中 MFC 使用方式一致
  1. MyDialog* dlg = nullptr;  
  2.   
  3. static void MyGroupTT1 () {

  4.     if (!dlg)
  5.     {
  6.       dlg = new MyDialog(nullptr);
  7.     }
  8.     dlg->Show();

  9.   }

  10.   static void MyGroupTT2() {

  11.     MyDialog2 dlg(nullptr, L"second dialog");
  12.     dlg.ShowModal();
  13.   }

  14. ACED_ARXCOMMAND_ENTRY_AUTO(CwxWidgetsDemoApp, MyGroup, TT1, TT1, ACRX_CMD_MODAL, NULL)
  15. ACED_ARXCOMMAND_ENTRY_AUTO(CwxWidgetsDemoApp, MyGroup, TT2, TT2, ACRX_CMD_MODAL, NULL
复制代码



5. 演示
因为使用的是动态链接库所以加载插件前一定要将库所在文件夹添加到 CAD 的搜索路径里
演示如下:

下边是之前的帖子一维下料使用wxwidgets实现(采用的 XRC 资源文件,他是模块化的可以重复组合使用)

这个是直接将上边的代码添加到 ARX 项目中,并添加了绘制图形函数之后的插件演示


资源推荐:
wxwidgets 创建 UI 界面软件可以采用 wxFormBuilder 或者 DialogBlocks(推荐)




本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

x

评分

参与人数 3明经币 +4 金钱 +70 收起 理由
edata + 1 + 50 很给力!
cable2004 + 20 很给力!
d1742647821 + 3 赞一个!

查看全部评分

回复

使用道具 举报

 楼主| 发表于 2025-8-21 20:30:01 | 显示全部楼层
Microsoft Visual C++ compiler versions 14.0, 14.1, 14.2 and 14.3 (corresponding to marketing product names of Microsoft Visual Studio 2015, 2017, 2019 and 2022 respectively).
Please note that MSVC 14.x versions are ABI-compatible and the same set of binaries is used for all of them.

回复 支持 反对

使用道具 举报

发表于 2025-8-22 20:02:58 | 显示全部楼层
思路基本理清了,
  1.                 HWND acadHwnd = adsw_acadMainWnd();
  2.                 wxNativeContainerWindow parent((WXHWND)acadHwnd);
  3.                 CArxWxDialog theDialog(&parent);
  4.                 parent.Enable(false);//禁用父窗口
  5.                 theDialog.ShowModal();
  6.                 parent.Enable(true);//避免忘记启用       
复制代码


在关闭按钮的事件中,提前解锁,这样对话框退出的时候,才能把焦点给cad,否则在解开禁用时就会出现cad不在前面的问题。
  1. void CArxWxDialog::OnCancel(wxCommandEvent& WXUNUSED(event)) {
  2.         wxWindow*pParent=GetParent();
  3.         if (pParent)
  4.         {
  5.                 pParent->Enable(true); //对话框结束前解开禁用
  6.         }
  7.         EndModal(wxID_CANCEL);
  8.         //Show(false); // 或 EndModal(wxID_CANCEL); // 模态对话框
  9. }
复制代码


大致是这个思路,封装封装,应该可以作为基类使用了。
try it
回复 支持 反对

使用道具 举报

发表于 2025-8-22 17:30:14 | 显示全部楼层
如果wxwindow不设置父窗口,那么他和cad就没有关系,他们是两个窗口,而showmodal只是消息阻塞,cad还能点击,如果点击就会挡住wxwindow。
模态窗口的创建大概是这么个流程,构建对象,设置父窗口,弹窗窗口,窗口的焦点自然从父窗口到了子窗口,系统创建模态窗口的时候会禁用父窗口,关闭的时候启用父窗口,焦点自然就回到了父窗口。
而wxwindow如果不能设置正确的设置父窗口,那么他是当做一个独立的窗口运行,关闭时焦点不会切换会父窗口,手动设置焦点就会闪屏。

手动模态对话框
  1. CWnd* mfcWnd = acedGetAcadFrame();
  2.                 mfcWnd->EnableWindow(FALSE);
  3.                 CArxWxDialog dlg(nullptr);
  4.                 dlg.ShowModal();
  5.                 mfcWnd->EnableWindow(TRUE);
  6.                 mfcWnd->SetFocus();

回复 支持 反对

使用道具 举报

 楼主| 发表于 2025-8-22 15:46:52 | 显示全部楼层
本帖最后由 橡皮 于 2025-8-22 15:49 编辑

原来代码在插件卸载时没有写 wxwidgets 主窗口处理,会导致卸载的时候程序崩溃。。。。忘了这个了
下边是卸载前要做的
  1. void CleanupWxWidgets() {
  2.   if (wxStarted) {
  3.     wxTheApp->OnExit();
  4.     wxEntryCleanup();
  5.     wxStarted = false;
  6.   }
  7. }

  8. virtual AcRx::AppRetCode On_kUnloadAppMsg (void *pkt) {
  9.   CleanupWxWidgets();
  10.   AcRx::AppRetCode retCode =AcRxArxApp::On_kUnloadAppMsg (pkt) ;
  11.   return (retCode) ;
  12. }
复制代码



回复 支持 反对

使用道具 举报

发表于 2025-8-21 16:31:21 | 显示全部楼层
wxwidgets 是跨平台的
回复 支持 反对

使用道具 举报

发表于 2025-8-22 12:36:28 | 显示全部楼层
我看官方3.3低版本vc已经没有支持了,
如果不需要编译低版本ObjectARX,还是可以使用.
个人观点,如果是开发ObjecARX,没有跨平台需求感觉意义不是很大.

ps:另外我试了下,也可能是我技术不行,模态对话框有点别扭.好像设置父窗口不太行,.感觉还没duilib容易融合.

回复 支持 反对

使用道具 举报

发表于 2025-8-22 14:18:06 来自手机 | 显示全部楼层
我是下载过程中就断,一直下载不了。看看这个ui
回复 支持 反对

使用道具 举报

 楼主| 发表于 2025-8-22 14:46:03 | 显示全部楼层
gzxl 发表于 2025-8-22 14:18
我是下载过程中就断,一直下载不了。看看这个ui

稍等我搞个自己的云盘链接
回复 支持 反对

使用道具 举报

 楼主| 发表于 2025-8-22 14:48:08 | 显示全部楼层
edata 发表于 2025-8-22 12:36
我看官方3.3低版本vc已经没有支持了,
如果不需要编译低版本ObjectARX,还是可以使用.
个人观点,如果是开发 ...

设置父窗口不太行是个什么情况啊
回复 支持 反对

使用道具 举报

 楼主| 发表于 2025-8-22 14:53:22 | 显示全部楼层
gzxl 发表于 2025-8-22 14:18
我是下载过程中就断,一直下载不了。看看这个ui

https://4brubberi-my.sharepoint. ... 7RyCrDrcIQ?e=vBW1R1
回复 支持 反对

使用道具 举报

发表于 2025-8-22 16:23:21 来自手机 | 显示全部楼层
SetParent设置cad窗口无效,模态窗口不能禁用父窗口,手动禁用和解禁等会闪屏。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|CAD论坛|CAD教程|CAD下载|联系我们|关于明经|明经通道 ( 粤ICP备05003914号 )  
©2000-2023 明经通道 版权所有 本站代码,在未取得本站及作者授权的情况下,不得用于商业用途

GMT+8, 2025-10-6 01:46 , Processed in 0.193045 second(s), 28 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表