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
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.
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.
@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 ?
.
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)
Cool LISP. Can I adjust the time of this LISP? If so, is it the at the bottom where it states 30?
Thanks,
Vince
@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..."
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
@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."
@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
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."
@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.
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."
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
@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."
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)
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?
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:
I hope this helps.
Kind Regards,
Lee Mac
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