Тема: Не выполняется команда Автокада в немодальном диалоге

Здравствуйте! Нужна помощь!
Диалог унаследован от CAdUiBaseDialog загружен как немодальный. По нажатию кнопки должна выполняться команда Автокада вставки блока - ничего не происходит!
Если вставляю команду в OnInitDialog - тогда успешно отрабатывает.
Как с этим бороться?

Re: Не выполняется команда Автокада в немодальном диалоге

> alex
Немодальные окна работают в Application Context, а команды - в контексте документа.

Re: Не выполняется команда Автокада в немодальном диалоге

Простите, может я задаю глупый вопрос.
Как мне получить контекст документа, что он из себя представляет и куда он исчезает после инициализации диалога. Если он еще доступен там, то каким образом я его могу перехватить?
Спасибо.

Re: Не выполняется команда Автокада в немодальном диалоге

> alex
Покопайте класс AcApDocManager и макрос acDocManager. На обработчик кнопки можно, например, повесить выражение:

acDocManager->sendStringToExecute(curDoc(), _T("_.CIRCLE 100,100,50 "));

Это означает выполнение команды в контексте текущего документа, хотя активен контекст приложения.

Re: Не выполняется команда Автокада в немодальном диалоге

Огромное спасибо!
Команды отрабатывают!
Можно ли таким образом выполнять и Лисповские программы?
Какие особенности или ограничения накладываются на командную строку?
Простите за наглость, в документации этой информации я не увидел.
И еще, все таки мне непонятно - acedCommand(...) являясь глобальной теряет связь с контекстом документа, но загрузка нового документа в Автокаде не выполнялась, или всякое окно система рассматривает как документ?

Re: Не выполняется команда Автокада в немодальном диалоге

alex пишет:

Можно ли таким образом выполнять и Лисповские программы?

Можно. Не забывай про завершающий пробел (или "\n") в командной строке.

И еще, все таки мне непонятно — acedCommand(...)

acedCommand нелья вызывать из обработчика немодального окна.
Единственный (но довольно существенный) недостсток  acDocManager->sendStringToExecute(...) - команда отработает в асинхронном режиме, когда AutoCAD получит управление. Соответственно после вызова acDocManager->sendStringToExecute() в своем обработчике кнопки ты не можешь расчитывать, что получишь результаты выполнения команды (в примере Николая Николаевича - окружность еще не будет отрисована).

Re: Не выполняется команда Автокада в немодальном диалоге

Да, я убедился в том что команды не завершены.
Пришлось выкручиваться через Лисповскую command.
Единственное, что в этом случае не воспринимается \ (слэш) двойной тоже не прошел их Автокад удаляет вчистую. Пришлось на лету менять каталог где находятся блоки и все отработало :).
Спасибо за помощь!!!

Re: Не выполняется команда Автокада в немодальном диалоге

С обратными косыми тоже разобрался, вместо "\\" подставил "/" и все получилось.

Re: Не выполняется команда Автокада в немодальном диалоге

> alex
Обратные слеши желательно заменить на прямые ("/"). Обратные слеши воспринимаются как пауза в команде.
Кроме того вместо того, чтобы использовать команду "_INSERT" ты мог сам написать ее аналог используя средства ObjectARX, который можно было бы вызывать и из обработчика немодального окна. Только необходимо было бы блокировать текущий документ:

acDocManager->lockDocument(curDoc());
// ... твой код ...
acDocManager->unlockDocument(curDoc());

Re: Не выполняется команда Автокада в немодальном диалоге

Спасибо, Александр!
Я, с ARXом еще на "Вы", когда-то писал на Лиспе и на ARXe 2000, но уже порядком все подзабыл. А тут как всегда времени в обрез :(
Так что пока по возможности обхожусь простейшими средствами...

Re: Не выполняется команда Автокада в немодальном диалоге

Вот обработчик клика по кнопке:
void DlgAddObj::OnBnClickedInsertBlock()
{
AcAxDocLock lock(acdbCurDwg());
if (lock.lockStatus() == Acad::eOk)
{
acutPrintf(L"Вставка блока...");
acedPostCommandPrompt();
CMDIFrameWnd* Frame = acedGetAcadFrame();
Frame->SetFocus();
acDocManager->sendStringToExecute(curDoc(),_T("(setq p1 (getpoint \"\n...:\"))"));
acDocManager->sendStringToExecute(curDoc(), _T("(command \"_.Insert\" \"E:/Works/XP/ESpec/Data/Blocks/KONT04h.dwg\" p1 \"1\" \"1\" \"\")\n"));
}
}
Все работает!
Вместо прямого пути, разумеется, вставляется любой путь. Координаты, масштабы и углы можно также запросить средствами Лиспа.
Порадовало и, можно сказать, удивило, что я получается на лету могу сконструировать Лисповскую программу и тут же ее выполнить. Для меня - это находка.
Может быть я рано радуюсь, может быть существуют какие либо ограничения?
Еще раз большое спасибо за консультации Александру и Николаю Николаевичу!

Re: Не выполняется команда Автокада в немодальном диалоге

> alex
У немодальных окон есть еще один недостаток - надо предусматривать, что при открытом немодальном окне пользователь закроет все открытые документы. Можно нарваться на аварийное завершение.

Re: Не выполняется команда Автокада в немодальном диалоге

Согласен.
Код который представлен выше не содержит проверок, но это не более чем заготовка, я надеюсь общество на это так и смотрит.
Потом я исхожу из тех соображений что менджер документов всякий раз при клике вернет указатель на текущий документ, который будет пустым при отсутствии такового.
Спасибо.

Re: Не выполняется команда Автокада в немодальном диалоге

void DlgAddObj::InsertBlock(const CString&path)
{
CFileFind ff;
if(ff.FindFile(path))
{
CString sp=path;
ads_name ename;
ads_point px;
sp.Replace('\\','/');
AcAxDocLock lock(acdbCurDwg());
if (lock.lockStatus() == Acad::eOk)
{
acutPrintf(L"Вставка блока...");
CString cmd;
cmd.Format(L"(command \"_.Insert\" \"%s\" p1 \"1\" \"1\" \"\" ) ",sp);
acedPostCommandPrompt();
CMDIFrameWnd* Frame = acedGetAcadFrame();
if(Frame)
{
Frame->SetFocus();
AcApDocument*pvd=curDoc();
if(pvd)
{
    acDocManager->sendStringToExecute(pvd,_T("(setq p1 (getpoint \"Введите точку вставки блока:\"))"));
    acDocManager->sendStringToExecute(pvd, cmd);
}
}
}
}
StoreLastItem(); // Здесь я пытаюсь сохранить метку примитива (вставляемого блока) в своей базе данных, но когда компилятор сюда приходит Автокад еще не собирается выполнять команду вставки блока (acDocManager->sendStringToExecute(...)) похоже, эта функция формирует некий буфер команд и при выходе из контекста текущей функции его выгружает.
Вопрос заключается в следующем, можно ли этот буфер выгрузить в нужный момент? Вполне допускаю, что я неправильно представляю механизм передачи команд автокаду.
}

Re: Не выполняется команда Автокада в немодальном диалоге

Я же уже писал что sendStringToExecute выполняется асинхронно по отношению к твоему коду. Поэтому воспользоваться результатами выполнения команды ты дальше в своем коде не сможешь. Переписывай INSERT с использованием средств ObjectARX. Чем быстрее ты поймешь что нужно это делать, а не воевать с sendStringToExecute, тем меньше потеряешь времени. Примеры на этом форуме есть.

Re: Не выполняется команда Автокада в немодальном диалоге

Да, я это уже понял. Хотя в этой ситуации выход ятаки нашел но это мне все меньше и меньше нравится. Я имею ввиду, использовать лисповские команды как основное средство для работы с Автокадом.
Я видел несколько тем посвященных вставке блоков, но мне показалось что код перегружен разными деталями. А поскольку я в этом деле новичек, то мне трудно выделить скелет алгоритма вставки. Если ты меня ткнешь носом в тему где вставляется просто блок я буду очень благодарен.
Впрочем в любом случае я тебе очень благодарен.
А выкрутился я просто, написал в ARXе функцию сохранения примитивов в базе и в этом же участке лиспа ее и вызвал.
Примерно так:
acDocManager->sendStringToExecute(pvd, _T("\\n(sitem (entget (entlast))) "));
Здесь: sitem - эта функция сохранения параметра примитива в базе. В этом случае все отрабатывает синхронно.