Qt ObjectARX实现获取AutoCAD的实体的DXF数据

发布时间 2023-10-17 11:52:42作者: 一杯清酒邀明月

ObjectARX为Auto CAD的二次开发工具。

准备工作:

1) Visual studio2017

2) QT4.12.2

3) Auto CAD2020

4) ObjectArx 2020 SDK

5) ObjectArx Wizard 2020向导

以上是需要用到的软件和环境,本文对环境搭建不做阐述,重在记录实现功能。

实现的功能介绍:

Auto CAD命令行中有自带获取实体数据的命令"LIST"。使用Ctrl+F2打开CAD文本窗口,输入LIST命令,选中实体获取数据。

但是这样获取到的数据只能呈现在Auto CAD软件中,如若我们要将数据传输到QT或QML中,然后使用这些数据在QT或QML中画出相应图像或者用这些数据做其它事情,我们应该如何实现呢? 

整体框架一览:

前提:必须已完成本文章开头实现ObjectARX+QT与CAD交互功能 !!!

First:代码展示

Second:代码解释

Third:运行结果展示(图片)。

Fourth:总结

代码展示:所有代码展示完的下方有对于代码的解释。

dialog.cpp代码:

  1 #include "dialog.h"
  2 #include "ui_dialog.h"
  3 #include<tchar.h>
  4  
  5  
  6 Dialog::Dialog(QWidget *parent) :
  7     QDialog(parent),
  8     ui(new Ui::Dialog)
  9 {
 10     ui->setupUi(this);
 11     th1 = new xiancheng();
 12  
 13     connect(th1,SIGNAL(sendData(int)),this,SLOT(recvData(int)));
 14     connect(this,SIGNAL(sendAllData(std::string)), th1,SLOT(recvAllData(std::string)));
 15 }
 16  
 17 Dialog::~Dialog()
 18 {
 19     delete ui;
 20 }
 21  
 22 int nCount = 0;
 23  
 24  
 25  
 26  
 27 std::string g_sAllData = "";
 28 /*获得实体数据 实际为非扩展数据*/
 29 void Dialog::on_pushButton_4_clicked(){
 30  
 31     dataSize_T data;
 32     data.str = "56789";
 33     data.nSize = data.str.length();
 34  
 35  
 36          ads_name ename;
 37          if(acedSSGet(NULL,NULL,NULL,NULL,ename) ==RTNORM ){
 38  
 39          int nLenth;
 40          acedSSLength(ename,&nLenth);
 41          acutPrintf(TEXT("\n select sets count is :%d"),nLenth);
 42  
 43          ui->textEdit_3->setText("\n aha The Following Content is Total Data:");
 44          for(int y=0; y<nLenth; y++){
 45              ads_name entres;
 46              acedSSName(ename,y,entres);    //将获取的名字放入entres.
 47              AcDbObjectId entid;
 48              acdbGetObjectId(entid,entres);
 49  
 50              ads_name entName;
 51              acdbGetAdsName(entName,entid);
 52  
 53              int rt, i;
 54              ads_point pt;
 55              struct resbuf *rbEnt; // 保存实体数据的结果缓冲区
 56              struct resbuf* pBuf;
 57  
 58 //                 if(acedEntSel(TEXT("\n请选择实体:"),entName,pt)){
 59 //                 }
 60                  rbEnt =acdbEntGet(entName);
 61                  pBuf = rbEnt;
 62                  TCHAR buf[133];
 63  
 64                  for (i = 0; pBuf != NULL; i++, pBuf = pBuf->rbnext) {
 65                      if (pBuf->restype < 0)
 66                          rt = pBuf->restype;
 67                      else if (pBuf->restype < 10)
 68                          rt = RTSTR;
 69                      else if (pBuf->restype < 38)
 70                          rt = RT3DPOINT;
 71                      else if (pBuf->restype < 60)
 72                          rt = RTREAL;
 73                      else if (pBuf->restype < 80)
 74                          rt = RTSHORT;
 75                      else if (pBuf->restype < 100)
 76                          rt = RTLONG;
 77                      else if (pBuf->restype < 106)
 78                          rt = RTSTR;
 79                      else if (pBuf->restype < 148)
 80                          rt = RTREAL;
 81                      else if (pBuf->restype < 290)
 82                          rt = RTSHORT;
 83                      else if (pBuf->restype < 330)
 84                          rt = RTSTR;
 85                      else if (pBuf->restype < 370)
 86                          rt = RTENAME;
 87                      else if (pBuf->restype < 999)
 88                          rt = RT3DPOINT;
 89                      else
 90                          rt = pBuf->restype;
 91  
 92                      switch (rt) {
 93                      case RTSHORT:
 94                          if (pBuf->restype == RTSHORT){
 95                              acutPrintf(TEXT("RTSHORT : %d\n"),
 96                                             pBuf->resval.rint);
 97                              ui->textEdit_3->append(QStringLiteral("\n RTSHORT:")+ ',' +(QString::number(pBuf->resval.rint)));
 98                              g_sAllData += QString::number(pBuf->resval.rint).toStdString() + '\n';
 99                          }
100                          else{
101                              acutPrintf(TEXT("(%d . %d)\n"), pBuf->restype,
102                                             pBuf->resval.rint);
103                              ui->textEdit_3->append(QStringLiteral("\n RTSHORT:") + ',' + (QString::number(pBuf->restype)) + ',' + (QString::number(pBuf->resval.rint)));
104                              g_sAllData += QString::number(pBuf->restype).toStdString() + '\n';
105                              g_sAllData += QString::number(pBuf->resval.rint).toStdString() + '\n';
106                          }
107                          break;
108                      case RTREAL:
109                          if (pBuf->restype == RTREAL){
110                              acutPrintf(TEXT("RTREAL : %0.3f\n"),
111                                             pBuf->resval.rreal);
112                              ui->textEdit_3->append(QStringLiteral("\n RTREAL:") + ',' + QString::number(pBuf->resval.rreal,'f',2));
113                              g_sAllData += QString::number(pBuf->resval.rreal).toStdString() + '\n';
114                          }
115                          else{
116                              acutPrintf(TEXT("(%d . %0.3f)\n"), pBuf->restype,
117                                                pBuf->resval.rreal);
118                               ui->textEdit_3->append(QStringLiteral("\n RTREAL:") + ',' + QString::number(pBuf->restype) + ',' + QString::number(pBuf->resval.rreal,'f',2));
119                               g_sAllData += QString::number(pBuf->restype).toStdString()  + '\n';
120                               g_sAllData += QString::number(pBuf->resval.rreal).toStdString() + '\n';
121                          }
122                          break;
123                      case RTSTR:
124                          if (pBuf->restype == RTSTR){
125                              acutPrintf(TEXT("RTSTR : %s\n"),
126                                         pBuf->resval.rstring);
127                               ui->textEdit_3->append(QStringLiteral("\n RTSTR:") + ',' + QString::fromWCharArray(pBuf->resval.rstring));
128                               g_sAllData +=  QString::fromWCharArray(pBuf->resval.rstring).toStdString() + '\n';
129                          }
130                          else{
131                              acutPrintf(TEXT("(%d . \"%s\")\n"), pBuf->restype,
132                                              pBuf->resval.rstring);
133                              ui->textEdit_3->append(QStringLiteral("\n RTREAL:") + ',' + QString::number(pBuf->restype) + ',' + QString::fromWCharArray(pBuf->resval.rstring));
134                              g_sAllData += QString::number(pBuf->restype).toStdString() + '\n';
135                              g_sAllData += QString::fromWCharArray(pBuf->resval.rstring).toStdString() + '\n';
136                          }
137                          break;
138                      case RT3DPOINT:
139                          if (pBuf->restype == RT3DPOINT){
140                              acutPrintf(
141                                  TEXT("RT3DPOINT : %0.3f, %0.3f, %0.3f\n"),
142                                  pBuf->resval.rpoint[X],
143                                  pBuf->resval.rpoint[Y],
144                                  pBuf->resval.rpoint[Z]);
145                              QString pop = QString::number( pBuf->resval.rpoint[X],'f',2);
146  
147                             ui->textEdit_3->append(QStringLiteral("\n RT3DPOINT:") + ',' + QString::number(pBuf->resval.rpoint[X],'f',2) + ',' + QString::number(pBuf->resval.rpoint[Y],'f',2) + ',' + QString::number(pBuf->resval.rpoint[Z],'f',2));
148                             g_sAllData += QString::number(pBuf->resval.rpoint[X]).toStdString() + '\n';
149                             g_sAllData += QString::number(pBuf->resval.rpoint[Y]).toStdString() + '\n';
150                             g_sAllData += QString::number(pBuf->resval.rpoint[Z]).toStdString() + '\n';
151                          }
152                          else{
153                              acutPrintf(
154                                  TEXT("(%d %0.3f %0.3f %0.3f)\n"),
155                                  pBuf->restype,
156                                  pBuf->resval.rpoint[X],
157                                  pBuf->resval.rpoint[Y],
158                                  pBuf->resval.rpoint[Z]);
159                              ui->textEdit_3->append(QStringLiteral("\n RT3DPOINTTwo:") + ',' + QString::number(pBuf->restype,'f',2) + ',' + QString::number(pBuf->resval.rpoint[X],'f',2) + ',' + QString::number(pBuf->resval.rpoint[Y],'f',2) + ',' + QString::number(pBuf->resval.rpoint[Z],'f',2));
160                              g_sAllData += QString::number(pBuf->restype).toStdString() + '\n';
161                              g_sAllData += QString::number(pBuf->resval.rpoint[X]).toStdString() + '\n';
162                              g_sAllData += QString::number(pBuf->resval.rpoint[Y]).toStdString() + '\n';
163                              g_sAllData += QString::number(pBuf->resval.rpoint[Z]).toStdString() + '\n';
164                          }
165                          break;
166                      case RTLONG:
167                          acutPrintf(TEXT("RTLONG : %d\n"),
168                                         pBuf->resval.rlong);
169                          ui->textEdit_3->append(QStringLiteral("\n RTLONG:") + QString::number(pBuf->resval.rlong));
170                          g_sAllData += QString::number(pBuf->resval.rlong).toStdString() + '\n';
171                          break;
172                      case -1:
173                      case RTENAME:
174                          acutPrintf(TEXT("(%d<Entity name:>)\n"),
175                                      pBuf->restype, pBuf->resval.rlname[0]);
176                          ui->textEdit_3->append(QStringLiteral("\n <Entity name: %x>:") + ',' + QString::number(pBuf->resval.rlname[0],16));
177                          g_sAllData +=  QString::number(pBuf->resval.rlname[0]).toStdString() + '\n';
178                          break;
179                      case -3:
180                          acutPrintf(TEXT("(-3)\n"));
181                          ui->textEdit_3->append("(-3)");
182                          g_sAllData += "(-3)" + '\n';
183                      }
184  
185                      if ((i == 23) && (pBuf->rbnext != NULL)) {
186                          i = 0;
187                          acedGetString(0,
188                              TEXT("Press <ENTER> to continue..."), buf);
189                      }
190                  }
191  
192          }
193     }
194     emit sendAllData(g_sAllData);
195     g_sAllData = "";
196     return;
197  
198 }
199  
200  
201 /*连接服务器*/
202 void Dialog::on_pushButton_clicked(){
203  
204  
205     th1->start();
206     acutPrintf(TEXT("i am Client"));
207 }
208  
209 void Dialog::recvData(int data){
210  
211     nCount = data;
212  
213 }
214  
215 void Dialog::on_pushButton_2_clicked(){
216  
217     acutPrintf(TEXT("\n nCount:%d"),nCount);
218 }
219  
220  
221 void Dialog::on_pushButton_3_clicked(){
222  
223     //emit sendAllData(g_sAllData);
224 }

dialog.h代码:

 1 #ifndef DIALOG_H
 2 #define DIALOG_H
 3  
 4 #include <QDialog>
 5 #include <Windows.h>
 6 #include <arxHeaders.h>
 7 #include <acedCmdNF.h>
 8  
 9 #include "xiancheng.h"
10  
11  
12 namespace Ui {
13 class Dialog;
14 }
15  
16 class Dialog : public QDialog
17 {
18     Q_OBJECT
19  
20 public:
21  
22     explicit Dialog(QWidget *parent = nullptr);
23     ~Dialog();
24  
25 signals:
26  
27     void sendAllData(std::string data);
28  
29  
30 private slots:
31  
32     void recvData(int data);
33  
34     void on_pushButton_4_clicked();
35  
36     void on_pushButton_clicked();
37  
38     void on_pushButton_2_clicked();
39  
40     void on_pushButton_3_clicked();
41  
42 private:
43     Ui::Dialog *ui;
44  
45     xiancheng* th1;
46  
47  
48  
49 };
50  
51 #endif // DIALOG_H

 this_main.cpp代码:

  1 #pragma warning( push)
  2 #pragma warning (disable: 4189 4100 )
  3 //#define _AFXDLL
  4 //#define _AFXDLL
  5 #include <Windows.h>
  6 #include <arxHeaders.h>
  7 #include "Dialog.h"
  8 #pragma warning( pop)
  9 #include<QtWidgets/QApplication>
 10 #include <string_view>
 11 #include <iostream>
 12 #include <string>
 13 #include <fstream>
 14 #include <cstring>
 15 #include <string.h>
 16 #include <QString>
 17 #include <QStringList>
 18 #include <QLabel>
 19 #include <stdio.h>
 20 //#include <rxmfcapi.h>
 21  
 22 //#include <afx.h>
 23  
 24  
 25  
 26 using namespace std::string_literals;
 27  
 28 #include <QtWidgets>
 29 #include <QtQml>
 30 #include <QMessageBox>
 31  
 32 struct resbuf* pBuf;
 33 int flag = 0;
 34 int i = 0;
 35 double dCount[10];
 36 namespace {
 37 namespace _cpp_private {
 38 const std::string qtApplicationPath = "123";/*!!!*/
 39 //#if _OBJECT_ARX_VERSION_X64_ == 2018
 40 //            u8R"(D:\Program Files\AutoCAD 2018\acad.exe)"s;
 41 //#else
 42 //            u8R"(D:\Program Files\AutoCAD 2022\AutoCAD 2022\acad.exe)";
 43 //#endif
 44 inline int & getArgc() {
 45     static int ans;
 46     ans = 1;
 47     return ans;
 48 }
 49 inline char** getArgv() {
 50     static char acadpath[] =u8R"(E:\AutoDesk CAD\AutoCAD 2020\acad.exe)";
 51     static char *argv[] = { nullptr };
 52     std::copy(qtApplicationPath.begin(), qtApplicationPath.end(),
 53               static_cast<char*>(acadpath));
 54     argv[0] = static_cast<char *>(acadpath);
 55     return argv;
 56 }
 57 }
 58 }/*namespace*/
 59  
 60 inline void ShowQtWindow() {
 61  
 62     Dialog *p = new Dialog;
 63     p->setAttribute(Qt::WA_DeleteOnClose);// 应用控件时自动释放
 64  
 65     p->show();
 66  
 67 }
 68  
 69  
 70 extern "C" AcRx::AppRetCode
 71 acrxEntryPoint(AcRx::AppMsgCode msg, void* pkt) {
 72     switch (msg) {
 73     case AcRx::kInitAppMsg: {
 74         acrxDynamicLinker->unlockApplication(pkt);
 75         acrxRegisterAppMDIAware(pkt);
 76         /*****************************************/
 77         {
 78             if (qApp == nullptr) {
 79                 /*create the qt applicaton and never destory it*/
 80                 auto varQtApplication =
 81                         new QApplication(_cpp_private::getArgc(), _cpp_private::getArgv());
 82                 (void)varQtApplication;
 83             }
 84             {
 85                 /*force to load images plugins*/
 86                 QImage varImage{ QString(":/png/this.png") };
 87                 varImage.width();
 88                 varImage.height();
 89             }
 90         }
 91         /*****************************************/
 92         acedRegCmds->addCommand(
 93                     L"SSTD_GLOBAL_CMD_GROUP",
 94                     L"ShowQtWindow",
 95                     L"ShowQtWindow",
 96                     ACRX_CMD_MODAL,
 97                     &ShowQtWindow);
 98  
 99  
100     }break;
101     case AcRx::kUnloadAppMsg: {}break;
102     default:break;
103     }
104     return AcRx::kRetOK;
105 }
106  
107  
108  
109 /********************************/
110  

xiancheng.cpp代码:

 1 #include "xiancheng.h"
 2 xiancheng::xiancheng()
 3 {
 4  
 5 }
 6 int nRnt = 99;
 7 std::string g_sDxfData = "";
 8  
 9  
10 char cBuff[50];
11  
12  
13 void xiancheng::run(){
14  
15     char cPop[100];
16  
17     char sBuff[20]={'0','1','2','3','4','5','6','7','8','9'};
18     std::string str = "123456789";
19     char sBuffLenth[5];
20     std::string sSum = "";
21  
22     int nClientSock = socket(AF_INET, SOCK_STREAM, 0);
23  
24     struct sockaddr_in serverAddr;
25     memset(&serverAddr, 0, sizeof (serverAddr));
26     serverAddr.sin_family = AF_INET;
27     serverAddr.sin_port = htons(写端口);
28     serverAddr.sin_addr.s_addr = inet_addr("写IP地址");
29  
30     int nRet = ::connect(nClientSock, (struct sockaddr*)&serverAddr, sizeof(serverAddr));
31     if(nRet < 0){
32  
33     }
34          itoa(g_sDxfData.length(),cPop,10);
35          int nLenths = send(nClientSock, cPop, sizeof(cPop), 0);
36          if(nLenths > 0){
37  
38          }
39          nRnt = send(nClientSock, g_sDxfData.c_str(), g_sDxfData.length(), 0);
40          acutPrintf(TEXT("Socket send data to Service"));
41          emit sendData( g_sDxfData.length());
42          g_sDxfData = "";
43          if(nRnt < 0){
44          }
45          else{
46  
47          }
48  
49 }
50  
51 void xiancheng::recvAllData(std::string data){
52  
53         g_sDxfData = data;
54         acutPrintf(TEXT("CAD recv all DXF data"));
55         //memcpy(cBuff,&data,sizeof(data));
56 }

xiancheng.h代码:

 1 #ifndef XIANCHENG_H
 2 #define XIANCHENG_H
 3  
 4 #include <QThread>
 5 #include <QDebug>
 6  
 7 #include <string>
 8 #include <Windows.h>
 9 #include <winsock.h>
10 #include <arxHeaders.h>
11 #include <acedCmdNF.h>
12 #include <tchar.h>
13  
14 typedef struct data_T{
15  
16    int nSize;
17    std::string str;
18 }dataSize_T;
19  
20 class xiancheng:public QThread
21 {
22     Q_OBJECT
23 public:
24     xiancheng();
25  
26     void run();
27 signals:
28     void sendData(int data);
29  
30 private slots:
31  
32     void recvAllData(std::string data);
33 };
34  
35 #endif // XIANCHENG_H

代码解析:

dialog.cpp:

此代码最主要部分为on_pushButton4_clicked()函数部分,第二个for循环上方部分为选择实体,可以选择单个实体或者多个实体。第二个for循环下方里面为获取实体的所有数据。

 this_main.cpp: 

ShowQtWindow()函数为展示QT的UI界面。将此函数通过命令形式在CAD中打开用到的是下图的方式。在CAD中输入"ShowQtWindow"语句后可以在CAD中打开QT的界面

xiancheng.cpp:

此代码编写的是一个Socket的客户端用于将dialog.cpp代码中获取到的CAD实体数据传输给服务端。

运行结果:

1)在Auto CAD的命令行中输入ShowQtWindow(命令可以随意命名,在this_main.cpp中修改)打开QT界面获取实体数据。

  2)将获取到的实体数据通过Socket传输到另外一个QT项目中。

总结:

1) 实现的功能是,通过手动选择的方式获取到Auto CAD中实体的数据并将其传输到QT中。

2)本文章未展示Socket服务端方面的代码(因为在另外一个QT项目工程里非此项目工程)。不过服务端项目工程也只是接收本文章客户端方面发来的数据,仅此而已。

3)ObjectARX对于Auto CAD的二次开发过程中会有很多问题,需要耐心解决和细心研究。

4)本文章代码编写方法以及代码编写规范等其它方面还有很多不足之处,请各位见谅。如若各位看官有独到见解还望不吝赐教。