Тема: Как безопасно дать пользователю ввести точку?

Вот такая у меня проблема. Необходимо дать пользователю при вводе точки возможность выбора объектной привязки.
С вводом точки всё понятно - Acadapplication.ActiveDocument.Utility.GetPoint(EmptyParam,'Укажите точку: '). Но при таком раскладе, после этого любое отвлечённое действие пользователя ведёт к краху. При попытке выбора "прозрачной" комманды (к примеру 'Zoom) программа вылетает с ошибкой.
Сейчас делаю вот что.

//Acad:TAcadDocument
Acad.Utility.SendCommand('GetPoint' ),

где GetPoint-это

(defun C:GetPoint ()
  (SetVar "UserS2" "->false")
  (Setq Point (GetPoint "\n Укажите точку "))
  (SetVar "UserR1" (Nth 0 Point))
  (SetVar "UserR2" (Nth 1 Point))
  (SetVar "UserR3" (Nth 2 Point))
  (SetVar "UserS2" "->true")
  (princ)
)

После этого читаю точку в onEndLisp.
Может есть другие варианты?
AutoCAD 2002, Delphi.

Re: Как безопасно дать пользователю ввести точку?

Так делать нельзя! "Delphi - дельфиево, Автокаду - автокадово"
Внутри Автокада, если уж использована SendCommand (это правильное решение), надо выполнить все, что LISP может сделать. Незачем, например, занимать целых 4 системные переменные на никчемную информацию.
Если с точкой надо что-то сделать - пусть сделает LISP. А если ЭТОГО он не может сделать (что?), пусть вернет точку. Но это должна быть нормальная, работающая функция, а не сделанная на соплях.
В приведенном варианте если пользователь НЕ укажет точку, все остальное рухнет. EndLisp будет, а в UserSx может быть что угодно.

Re: Как безопасно дать пользователю ввести точку?

А если диалоговое окно сделано на Delphi и нужно из него указать точку, т.е. "временный выход".

Re: Как безопасно дать пользователю ввести точку?

> GRF
Очень хороший вопрос!!
Имеем два варианта:
1. Acad - сервер, Delphi - клиент. Тогда вся работа в Delphi, попытки достучаться до Автокада (а ему на эти стуки может быть некогда отвечать - например ZOOM Realtime включен) и имеем проблемы с исходным вопросом.
2. В Delphi-dll диалог, вызываемый из LISP. То есть Acad - клиент, Delphi-сервер. В этом случае диалог запущен модально и надо попытаться из него или вызвать Calllback-функцию (ее надо предусмотреть) и перейти к проблемам варианта 1. Да еще с учетом, что Автокад занят нашей же функцией, ждет ее завершения и вряд ли отзовется.
"Касивых" и "по науке" решений можно не найти. Но есть простое и надежное, но "неправильное" - изготовление обычного EXE, без ActiveX и запуск в модальном режиме.
В момент, когда надо, допустим, получить точку (да хоть что), выгружается программа, управление передается в вызвавший Лисп (с указанием по каким причинам закрылись), там делается нужное указание и снова загружается программа. Так делали еще в DOS, когда никаких ActiveX и не задумывалось.
Как передавать данные - догадайтесь с трех раз сами.

Re: Как безопасно дать пользователю ввести точку?

> ShaggyDoc
Почему, если пользователь не укажет точку, то всё рухнет? Усё под контролем. :)) Криво, нелепо, но работает как надо.
1. Если SendCommand проигнорирована акадом, то пользователь получает "AutoCAD занят... Зайдите завтра." ибо она в блоке try except, если нет- значит гарантированно знаем, что пошла GetPoint;
2. Если GetPoint была отменена (*Cancel*) или пользователь ввёл "марсианские" координаты, то в UserS2 у нас гарантированно "->false", если пользователь грамотный, то процедура прошла до конца и в UserS2 имеем "->true";
3. В onEndLisp анализируем UserS2 и если true- идём на обработку точки.
И если уж "гулять так гулять", то перед вызовом SendCommand ставим в UserS1 метку, типа "@MYCOMMAND", а в onEndLisp её анализируем, если не наша, то выходим, если наша- то пункт 3 и в конце ставим её в "@OTHER", чотб чужие не обрабатывать.
Немного конкретики: программа не является диалоговым окном. Она длитетельное время может висеть на экране (stayontop). Что то вроде "рекордера текстов программ для ЧПУ станка".

Re: Как безопасно дать пользователю ввести точку?

> Леприкон
"Почему, если пользователь не укажет точку, то всё рухнет? Усё под контролем. :)) Криво, нелепо, но работает как надо."
Работает, как надо, пока работает сам автор. Или в его присутствии.
Если в момент

(Setq Point (GetPoint "\n Укажите точку "))

будет дан пустой ответ в Point что будет? А если нажут Esc?
Как минимум, нужен

(initget 1)
(if (Setq Point (GetPoint "\n Укажите точку "))
 (progn
  что-то делаем
 )
)

Использовать UserXX очень ненадежно. Потому, что это ВСЕМ приходит в голову. Коли вы можете прочитать только системную переменную, так и читайте LASPOINT - именно в ней будет указанная точка (если она, конечно указана). Зачем же одну переменную раскладывать на целых четыре?
Зачем применять псевдокоманду C:GetPoint  для возвращения точки косвенным путем, через известный всем проход? Да еще именовать ее так же, как стандартную функцию?
Кстати, в SendCommand можно посылать символы для прерывания возможно активной команды и надо посылать нажатие Enter.
Если "программа не является диалоговым окном", то наверняка ее можно сделать только на Lisp. Уж "рекордером программ" он может быть отменным.

Re: Как безопасно дать пользователю ввести точку?

> ShaggyDoc
Спасибо, спорить уже не буду.

Re: Как безопасно дать пользователю ввести точку?

Прошу прощения, в предыдущем моем постинге конечно должно быть

(initget 1)
(Setq Point (GetPoint "\n Укажите точку "))

или

(if (Setq Point (GetPoint "\n Укажите точку ")) (progn  что-то делаем ))

Re: Как безопасно дать пользователю ввести точку?

"... в SendCommand можно посылать символы для прерывания возможно активной команды ...".
А какие, если не секрет? Пробую и так: SendCommand('^C^C ') и так SendCommand('Command '), но постоянно натыкаюсь на отклонённый вызов если к примеру выполняется команда Line.

Re: Как безопасно дать пользователю ввести точку?

Попробуй для прерывания команды использовать оператор

SendKeys"{Esc}"

Re: Как безопасно дать пользователю ввести точку?

А кто ответит, как из LISPа загрузить dll - Delphi-йскую, передать в процедуру (модал. диалог. окно) параметры, закрыть окно и
в Lisp воспользоваться данными из окна.

Re: Как безопасно дать пользователю ввести точку?

> alex
Вот общая схема работы с сервером:

(setq MySVR (vlax-get-or-create-object "MyDLL.MySVR")); получение указателя на сервер
(vlax-invoke-method MySVR "CreateDLG"); создание формы
; Передача данных на сервер
(vlax-put-property MySVR "Property1")
(vlax-put-property MySVR "Property2")
(...)
(vlax-put-property MySVR "PropertyN")
(setq IsContinue T); признак запуска/возврата к диалогу
(while IsContinue
  (setq SVRRes (vlax-variant-value (vlax-invoke-method MySVR "ShowDLG"))); запуск диалога в модальном режиме и получение ModalResult
  ; В зависимости от значения ModalResult (SVRRes) - выполняются определенные действия
  (cond ((= SVRRes 1); НАЖАТА КНОПКА "ПРИНЯТЬ"
     ; Получение данных от сервера
     (setq Property1 (vlax-get-property MySVR "Property1"))
     (setq Property2 (vlax-get-property MySVR "Property2"))
     (...)
     (setq PropertyN (vlax-get-property MySVR "PropertyN"))
     ; LISP-действия согласно полученным данным
     (...)
     (setq IsContinue nil); признак окнчания работы
     )
    ((= SVRRes 4); НАЖАТА КНОПКА "ПРОСМОТР"
     ; Получение данных от сервера
     (setq Property1 (vlax-get-property MySVR "Property1"))
     (setq Property2 (vlax-get-property MySVR "Property2"))
     (...)
     (setq PropertyN (vlax-get-property MySVR "PropertyN"))
     ; LISP-действия согласно полученным данным
     (...)
     )
    ((= SVRRes 2); НАЖАТА КНОПКА "ОТМЕНА"
     (setq IsContinue nil); признак окончания работы
     )
    )
  )
(vlax-invoke-method MySVR "FreeDLG"); разрушение диалогового окна
(vlax-release-object MySVR); релизим сервер
(gc); сборка мусора

В данном случае кнопки "Принять", "Просмотр" и "Отмена" соответстуют mrOK, mrRetry, mrCancel. Так же можно добавить и указание точки со своим ModalResult.
Зарегистрировать сервер можно LISP-выражением:

(startapp "regsvr32" (strcat "/s " "путь" "\\MyDLL.dll"))

И конечно в начале работы нужно проверить, зарегистрирован ли сервер.
>den-si
Просьба перенести этот вопрос в ветку "Программирование:Delphi.

Re: Как безопасно дать пользователю ввести точку?

> GRF
Попробывал повторить. Неработает.
А если есть время можно-ли реальный
примерчик на мыло с окошком "Hello World" в
DLL. alexbabichuk@hotmail.com
Заранее благодарен.