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