Тема: Automation в AutoCAD с VC++

Может у кого есть пример кода? Было бы неплохо wink

Re: Automation в AutoCAD с VC++

// 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.

Re: Automation в AutoCAD с VC++

Я не совсем точно сформулировал: Мне нужно из моего приложения вызвать акад, открыть чертеж, вставить блоки и закрыть. Приложение делаю на VC++.

Re: Automation в AutoCAD с VC++

На VC++ нету
А на VB5 есть под ACAD14 но цепляет и ACAD2000

Re: Automation в AutoCAD с VC++

Hi, Вячеслав
Следует из своего приложения запустить Автокад, создав новый процесс(например, CreateProcess(NULL, szCommandLine, NULL, NULL,...), а затем с помощью EnumWindowsProc найти HWND  его  главного окна и  послать ему  сообщение  WM_COPYDATA, предварительно задав структуре PCOPYDATASTRUCT  ту команду,  которую надо выполнить в Автокаде. Так можно заставить Автокад выполнять любые команды из внешней программы, не обязательно написанной  на С++.
VVV

Re: Automation в AutoCAD с VC++

ИМХО делаеться проще...
Я коннектюсь к Автокаду через COM, создаю объект типа acadDoc(ThisDrawing), а затем практически все команды которые есть в VBA работают...
Правда кодилось не в VC++, а в Делфях, но если интересно код могу выложить.

Re: Automation в AutoCAD с VC++

Сделать то, что хочет Вячеслав Кокорев можно из любой программы, поддерживающей технологию COM. Хоть на VC++, хоть на Delphi деланной. Хоть на VB. Причем разными способами, в зависимости от сложности задачи.

Можно сделать, как рекомендует VVV. В этом случае гарантируется, что Автокад запущен к моменту посылки команды. В качестве команды лучще послать LISP-выражение, это проще, чем писать на VC++ конкретную команду, которую еще не раз придется переделывать.

Можно сделать, как рекомендует Savage. При этом можно посылать "команды" вслепую (но их надо знать точно), а можно импортировать библиотеку типов. В этом случае ваша программа будет знать объекты и методы Автокада и компилятор не пропустит неправильные действия. Но еще не факт, что правильные, с точки зрения компилятора действия, Автокад выполнит, как задумано.

В любом случае (для реальных программ), надо учитывать, что на компьютере может быть несколько Автокадов, разных версий и надо предварительно (программно) выбирать требуемый и запускать именно его. В этом отношении совет VVV лучше, так как он позволяет предварительно сформировать правильную szCommandLine.

Re: Automation в AutoCAD с VC++

Q. Вопрос с ShaggyDoc-у. Я, честно говоря, не очень понял, почему это ?лучще послать LISP-выражение, ? чем писать на VC++ конкретную команду?? ? Чем это лучше и проще? Какая тут мысль имелась ввиду?
С уважением, VVV

Re: Automation в AutoCAD с VC++

Позвольте ответить на ваш вопрос VVV.
ShaggyDoc, верно подметил, что действительно лучше посылать отлаженный кусок ЛИСП кода, чем повторять те же действия, но скажем в VC, не придеться отлаживать именно ЭТОТ кусок, который что-то делает в АКАДЕ...

2ShaggyDoc.
Не подскажите где можно взять эту самую "библиотеку типов"?

> В этом отношении совет VVV лучше, так как он позволяет предварительно сформировать правильную szCommandLine.
позвольте с вами не согласиться, что же мешает сделать выбор необходимый для этой версии набора комманд, прям в куске кода? замедте, при это не придеться возится с апишными функциями.

Re: Automation в AutoCAD с VC++

Прошу прощения, но мне кажется, что добровольный адвокат ShaggyDoc-а еще больше запутал вопрос. При чем тут удобство работы с отлаженным куском кода, когда речь идет просто о  способе передачи данных от одного приложения к другому. Автокад  пытается выполнить как команду, то что передается его главному окну. Конечно он обработает и кусок лисп-кода. Но какой  смысл с помощью сообщения предавать этому окну  непонятного размера  ?отлаженный кусок кода?, если можно из внешнего приложения просто послать ему короткое имя  лисп или ARX команды-функции(предварительно загруженной  в автокад к-либо образом,  в том числе,  путем передачи команды загрузки  из внешней программы)  или родной автокадовской команды. При этом никто не мешает сколько угодно отлаживать,  как само внешнее приложение,  так и уже ?отлаженный кусок кода?,  который отрабатывает в среде Автокада.  Лишь бы название той команды,  которую посылает внешняя программа не менялось. Возможно,  я что-то недопонял в предложении ShaggyDoc-а, и именно поэтому  просил его  разъяснить мне свою точку зрения.

Re: Automation в AutoCAD с VC++

VVV прав.
Я имел ввиду, что лучше послать в командную строку Автокада именно Лисп-выражение. Это может быть и вызов уже загруженной функции, например "(my_func "block_name")", или загрузка Лисп-программы, которая сразу что-то будет делать, например "(load "import.lsp")". Это может быть и готовая программа, и сгенерированная "на лету".

В простейших случаях можно отправить и выражение типа
(command "_.INSERT" "BLOCK_NAME" .....). Или просто в виде последовательности требуемых нажатий клавиш. Но только в простых случаях.

Я предпочитаю посылать (load ....). В этом случае работает отлаженная программа, в которой имеется и обработка ошибок, и проверка корректности данных.

>Относительно "чем писать на VC++ конкретную команду".
Разумеется, особо сложного здесь нет. Например, для вставки блока. А вот для создания более сложных объектов, хотя бы полилиний, надо программно формировать и объекты вершин, и массив вершин. Да еще чтобы было правильно. Да еще с учетом того, что бывают разные механизмы. Поэтому иногда бывает проще делать требуемые данные в виде текста, и обрабатывать их Lisp.

>Savage
Библиотека типов (Type Library) - это файл с расширением .TLB.

Именно в библиотеках типов описано, что и как может делать COM-сервер. Для Автокада это ACAD.TLB, живущий рядом с ACAD.EXE

Re: Automation в AutoCAD с VC++

VVV (2002-02-06 15:54:30)
VVV можно ли увидеть пример заполнения структуры PCOPYDATASTRUCT с передачей сообщения?
С уважением...

Re: Automation в AutoCAD с VC++

> 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(...)

Re: Automation в AutoCAD с VC++

Спасибо, Александр!
Не знаю даже как Вас благодарить!
Вы уже неоднократно выводили меня из тупика!
Буду пробовать.

Re: Automation в AutoCAD с VC++

Будешь в Киеве - поблагодаришь! smile

Re: Automation в AutoCAD с VC++

Я в цикле через 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);
}

Re: Automation в AutoCAD с VC++

> alex
У тебя приложение уникодовское? Если нет - замени _tcslen на strlen. И не забываешь ли ты добавить пробел в конец команды? И не занят ли в этот момент AutoCAD другой работой? И т.д. и т.п.

Re: Automation в AutoCAD с VC++

Заменил, но результат тот же. Автокад в этот момент ничем не занят.
Конечный пробел в каманду вставил.
Может быть 2008 Акад не поддерживает этот сервис?
Спасибо.

Re: Automation в AutoCAD с VC++

Похоже ты все-таки не тому окну посылаешь SendMessage

Re: Automation в AutoCAD с VC++

При открытом Автокаде в Spy++ я брал указатели на окна Акада и подсовывал функции "SendCmdAcad(HWND hwaAcad,CString &cmd)", но результата не добился.
Может отладчик как-то мешает?
Попробовал в релизе - тоже ничего.

Re: Automation в AutoCAD с VC++

Может в Автокаде какую опцию нужно включить или выключить?

Re: Automation в AutoCAD с VC++

Может в Автокаде нужно включить или выключить какую-то опцию?

Re: Automation в AutoCAD с VC++

Поигрался с AutoCAD 2008 - действительно команда не отрабатывается. Так что изучай ActiveX-модель AutoCAD.

Re: Automation в AutoCAD с VC++

Ну, что же, спасибо и на том.
Спасибо тебе за терпение и время.

Re: Automation в AutoCAD с VC++

Хочу поднять эту "древнюю" тему

Александр Ривилис пишет:

Поигрался с AutoCAD 2008 - действительно команда не отрабатывается. Так что изучай ActiveX-модель AutoCAD.

Возникла задача послать в АКАД 2010 команду через SendMessage. Сообщение посылается главному окну из внешнего приложения. Результат выполнения = 0. Имеет ли смысл продолжать "эксперименты" в этом направлении (ну там, найти окно ком. строки и в него посылать сообщение [а если оно закрыто?] и т. д.)?

Сообщения 25

Тему читают: 1 гость

Страницы 1

Чтобы отправить ответ, вы должны войти или зарегистрироваться

Форумы CADUser → Программирование → Разное → Automation в AutoCAD с VC++