Visual LISP, AutoLISP and General Customization
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

LISP routine to activate alert window based on drawing timer

18 REPLIES 18
Reply
Message 1 of 19
Anonymous
3565 Views, 18 Replies

LISP routine to activate alert window based on drawing timer

Hi,

 

I was interested in finding out if it's possible to write a LISP routine that would execute a pop-up dialog box say every 30 minutes.  This is strictly for ergonomic reasons to remind the user to take a pre-determined break.

 

I am not an expert code writer by any means, but I imagine the routine would autoload and resetting the timer to 0 upon opening a particular drawing file.  The LISP routine would then run in the background and run the (alert "") command when the timer reaches 30m 0s.  When the user presses the OK button, the timer resets to 0 again.

 

Thanks

18 REPLIES 18
Message 2 of 19
dgorsman
in reply to: Anonymous

LISP doesn't run in the background.  It essentially takes the place of the user providing input to AutoCAD. 

 

For this, you could get away with a BAT file being run by Windows Scheduled Task Manager but a simple EXE built with dotNET would provide more options.  With a bit of work a Service could be built.  Either way, probably for the best to keep it out of AutoCAD altogether.

 

Whatever you do, provide a means to disable it - constant 30 minute reminders (*especially* when deadlines are knocking on the door) are a PITA.

----------------------------------
If you are going to fly by the seat of your pants, expect friction burns.
"I don't know" is the beginning of knowledge, not the end.


Message 3 of 19
scot-65
in reply to: Anonymous

I had a coworker that purchased one of these "Take a Break" timers. How annoying!

I was able to find similar freeware versions online.

As dgorsman said, it is best to stay out of AutoCAD for this, unless you use reactors.

 

Look in the Softpedia website.

 

???


Scot-65
A gift of extraordinary Common Sense does not require an Acronym Suffix to be added to my given name.


Message 4 of 19
pbejse
in reply to: Anonymous


@chobbs wrote:

Hi,

 

I was interested in finding out if it's possible to write a LISP routine that would execute a pop-up dialog box say every 30 minutes.  This is strictly for ergonomic reasons to remind the user to take a pre-determined break.

 

I am not an expert code writer by any means, but I imagine the routine would autoload and resetting the timer to 0 upon opening a particular drawing file.  The LISP routine would then run in the background and run the (alert "") command when the timer reaches 30m 0s.  When the user presses the OK button, the timer resets to 0 again.

 

Thanks


it can be done using reactors

Is that 30 minutes from the time the file is open? or at every pre-deterined time like 7:30, 8:00, 8:30 ?

.

Message 5 of 19
pbejse
in reply to: pbejse

Try this:

<Not thouroughly tested>

 

 

(defun c:CountDown ()
(vl-load-com)
;;;		30 Minutes Countdown	 	;;;
;;;		   pbe June 2012		;;;
;;; 	kudos to Lee Mac for Reactor Snippet	;;;
;;;					 	;;;
      
((lambda ( data foo / react pt )
       (if (setq react
             (vl-some
               (function
                 (lambda ( reactor )
                   (if (eq data (vlr-data reactor)) reactor)
                 )
               )
               (cdar
                 (vlr-reactors :vlr-command-reactor)
               )
             )
           )
         (if (vlr-added-p react)
           (progn
             (vlr-remove react)
             (setq then nil)
             (princ "\n<<Timer Unloaded>>>")
           )
           (progn (vlr-add react)
                  (setq then nil)
                  (princ "\n<<<Timer Re-Loaded>>>"))
         )(progn
             (setq react
               (vlr-command-reactor data
                 (list
                   (cons :vlr-CommandEnded foo)
                 )
               )
             )(princ "\n<<Timer Loaded>>>"))
       )
       react
     )
    "CountDown"
    '_TellmeItsTime 
  )
  (princ)
)

(defun _TellmeItsTime ( reactor arguments)
(if (null then)  (setq then (getvar 'date)))   
      (if  (> (*  (- (setq pass (getvar 'date))
                        then) 1440)
                       30)
           (progn (alert "<<<<30 Minute Mark>>>")
                 (setq then pass))
              )
      )
(c:CountDown)

 

 

Message 6 of 19
vlsheehan
in reply to: pbejse

Cool LISP. Can I adjust the time of this LISP? If so, is it the at the bottom where it states 30?

 

Thanks,

Vince

Vincent Sheehan

Sr. Civil Designer
Poly In 3D Blog

Message 7 of 19
pbejse
in reply to: vlsheehan


@Anonymous wrote:

Cool LISP. Can I adjust the time of this LISP? If so, is it the at the bottom where it states 30?

 

Thanks,

Vince


Yup.. i suppose you can.

 

I never got a reply from the OP..... *..sigh..."

Message 8 of 19
hgasty1001
in reply to: Anonymous

Hi,

 

Jus a thought, why not an editor reactor triggered by autosave (:vlr-saveComplete), and set the autosave to 30 mintues or what ever you need?.

 

Gaston Nunez

Message 9 of 19
BlackBox_
in reply to: hgasty1001


@hgasty1001 wrote:

Hi,

 

Jus a thought, why not an editor reactor triggered by autosave (:vlr-saveComplete), and set the autosave to 30 mintues or what ever you need?.

 

Gaston Nunez


That's not a bad idea; the only downside I can see immediately, is that you're now dependent on SaveTime System Variable = your timer increment. If the user(s) instead want SaveTime = a different value +/-, then the idea breaks down.

 

But this idea would work, and AutoCAD does a better job of setting off the timer as it were at exactly the right time, instead of the first time a Command is invoked after that timer, if that makes sense.



"How we think determines what we do, and what we do determines what we get."

Message 10 of 19
pbejse
in reply to: BlackBox_


@BlackBoxCAD wrote:

@hgasty1001 wrote:

 

Jus a thought, why not an editor reactor triggered by autosave (:vlr-saveComplete), and set the autosave to 30 mintues or what ever you need?.

 

Gaston Nunez


That's not a bad idea;.....

 


Not bad indeed. Make it so gasty1001

Message 11 of 19
BlackBox_
in reply to: pbejse

To the best of my limited knowledge....

 

If you really wanted to do this right, you'd use a custom .NET LispFunction Method which registers a System.Timer.Elapsed Event Handler, supplying the ResultBuffer with both the int32 (?increment (the time to elapse), and the symbol/function (without Command calls) as the would-be Callback invoked via silent SendStringToExecute() call immediately following the unregisteration of the aforementioned Event Handler. *untested*



"How we think determines what we do, and what we do determines what we get."

Message 12 of 19
Kent1Cooper
in reply to: Anonymous


@chobbs wrote:

....the routine would autoload and resetting the timer to 0 upon opening a particular drawing file.  The LISP routine would then run in the background and run the (alert "") command when the timer reaches 30m 0s. ....


Another reason I agree with those suggesting keeping this outside of AutoCAD:  I often have multiple drawings open at the same time.  If such a routine were active in each of them, assuming the times they were opened had no particular relationship to each other, I would be getting reminders at irregular intervals, and often much closer together than the set time span.  Or at best, if the reminder is by an (alert) box, I would get them only in the currently active drawing, but many times when I switched to another drawing, a reminder would be there waiting for me, even if I just got one in the last drawing I was in.  If your Users don't often work on more than one drawing at a time, it wouldn't be an issue, nor if the thing could be written somehow to keep track of the time only within the currently active drawing.  But I assume something unrelated to AutoCAD would be more regular and predictable.

 

But if you really want it in AutoCAD, here's a thought....  Years ago, when we used Tablet menus, and before AutoSave existed in AutoCAD, we had a "button" on the Tablet for Cancel.  Its code contained a Cancel, and then a check on the time since the drawing was opened or last saved, I think using one of the TD... System Variables.  If that was more than some predetermined interval, it prompted the User to ask whether they wanted to save the drawing.  If they did so, of course the clock would be reset, so it would then leave them alone for a while.  Cancel was something one would use pretty frequently, and piggybacking this onto it meant the reminder would usually come up not much past the set interval, but would never interrupt a command in progress or anything.  If a reactor can be triggered by Cancel [that's one area I haven't delved into], a similar effect could be achieved, with a different reminder.  If there's any command that you use quite regularly, you could perhaps redefine it to do something like that, if there's any reason to do it that way rather than with a reactor.

Kent Cooper, AIA
Message 13 of 19
BlackBox_
in reply to: hgasty1001

FWIW -

 

The :vlr-SaveComplete Event never fires for Autosave (regardless of SAVETIME), according to MgdDbg Event monitoring for Application, Editor, and Document Events (copied from Command Line):

 

[Editor Event] : Prompted For Selection s
[Editor Event] : Point Filter         s
[Editor Event] : Point Monitor        s
[Editor Event] : Prompting For Selection s
[Editor Event] : Prompt For Selection Ending s
[Editor Event] : Prompted For Selection sa
[Editor Event] : Point Filter         sa
[Editor Event] : Point Monitor        sa
[Editor Event] : Prompting For Selection sa
[Editor Event] : Prompt For Selection Ending sa
[Editor Event] : Prompted For Selection sav
[Editor Event] : Point Filter         sav
[Editor Event] : Point Monitor        sav
[Editor Event] : Prompting For Selection sav
[Editor Event] : Prompt For Selection Ending sav
[Editor Event] : Prompted For Selection save
[Editor Event] : Point Filter         save
[Editor Event] : Point Monitor        save
[Editor Event] : Prompting For Selection save
[Editor Event] : Prompt For Selection Ending save
[Editor Event] : Prompted For Selection savet
[Editor Event] : Point Filter         savet
[Editor Event] : Point Monitor        savet
[Editor Event] : Prompting For Selection savet
[Editor Event] : Prompt For Selection Ending savet
[Editor Event] : Prompted For Selection saveti
[Editor Event] : Point Filter         saveti
[Editor Event] : Point Monitor        saveti
[Editor Event] : Prompting For Selection saveti
[Editor Event] : Prompt For Selection Ending saveti
[Editor Event] : Prompted For Selection savetim
[Editor Event] : Point Filter         savetim
[Editor Event] : Point Monitor        savetim
[Editor Event] : Prompting For Selection savetim
[Editor Event] : Prompt For Selection Ending savetim
[Editor Event] : Prompted For Selection savetime
[Editor Event] : Point Filter         savetime
[Editor Event] : Point Monitor        savetime
[Editor Event] : Prompting For Selection savetime
[Editor Event] : Prompt For Selection Ending savetime
[Editor Event] : Prompted For Selection savetime

[Editor Event] : Leaving Quiescent State
[Doc Event] : Command will Start        : SETVAR
Enter new value for SAVETIME <1>:
[Editor Event] : Prompting For Integer 1

[Editor Event] : Prompted For Integer
[App Event] : System Var Changing       : SAVETIME
[App Event] : System Var Changed        : SAVETIME
[Doc Event] : Command Ended             : SETVAR
[Editor Event] : Entering Quiescent State
Command:
[Editor Event] : Point Filter
[Editor Event] : Point Monitor
[Editor Event] : Prompting For Selection
[Editor Event] : Prompt For Selection Ending
[Editor Event] : Prompted For Selection
[Editor Event] : Leaving Quiescent State
[App Event] : System Var Changing       : FILEDIA
[App Event] : System Var Changed        : FILEDIA
Automatic save to C:\Users\BLACKB~2\AppData\Local\Temp\FooBar_1_2_1562.sv$ 
...

Command: Updating Indexes for block *MODEL_SPACE
Done.

[App Event] : System Var Changing       : NAVBARDISPLAY
[App Event] : System Var Changed        : NAVBARDISPLAY
[App Event] : System Var Changing       : NAVBARDISPLAY
[App Event] : System Var Changed        : NAVBARDISPLAY
[App Event] : System Var Changing       : NAVBARDISPLAY
[App Event] : System Var Changed        : NAVBARDISPLAY
[App Event] : System Var Changing       : NAVBARDISPLAY
[App Event] : System Var Changed        : NAVBARDISPLAY
[App Event] : System Var Changing       : FILEDIA
[App Event] : System Var Changed        : FILEDIA
[Editor Event] : Entering Quiescent State
Command:
[Editor Event] : Point Filter
[Editor Event] : Point Monitor
[Editor Event] : Prompting For Selection
[Editor Event] : Prompt For Selection Ending

 



"How we think determines what we do, and what we do determines what we get."

Message 14 of 19
hgasty1001
in reply to: BlackBox_

Hi,

 

You are right editor events are not fired from Autosave, but Autosave does fire at least 2 others events :vlr-documentLockModeWillChange and :vlr-documentLockModeChanged ,but they are part of the Document Manager event set.

 

Gaston Nunez

 

 

Message 15 of 19
BlackBox_
in reply to: hgasty1001


@hgasty1001 wrote:

Hi,

 

You are right editor events are not fired from Autosave, but Autosave does fire at least 2 others events :vlr-documentLockModeWillChange and :vlr-documentLockModeChanged ,but they are part of the Document Manager event set.

 

Gaston Nunez

 

 


That is correct, Gaston; I noticed that after-the-fact, but could not come back and edit my post again. 

 

Cheers

 

 

 

Also, while I'm at it, a correction to my earlier post....


@BlackBoxCAD wrote:

To the best of my limited knowledge....

 

If you really wanted to do this right, you'd use a custom .NET LispFunction Method which registers a System.Timer.Elapsed Event Handler, supplying the ResultBuffer with both the int32 (?increment (the time to elapse), and the symbol/function (without Command calls) as the would-be Callback invoked via silent SendStringToExecute() call immediately following the unregisteration of the aforementioned Event Handler. *untested*


... One cannot pass a SUBR (Symbol/Function) to LispFunction, else error 'overflow' message returned, however, (to the best of my knowledge) one can pass the name of said SUBR as string, which can be used to build the string command parameter of the SendStringToExecute() Method for the Elapsed Event Handler.

 

Pseudo-code:

(MyLispFunctionMethod 1800 "MyDefunSubFunctionName")

 



"How we think determines what we do, and what we do determines what we get."

Message 16 of 19
ehsantavassolian
in reply to: pbejse

hi
thank you , because You have made very functional applications on your site.
I intend to write an application
I used a program from a friend on the site
Maybe you have written this.
But I'm going to do a command at the specified time.
For example, Qsave once every minute.

 

(defun c:CountDown ()
(vl-load-com)
;;; 30 Minutes Countdown ;;;
;;; pbe June 2012 ;;;
;;; kudos to Lee Mac for Reactor Snippet ;;;
;;; ;;;
((lambda ( data foo / react pt )
(if (setq react
(vl-some
(function
(lambda ( reactor )
(if (eq data (vlr-data reactor)) reactor)
)
)
(cdar
(vlr-reactors :vlr-command-reactor)
)
)
)
(if (vlr-added-p react)
(progn
(vlr-remove react)
(setq then nil)
(princ "\n<<Timer Unloaded>>>")
)
(progn (vlr-add react)
(setq then nil)
(princ "\n<<<Timer Re-Loaded>>>"))
)(progn
(setq react
(vlr-command-reactor data
(list
(cons :vlr-CommandEnded foo)
)
)
)(princ "\n<<Timer Loaded>>>"))
)
react
)
"CountDown"
'_TellmeItsTime
)
(princ)
)

(defun _TellmeItsTime ( reactor arguments)
(if (null then) (setq then (getvar 'date)))
(if (> (* (- (setq pass (getvar 'date)) then) 1440) 1)
(progn

 

 

(setq then pass)

(alert "<<<<Works so well right here>>>")
(command ".qsave")                                                           ;; *****problem is here*****
(alert "<<<<This section does not come>>>")

 

 


)
)
)
(c:CountDown)

Message 17 of 19

I'm not really conversant with reactors, but if I recall correctly, you can't use the (command) function in them, which if true would mean you need to find some different way to accomplish the saving.

 

Also, I'm wondering about this line:

 

(defun _TellmeItsTime ( reactor arguments)

 

Are those stand-ins from some generic suggestion, and shouldn't they be actual argument names that appear later in the function?  Are any arguments needed at all in this case?

Kent Cooper, AIA
Message 18 of 19

lee mac helped me by another way:

 

The issue that you are experiencing is because it is not possible to evaluate an AutoCAD command from within a Visual LISP Reactor callback function. Instead, you must either use ActiveX methods to perform the necessary operations, or perform a post-process evaluation using the ActiveX sendcommand method.

 

Here is an example demonstrating similar functionality to what you are trying to achieve:

https://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/autosave-i-need-it-to-be-a-true-auto...

 

I hope this helps.

 

Kind Regards,

 

 

Lee Mac 

Message 19 of 19
john.uhden
in reply to: Kent1Cooper

As far as the multiple drawing scenario, you could use vl-bb-set and vl-bb-ref so that all open drawings are on the same schedule.  When the current drawing resets the timer to zero, the other drawings will know that there's plenty of time until the next alert.  Because the other drawings are inactive, and because their reactor won't fire until there is some activity, there is no chance that an inactive drawing will fire the callback function to display its alert that would not be seen until activated.  Well maybe that's not "no chance" as perhaps a user could instantaneously switch drawings as the timer is about to go off, or something odd like that.

John F. Uhden

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk Design & Make Report

”Boost