Author Topic: How to close a modal form to pick a point and re-show the form again  (Read 10040 times)

Fred Tomke

  • OpenDCL Technician
  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2070
  • [ Mr. Bad Guy ]
    • Kommunale Entwicklungsplanung auf digitaler Basis - digital landscape and urban design
Question:
I want to pick a point in AutoCAD while a modal form is showing.

Answer:
You cannot pick a point or select objects in the drawing as long a modal form is showing. You have to close the form and to show it again after you have picked the point. The returning values for dcl_form_show and dcl_form_close will help you.

Code: (autolisp) [Select]
(defun c:MyProg (/ doCont intResult c:proj_form_OnInitialize c:proj_form_pb_accept c:proj_form_pb_select c:proj_form_pb_cancel)
  (defun c:proj_form_OnInitialize ()
    (princ "Initializing the form...")
  );  c:proj_form_OnInitialize

  (defun c:proj_form_pb_accept ()
    (dcl_form_close proj_form 0)
  ); c:proj_form_pb_accept

  (defun c:proj_form_pb_select ()
    (dcl_form_close proj_form 1)
  ); c:proj_form_pb_select

  (defun c:proj_form_pb_cancel ()
    (dcl_form_close proj_form 2)
  ); c:proj_form_pb_cancel

  (setq doCont T)
  (while doCont
    (setq doCont nil) ;; to avoid neverending loop at ESC
    (setq intResult (dcl_form_show proj_form))
    (cond
      ((= intResult 0) (princ "Something will happen here."))
      ((= intResult 1) (setq ptPoint (getpoint "\nPick point: ")) (setq doCont T)) ;; don't forget to set doCont to T to show the form again
      ((= intResult 2) (princ "This will be executed after ESC and after pressing Cancel button."))
    ); cond
  ); while
  (princ)
); MyProg

Here you will find a sample with placing blocks:
http://www.opendcl.com/forum/index.php?topic=769.0

Here you will find a sample with a nested dialog.
http://www.opendcl.com/forum/index.php?topic=947.0

Also see the "Selections.lsp" sample installed with the Studio under: "C:\Program Files\OpenDCL Studio\<LANGUAGE>\Samples"

Fred
« Last Edit: December 14, 2009, 10:51:06 PM by Fred Tomke »
Fred Tomke
Dipl.-Ing. (FH) Landespflege

[ landscaper - landscape developer - digital landscape and urban design]

Fred Tomke

  • OpenDCL Technician
  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2070
  • [ Mr. Bad Guy ]
    • Kommunale Entwicklungsplanung auf digitaler Basis - digital landscape and urban design
How to close a modal form to pick a point and re-show the form again - Part II
« Reply #1 on: February 26, 2010, 01:31:37 PM »
Hello,

in addition to the initial post, this post is going into detail, when a modal form is being called from a modeless form (or palette or dockable form) and you want to have access to the AutoCAD drawing database from the modal form.

Like in the first part you will have to close the modal form, as long as you need access to the drawing database. AutoCAD prevents you from having fully access to the drawing database if you call the modal form within a synchronous called event handler. The following event handler won't give you access to the drawing database if the EventInvoke property state of the clicked button is 0 for KeepFocus (don't mix it with the KeepFocus property of forms!).

Code: (autolisp) [Select]
(defun c:MyProj_MyForm_MyButton1_OnClicked ()
  (dcl_form_Hide MyProj_MyForm T)
  (call_function_with_modal_form)
  (dcl_form_Hide MyProj_MyForm nil)
); c:MyProj_MyForm_MyButton1_OnClicked

(defun c:MyProj_MyForm_MyButton2_OnClicked ()
  (dcl_form_close MyProj_MyForm)
  (call_function_with_modal_form)
  (dcl_form_show MyProj_MyForm)
); c:MyProj_MyForm_MyButton2_OnClicked

This code works very well as long as you don't need access to the drawing database. But if you want to pick points, select objects or attach object data you will have to finish the event handler at first!

There are 2 ways to do that:

1. Call another command using dcl_sendstring from a synchronous called event handler.
This makes only sense if you have to define additional variables at first or you have to finish other tasks at first before calling the other command.
  • The control's EventInvoke property state is 0 (for KeepFocus).
  • The event is active and calls the event handler with the default name (like c:MyProj_MyForm_MyButton_OnClicked).
  • During the event handler an externally defined command is called using (dcl_sendstring "ExternalCommand ") and NOT using (c:ExternalCommand).

2. The event handler is an own command which is called asynchronous.
  • The control's EventInvoke property state is 1 (for AllowCommand).
  • The event is active. The name of the event handler is only the cammand name (like ExternalCommand) or c:ExternalCommand. If you want, press the AddCancel button to make sure that all active commands and inputs are stopped. The prefix ^C^C will appear in front of you command name (like ^C^CExternalCommand).
  • You need no additional event handler but only the command which executes all the desired tasks.

The attached sample will show you how to work with modeless forms, modal forms and user inputs from the commandline.
It is based on a topic from andrew.
All files need to be located into an AutoCAD support path. Compare both buttons of the modeless form with each other.

Note: the latest selected item will be stored into the drawing using vlax-ldata-put. Also outside any event and modal form!!!
Change objects and objectdata outside (!!!) a running modal form and never inside. Make sure that Lisp-reactors are getting never fired when a modal form is active or a synchronous event is running.

Have fun,
Fred
« Last Edit: February 26, 2010, 01:50:11 PM by Fred Tomke »
Fred Tomke
Dipl.-Ing. (FH) Landespflege

[ landscaper - landscape developer - digital landscape and urban design]