Тема: Automation в AutoCAD с VC++
Может у кого есть пример кода? Было бы неплохо
Информационный портал для профессионалов в области САПР
Вы не вошли. Пожалуйста, войдите или зарегистрируйтесь.
Форумы CADUser → Программирование → Разное → Automation в AutoCAD с VC++
Страницы 1
Чтобы отправить ответ, вы должны войти или зарегистрироваться
Может у кого есть пример кода? Было бы неплохо
// ObjectARX defined commands
#include "StdAfx.h"
#include "StdArx.h"
char* Decode (char*);
char* Recode (char*);
void Body_work (char*);
// This is command 'DECODE'
void decoddecode()
{
// TODO: Implement the command
char flag = 'd';
Body_work(&flag);
}
// This is command 'RECODE'
void decodrecode()
{
// TODO: Implement the command
char flag = 'r';
Body_work(&flag);
}
void Body_work (char *flag)
{
// TODO: Implement the command // TODO: Implement the command
struct resbuf eb1, *tr_obj, *p;
char sbuf1[5]; // Buffers to hold strings
char *nl;
char* txt1;
ads_name ssname1, object1;
long ilast, i;
eb1.restype = 0; // Entity type group
strcpy(sbuf1, "TEXT");
eb1.resval.rstring = sbuf1; // Entity type is text.
eb1.rbnext = NULL;
acedSSGet(NULL, NULL, NULL, &eb1, ssname1);
acedSSLength(ssname1, &ilast);
//acutPrintf("\nCounts quantity objects : %d", ilast);
switch (*flag)
{
case 'd':
acedSetStatusBarProgressMeter("Decode text in R15 format", 0, ilast);
//break;
case 'r':
acedSetStatusBarProgressMeter("Recode text in R12 format", 0, ilast);
default:
break;
}
for (i = 0;irbnext)// DXF code string search
//if ((p->restype >= 0) && (p->restype restype = 1;
if (p->restype == 1) // if DXF code = string
{
txt1= p->resval.rstring;
if(*flag == 'd')
nl = Decode (txt1);
else
nl = Recode (txt1);
strcpy(p->resval.rstring, nl);
// acutPrintf(" Context : %s", txt1);
// модификатор
if (acdbEntMod(tr_obj) != RTNORM) // если объект можно модифицировать
{
acutRelRb(tr_obj);
//return 0; // Error
}//End модификотор
break; // From the for loop
} // end if DXF code = string
acutRelRb(tr_obj); // Release result buffer.
acedSetStatusBarProgressMeterPos(i);
}// end search object
acedRestoreStatusBar();
acedSSFree(ssname1);
}// body work
char* Decode (char* text)
{
int i,num;
unsigned char a;
char* old_text=new char[strlen(text)+1];
strcpy(old_text,text);
num = strlen (text);// количество букв
for(i = 0;i127)&&(a211))>255)
{
strcpy(text , old_text);
// acutPrintf("\nСработало");
break;
}
else
a=a + 64*((a>127)&&(a211);
text[i]=a;
//acutPrintf(" a после = %d",a);
}
delete[strlen(old_text)+1] old_text;
return text;
}
char* Recode (char* text)
{
int i,num;
unsigned char a;
char* old_text=new char[strlen(text)+1];
strcpy(old_text,text);
num = strlen (text);// количество букв
for(i = 0;i191)&&(a239))191)&&(a239);
text[i]=a;
//acutPrintf(" a после = %d",a);
}
delete[strlen(old_text)+1] old_text;
return text;
}
P.S.
Это конвертор для текста из акада r12 в r15 и обратно
Написан криво но работает.
Хотелось бы еще увидеть примеры проектов на ARX.
Я не совсем точно сформулировал: Мне нужно из моего приложения вызвать акад, открыть чертеж, вставить блоки и закрыть. Приложение делаю на VC++.
На VC++ нету
А на VB5 есть под ACAD14 но цепляет и ACAD2000
Hi, Вячеслав
Следует из своего приложения запустить Автокад, создав новый процесс(например, CreateProcess(NULL, szCommandLine, NULL, NULL,...), а затем с помощью EnumWindowsProc найти HWND его главного окна и послать ему сообщение WM_COPYDATA, предварительно задав структуре PCOPYDATASTRUCT ту команду, которую надо выполнить в Автокаде. Так можно заставить Автокад выполнять любые команды из внешней программы, не обязательно написанной на С++.
VVV
ИМХО делаеться проще...
Я коннектюсь к Автокаду через COM, создаю объект типа acadDoc(ThisDrawing), а затем практически все команды которые есть в VBA работают...
Правда кодилось не в VC++, а в Делфях, но если интересно код могу выложить.
Сделать то, что хочет Вячеслав Кокорев можно из любой программы, поддерживающей технологию COM. Хоть на VC++, хоть на Delphi деланной. Хоть на VB. Причем разными способами, в зависимости от сложности задачи.
Можно сделать, как рекомендует VVV. В этом случае гарантируется, что Автокад запущен к моменту посылки команды. В качестве команды лучще послать LISP-выражение, это проще, чем писать на VC++ конкретную команду, которую еще не раз придется переделывать.
Можно сделать, как рекомендует Savage. При этом можно посылать "команды" вслепую (но их надо знать точно), а можно импортировать библиотеку типов. В этом случае ваша программа будет знать объекты и методы Автокада и компилятор не пропустит неправильные действия. Но еще не факт, что правильные, с точки зрения компилятора действия, Автокад выполнит, как задумано.
В любом случае (для реальных программ), надо учитывать, что на компьютере может быть несколько Автокадов, разных версий и надо предварительно (программно) выбирать требуемый и запускать именно его. В этом отношении совет VVV лучше, так как он позволяет предварительно сформировать правильную szCommandLine.
Q. Вопрос с ShaggyDoc-у. Я, честно говоря, не очень понял, почему это ?лучще послать LISP-выражение, ? чем писать на VC++ конкретную команду?? ? Чем это лучше и проще? Какая тут мысль имелась ввиду?
С уважением, VVV
Позвольте ответить на ваш вопрос VVV.
ShaggyDoc, верно подметил, что действительно лучше посылать отлаженный кусок ЛИСП кода, чем повторять те же действия, но скажем в VC, не придеться отлаживать именно ЭТОТ кусок, который что-то делает в АКАДЕ...
2ShaggyDoc.
Не подскажите где можно взять эту самую "библиотеку типов"?
> В этом отношении совет VVV лучше, так как он позволяет предварительно сформировать правильную szCommandLine.
позвольте с вами не согласиться, что же мешает сделать выбор необходимый для этой версии набора комманд, прям в куске кода? замедте, при это не придеться возится с апишными функциями.
Прошу прощения, но мне кажется, что добровольный адвокат ShaggyDoc-а еще больше запутал вопрос. При чем тут удобство работы с отлаженным куском кода, когда речь идет просто о способе передачи данных от одного приложения к другому. Автокад пытается выполнить как команду, то что передается его главному окну. Конечно он обработает и кусок лисп-кода. Но какой смысл с помощью сообщения предавать этому окну непонятного размера ?отлаженный кусок кода?, если можно из внешнего приложения просто послать ему короткое имя лисп или ARX команды-функции(предварительно загруженной в автокад к-либо образом, в том числе, путем передачи команды загрузки из внешней программы) или родной автокадовской команды. При этом никто не мешает сколько угодно отлаживать, как само внешнее приложение, так и уже ?отлаженный кусок кода?, который отрабатывает в среде Автокада. Лишь бы название той команды, которую посылает внешняя программа не менялось. Возможно, я что-то недопонял в предложении ShaggyDoc-а, и именно поэтому просил его разъяснить мне свою точку зрения.
VVV прав.
Я имел ввиду, что лучше послать в командную строку Автокада именно Лисп-выражение. Это может быть и вызов уже загруженной функции, например "(my_func "block_name")", или загрузка Лисп-программы, которая сразу что-то будет делать, например "(load "import.lsp")". Это может быть и готовая программа, и сгенерированная "на лету".
В простейших случаях можно отправить и выражение типа
(command "_.INSERT" "BLOCK_NAME" .....). Или просто в виде последовательности требуемых нажатий клавиш. Но только в простых случаях.
Я предпочитаю посылать (load ....). В этом случае работает отлаженная программа, в которой имеется и обработка ошибок, и проверка корректности данных.
>Относительно "чем писать на VC++ конкретную команду".
Разумеется, особо сложного здесь нет. Например, для вставки блока. А вот для создания более сложных объектов, хотя бы полилиний, надо программно формировать и объекты вершин, и массив вершин. Да еще чтобы было правильно. Да еще с учетом того, что бывают разные механизмы. Поэтому иногда бывает проще делать требуемые данные в виде текста, и обрабатывать их Lisp.
>Savage
Библиотека типов (Type Library) - это файл с расширением .TLB.
Именно в библиотеках типов описано, что и как может делать COM-сервер. Для Автокада это ACAD.TLB, живущий рядом с ACAD.EXE
VVV (2002-02-06 15:54:30)
VVV можно ли увидеть пример заполнения структуры PCOPYDATASTRUCT с передачей сообщения?
С уважением...
> alex
void SendCmdToAcad(CString& cmd) { COPYDATASTRUCT cmdMsg; cmdMsg.dwData = (DWORD)1; cmdMsg.cbData = (DWORD)_tcslen(cmd) + 1; cmdMsg.lpData = cmd.GetBuffer(cmd.GetLength()+1); ::SendMessage(HWND_ACAD, WM_COPYDATA, NULL, (LPARAM)&cmdMsg); }
HWND_ACAD - это HWND главного окна AutoCAD, которое нужно найти при помощи функции ::EnumWindows(...)
Спасибо, Александр!
Не знаю даже как Вас благодарить!
Вы уже неоднократно выводили меня из тупика!
Буду пробовать.
Я в цикле через FindWindow(...) нахожу HWND открытого Автокада. Передаю команду - но в ответ тишина :(
Ниже две функции - одна ищет открытое окно Автокада, другая передает команду Автокаду.
Я получаю такой же указатель как и Spy++.
Что здесь не так?
HWND CMSetup::FindHwAcad()
{
HWND hWnd=NULL;
char psv[100];
CString sv=_T("AutoCAD 2008");
hWnd=FindWindow(NULL,NULL);
while(hWnd)
{
::GetWindowText(hWnd,psv,100);
if(strstr(psv,sv))
{
return hWnd;
}
hWnd=::GetWindow(hWnd,GW_HWNDNEXT);
}
return NULL;
}
void CMSetup::SendCmdAcad(HWND hwaAcad,CString &cmd)
{
COPYDATASTRUCT cmdMsg;
cmdMsg.dwData = (DWORD)1;
cmdMsg.cbData = (DWORD)_tcslen(cmd) + 1;
cmdMsg.lpData = cmd.GetBuffer(cmd.GetLength()+1);
::SendMessage(hwaAcad, WM_COPYDATA, NULL, (LPARAM)&cmdMsg);
}
> alex
У тебя приложение уникодовское? Если нет - замени _tcslen на strlen. И не забываешь ли ты добавить пробел в конец команды? И не занят ли в этот момент AutoCAD другой работой? И т.д. и т.п.
Заменил, но результат тот же. Автокад в этот момент ничем не занят.
Конечный пробел в каманду вставил.
Может быть 2008 Акад не поддерживает этот сервис?
Спасибо.
Похоже ты все-таки не тому окну посылаешь SendMessage
При открытом Автокаде в Spy++ я брал указатели на окна Акада и подсовывал функции "SendCmdAcad(HWND hwaAcad,CString &cmd)", но результата не добился.
Может отладчик как-то мешает?
Попробовал в релизе - тоже ничего.
Может в Автокаде какую опцию нужно включить или выключить?
Может в Автокаде нужно включить или выключить какую-то опцию?
Поигрался с AutoCAD 2008 - действительно команда не отрабатывается. Так что изучай ActiveX-модель AutoCAD.
Ну, что же, спасибо и на том.
Спасибо тебе за терпение и время.
Хочу поднять эту "древнюю" тему
Поигрался с AutoCAD 2008 - действительно команда не отрабатывается. Так что изучай ActiveX-модель AutoCAD.
Возникла задача послать в АКАД 2010 команду через SendMessage. Сообщение посылается главному окну из внешнего приложения. Результат выполнения = 0. Имеет ли смысл продолжать "эксперименты" в этом направлении (ну там, найти окно ком. строки и в него посылать сообщение [а если оно закрыто?] и т. д.)?
Страницы 1
Чтобы отправить ответ, вы должны войти или зарегистрироваться
Форумы CADUser → Программирование → Разное → Automation в AutoCAD с VC++
Форум работает на PunBB, при поддержке Informer Technologies, Inc