jpsheader.jpg (29354 bytes)

Back to DCL Tutorial Homepage

Back to AutoLisp Homepage

Back to JefferyPSanders.com

 

 

 

D

I

A

L

O

G

 

 

C

O

N

T

R

O

L

 

 

L

A

N

G

U

A

G

E

 

 

 

 

 

D

I

A

L

O

G

 

 

C

O

N

T

R

O

L

 

 

L

A

N

G

U

A

G

E

 

 

 

 

 

D

I

A

L

O

G

 

 

C

O

N

T

R

O

L

 

 

L

A

N

G

U

A

G

E

 

 

 

 

 

D

I

A

L

O

G

 

 

C

O

N

T

R

O

L

 

 

L

A

N

G

U

A

G

E

 

 

The AutoLisp Tutorial - DCL

Dialog Control Language


    Getting Started


    I'm not going to explain everything there is to know about Dialog Control Language.  There are plenty of books on the subject.  I will attempt to give you a good understanding of how DCL interacts with AutoLisp.  You should be able to write your first DCL driven Autolisp program in no time. 


  Here is the basic order for things to happen inside the AutoLisp file:

(defun C:MyProgram()                 ; Define the main program

  (defun myFunction1()               ; Define the functions you need like saveVars

    ;do stuff here

   )

   (defun myFunction2()

     ;do stuff here

   )

   (setq list1(list "a" "b" "c" "d")) ; Build the list if any are required

   (setq list2(list "1" "2" "3" "4"))

   (setq list3(list "x" "y" "z"))

 

   load_dialog                          ;Load the DCL file


   new_dialog                          
;Load the DCL definition inside the DCL file


   start_list                           ;Put the list in the dialog box
   add_list
   end_list

   start_list                                                                    ;As many list as you need
   add_list
   end_list


   set_tile                             ; Set the tiles (if necessary)

   mode_tile                                                                    ; Enable or disable tiles (as necessary)

        ;Set up as many action tiles as you need.

   (action_tile "accept" "(myFunction1)(done_dialog 2)")
   (action_tile "cancel" "(myFunction2)(done_dialog 1)")


    ;Two action tiles need to have the done_dialog call. One of these needs to save the settings before
         ; the done_dialog call.

    (setq d(start_dialog))                               ; Start the dialog box    

    unload_dialog                                                ; Unload the dialog box

   

          ; Do stuff if the user presses the cancel key

    (if (= d 1)

      ;do stuff here if cancel was pressed

     )

          ; Do stuff if the user presses the accept key

    (if (= d 2)

      ;do stuff here if okay was pressed

     )

)                                                                                                    ; close the program

  We will discuss this in detail later on.


   I've found the hardest thing to get a grip on is laying out the dialog box.  Please take a look at the rows and columns section if you need help with laying out a dialog box.  For now let's look at the basics. We will cover these items first:   button, row, column, boxed_row, and boxed_column.

  Okay and Cancel Buttons - The DCL code for a these buttons look like this:

  : button {              // Define the button    
    key = "accept";      
// Define the action key (This is my name assigned to this button)      
    label = " Okay ";    
// This is the text displayed on the button.       
    is_default = true;   
// Allows the button to activate when the user presses the enter key.
  }                       
// Close the button definition


  : button {              
// Define another button
    key = "cancel";      
// Define the action key. (I chose this name for the button.)
    label = " Cancel ";  
// Text displayed on the button.
    is_default = false;  
// Does not allow this key to activate when the enter key is pressed.
    is_cancel = true;    
// Activate this key when the close button [ X ] is selected.
  }                       
// Close the button definition

  Rows and Columns designate areas to lay your controls on.   [Controls are list boxes, edit boxes, buttons, etc. ]. 

Here is the DCL code for a column:

: column {

}  

Here is the DCL code for a row:

: row {

}  

   Simple right?


  Here is the code for a column with two buttons:

: column {

  : button {
    key = "accept";
    label = " Okay ";
    is_default = true;
  }

  : button {
    key = "cancel";
    label = " Cancel ";
    is_default = false;
    is_cancel = true;
  }

}

DCL01.JPG (3288 bytes)

Notice the buttons are stacked on top of each other.

 

Here is the code for a row with two buttons:

: row {

  : button {
    key = "accept";
    label = " Okay ";
    is_default = true;
  }

  : button {
    key = "cancel";
    label = " Cancel ";
    is_default = false;
    is_cancel = true;
  }

}

DCL02.JPG (3976 bytes)

Notice the buttons are side by side.


  Let's turn the above into Boxed Rows and Boxed Columns.  Here is the code for a boxed_column with two buttons:

: boxed_column {

  : button {
    key = "accept";
    label = " Okay ";
    is_default = true;
  }

  : button {
    key = "cancel";
    label = " Cancel ";
    is_default = false;
    is_cancel = true;
  }

}

DCL03.JPG (4383 bytes)

Notice the box around the buttons.

 

Here is the code for a boxed_row with two buttons:

: boxed_row {

  : button {
    key = "accept";
    label = " Okay ";
    is_default = true;
  }

  : button {
    key = "cancel";
    label = " Cancel ";
    is_default = false;
    is_cancel = true;
  }

}

DCL04.JPG (4955 bytes)

Notice the box around the buttons.


   Now we know the difference between a row and a boxed_row.  We also know that controls inside a column get stacked on top of each other [ vertical ] and controls inside a row are next to each other [ horizontal ]. 

  Important:  You should never ever attempt to build a dialog box without a cancel button.  


Overview

Let's take a look at the entire code for the dialog box above, including the LSP file:

DCL FILE NAMED: DCL_TEST.DCL         AUTOLISP PROGRAM NAMED: DCL_TEST.lsp

DCL_TEST : dialog {

  : boxed_row {

    : button {
      key = "accept";
      label = " Okay ";
      is_default = true;
    }

    : button {
      key = "cancel";
      label = " Cancel ";
      is_default = false;
      is_cancel = true;
    }

  }

}

(defun C:DCL_TEST()

  (if(not(setq dcl_id (load_dialog "DCL_TEST.dcl")))
    (progn
      (alert "The DCL file could not be loaded.")
      (exit)
    )
    (progn
      (if (not (new_dialog "DCL_TEST" dcl_id))
        (progn
          (alert "The definition could not be found inside the DCL file")
          (exit)
        )
        (progn
          (action_tile "cancel" "(done_dialog 1)")
          (action_tile "accept" "(done_dialog 2)")
          (setq ddiag(start_dialog)) 
          (unload_dialog dcl_id)
          (if (= ddiag 1)
            (princ "\n \n ...DCL_TEST Cancelled. \n ")
          )
          (if (= ddiag 2)
            (alert "You pressed the OKAY button!")
          )
        )
      )
    )
  )
  (princ)
)

 

AutoLISP

Let's take a look at the AutoLisp part of this simple program.

  First we defined our program:

(defun C:DCL_TEST()

 

  The second thing was to load the DCL file from disk.  Insert a path if necessary, but I always liked to use the autocad search path to find the file.   Notice the dcl_id variable used.  We will need this later on.  This identifies the file opened.

;;;--- Load the dialog file from disk into memory
  (setq dcl_id (load_dialog "DCL_TEST.dcl"))

You can improve this with a little error checking:

  (if(not (setq dcl_id (load_dialog "DCL_TEST.dcl")))
    (progn
      (alert "The file could not be loaded.")
      (exit)
    )
  )

 

  Since a DCL file can contain multiple dialog box definitions, [ I'll show you an example later on. ] we need to specify which dialog box we want to load.  This is taken care of in the next statement.  Notice the name matches the definition inside the DCL file. 

  ;;;--- See if the DCL definition is found inside the DCL file
  (new_dialog "DCL_TEST" dcl_id)

   You can inprove this with a little error checking:  

  (if (not (new_dialog "DCL_TEST" dcl_id))
    (progn
      (alert "The DCL definition could not be found inside the DCL file.")
      (exit)
    )
  )

The only problem with the above method is if the DCL file fails to load into memory you will get an alert stating the file did not load.  That's not a problem, but you will also get an alert saying the Definition could not be found.  We don't want both popping up.  So, change the above to be nested, like this:

;;;--- Try to load the DCL file from disk into memory
(if(not(setq dcl_id (load_dialog "DCL_TEST.dcl")))
    (progn
      (alert "The DCL file could not be loaded.")
      (exit)
    )

    ;;;--- Else, the DCL file was loaded into memory
    (progn

      ;;;--- Try to load the definition inside the DCL file
      (if (not (new_dialog "DCL_TEST" dcl_id))
        (progn
          (alert "The definition could not be found inside the DCL file")
          (exit)
        )

        ;;;--- Else, the definition was loaded, we are ready to roll
        (progn

          ;;;--- Put action keys here

        )
      )
    )
  )

  Next, we define our action keys.  These tell the program what to do whenever a user presses a button, selects an item in a list, etc.  Notice the two action keys.  "cancel" and "accept" .   These match the keys in the DCL file.  I made these names up.  You can name them whatever you want as long as it is not a name used by AutoCAD and it only appears once in each DCL definition.  You can't have two controls with the same key, the program would get confused.  So would I!!!   Whenever the user presses the cancel key, the done_dialog statement returns the value of 1 the start_dialog statement and closes the dialog box.  Upon pressing the Okay button, [ key = accept ], the done_dialog program returns the value of 2 to the start_dialog statement and closes the dialog box.  That's it.  Nothing else to add, except you could have just about anything in here, including instructions to execute a function [ I'll demonstrate that later. ]

  ;;;--- If an action event occurs, do this function
  (action_tile "cancel" "(done_dialog 1)")
  (action_tile "accept" "(done_dialog 2)")

 

  Finally, the big step.  Everything is defined, let's display the dialog box and set up the variable to hold the value returned from the done_dialog statement.


  ;;;--- Display the dialog box
  (setq ddiag(start_dialog))

 

  The program halts here until the dialog box is issued a "done_dialog" call.  In the mean time the user is interacting with the action keys.  When the user presses a button the program kills the dialog box with the unload_dialog call.  Notice the dcl_id passed as a parameter.  You could have more than one dialog file open at one time.  So, the unload_dialog function needs to know which one to unload.

   ;;;--- Unload the dialog box from memory
  (unload_dialog dcl_id)

 

  Finally the dialog box is gone.  What next?   Find out which button the user pressed?  Exactly!  Remember the done_dialog was setup to return either 1 or 2.  The start_dailog statement set this value to the variable ddiag.  We will use that now to determine which button was pressed. 

 
  ;;;--- If the cancel button was pressed - display message
  (if (= ddiag 1)
    (princ "\n \n ...DCL_LSP Cancelled. \n ")
  )

  ;;;--- If the "Okay" button was pressed
  (if (= ddiag 2)
    (alert "You pressed the Okay button!")
  )

 

  And the last step, close the autolisp program.

  (princ)
)


The basic DCL and AutoLisp model

  I will now give you the model I use for 98% of all dialog based programs I write.  I start with this basic program and build from there.  It is basically the same thing we've gone over before.  I put up a dialog box.  I allow the user to press buttons and manipulate data.  The only difference is, when the user presses the OKAY button I save the settings in the dialog file before it closes.  I do this inside the action key call with a function called saveVars.  Without further ado, here's the model:

The DCL Model:

EXAMPLE : dialog {
          label = "EXAMPLE.lsp";           
// Puts a label on the dialog box
          initial_focus = "textval";       
// Sets the initial focus
          : column {
            : row {
              : boxed_column {
                : edit_box {               
// The edit_box control - Something new!
                  key = "textval";
                  label = "Text Value to Find";
                  edit_width = 30;
                  value = "";
                }
              }
            }
            : row {
              : boxed_row {
                : button {
                  key = "accept";
                  label = " Okay ";
                  is_default = true;
                }
                : button {
                  key = "cancel";
                  label = " Cancel ";
                  is_default = false;
                  is_cancel = true;
                }
              }
            }
          }
}

The AutoLisp Model:

;;;--- EXAMPLE.lsp - Text Find

(defun saveVars()
  ;;;--- Save the input from the dialog box
  (setq textVal (get_tile "textval"))
)


(defun C:EXAMPLE()

;;;--- Try to load the DCL file from disk into memory
(if(not(setq dcl_id (load_dialog "DCL_TEST.dcl")))
    (progn
      (alert "The DCL file could not be loaded.")
      (exit)
    )

    ;;;--- Else, the DCL file was loaded into memory
    (progn

      ;;;--- Try to load the definition inside the DCL file
      (if (not (new_dialog "DCL_TEST" dcl_id))
        (progn
          (alert "The definition could not be found inside the DCL file")
          (exit)
        )

        ;;;--- Else, the definition was loaded, we are ready to roll
        (progn

    
     ;;;--- If an action event occurs, do this function
          (action_tile "cancel" "(done_dialog 1)")
          (action_tile "accept" "(saveVars)(done_dialog 2)")

          ;;;--- Display the dialog box
          (setq ddiag(start_dialog))

          ;;;--- If the cancel button was pressed - display message
          (if (= ddiag 1)
            (princ "\n \n ...EXAMPLE Cancelled. \n ")
          )

          ;;;--- If the "Okay" button was pressed
          (if (= ddiag 2)
            (princ "\n \n ...Example Complete!")
          ) 
        )
      )
    )
  )

  ;;;--- Suppress the last echo for a clean exit
  (princ)

)

Screen Shot:

DCL05.JPG (9772 bytes)

  If you could not follow some of the autolisp functions, you can ignore them for now or read the Autolisp Tutorial

  This is the model.  Very little will change from this setup.  You may add some controls to the DCL file which in turn will add Action calls and influence the number of lines inside the saveVars routine.  The only other thing that will change is inside the OKAY button function.  [ When ddiag = 2 ].   You will have to tell the program what to do when all of the information is gathered.  We will cover these later.

Back


AutoLisp DCL Tutorial Home

AutoLisp Home

Home

All questions/complaints/suggestions should be sent to JefferyPSanders.com

Last Updated May 22nd, 2013

Copyright 2002-2013 JefferyPSanders.com. All rights reserved.