alanjt Posted April 14, 2010 Posted April 14, 2010 I seriously do not recommend you have this set to auto on. If you open a file, just to take something from it, print, etc. you will have to remember to turn the reactor off; otherwise, you will be changing the edit date of the file. This may not be a big deal to you, but you really should be aware it. Please heed my advice. Quote
chulse Posted April 14, 2010 Author Posted April 14, 2010 I seriously do not recommend you have this set to auto on. If you open a file, just to take something from it, print, etc. you will have to remember to turn the reactor off; otherwise, you will be changing the edit date of the file. This may not be a big deal to you, but you really should be aware it. I thought about that... I was just thinking if there would be a way to check if the user wanted to save the DWG, or possibly check if the user had saved the dwg in the last 5 min or something... Any thoughts? The goal here was to prevent users from closing a dwg they were working on without reverting the UCS to World first. This is intended to prevent xrefing problems... Quote
Glen Smith Posted April 14, 2010 Posted April 14, 2010 It looks like you are most of the way to where you want to be, but I just wanted to toss another option out there. I have a macro on a button in a toolbar: "Zoom Save Close". It zooms extents on both model and paper space, locks the viewports, saves the drawing and closes it. You could write one that would set the UCS to World. This way, you can still exit the drawing without the fancy reactor changing the UCS. When you are actually editing the drawing and exit, you use the button "set UCS to World, Save, Close" and move to the next one. Just another thought. Glen Quote
chulse Posted April 14, 2010 Author Posted April 14, 2010 It looks like you are most of the way to where you want to be, but I just wanted to toss another option out there. I have a macro on a button in a toolbar: "Zoom Save Close". It zooms extents on both model and paper space, locks the viewports, saves the drawing and closes it. You could write one that would set the UCS to World. This way, you can still exit the drawing without the fancy reactor changing the UCS. When you are actually editing the drawing and exit, you use the button "set UCS to World, Save, Close" and move to the next one. Just another thought. Glen Good idea. However, I'd prefer not to leave this up to the user, but rather be completely "behind the scenes" and not rely on the user doing or remembering anything... Quote
chulse Posted April 15, 2010 Author Posted April 15, 2010 Ok, this is a shameless bump... but does anyone have any ideas how to automate the turning on/off of the reactor based on when the file was last saved? Quote
alanjt Posted April 15, 2010 Posted April 15, 2010 Ok, this is a shameless bump... but does anyone have any ideas how to automate the turning on/off of the reactor based on when the file was last saved? vl-file-systime(vl-file-systime filename) Arguments filename A string containing the name of the file to be checked. Return Values A list containing the modification date and time, or nil, if the file is not found. Determines the size of a file, in bytes Returns last modification time of the specified file 216 | AutoLISP Reference The list returned contains the following elements: n year n month n day-of-week n day-of-month n hours n minutes n seconds Note that Monday is day 1 of day-of-week, Tuesday is day 2, etc. Examples _$ (vl-file-systime "c:/program files/acad2000/sample/visuallisp/yinyang.lsp") (1998 4 3 8 10 6 52 0) The returned value shows that the file was last modified in 1998, in the 4th month of the year (April), the 3rd day of the week (Wednesday), on the 10th day of the month, at 6:52:0. ............... Quote
chulse Posted April 15, 2010 Author Posted April 15, 2010 alanjt - thanks How can I compare that value to the current time/date? Is the current date saved in a variable somewhere and would the list structure be the same? Quote
alanjt Posted April 16, 2010 Posted April 16, 2010 alanjt - thanksHow can I compare that value to the current time/date? Is the current date saved in a variable somewhere and would the list structure be the same? (getvar 'cdate) You'll have to do a little converting. Quote
chulse Posted April 17, 2010 Author Posted April 17, 2010 Thanks - this should keep me busy for a while. BTW, I decided to keep it turned off by default (at least until I can make the date thing work...) Quote
Lee Mac Posted April 17, 2010 Posted April 17, 2010 Be careful with vl-file-systime, if I remember, it doesn't report too well with files that are open. Quote
alanjt Posted April 17, 2010 Posted April 17, 2010 Be careful with vl-file-systime, if I remember, it doesn't report too well with files that are open. Didn't know that. Granted, I've never thought of using it on an open file. Quote
Lee Mac Posted April 17, 2010 Posted April 17, 2010 I'm not sure that this would be any more accurate: ;; Get File Last Modified time (Lee Mac) ;; Args: Filepath of file to query ;; Returns: Julian Date (defun GetLastModified ( file / fso fObj date ) (vl-load-com) (setq fso (vlax-create-object "Scripting.FileSystemObject")) (cond ( (zerop (vlax-invoke fso 'FileExists file))) ( (setq fObj (vlax-invoke-method fso 'GetFile file) date (+ 2415019 (vlax-get-property fObj 'DateLastModified))))) (vlax-release-object fso) date) (defun c:LastMod ( / f ) (if (setq f (getfiled "Select File to Query" "" "" 16)) (princ (strcat "\nLast Modified: " (toDate (rtos (GetLastModified f) 2 15) "DD.MO.YYYY HH:MM:SS")))) (princ)) (defun toDate ( str format ) (menucmd (strcat "m=$(edtime," str "," format ")"))) Quote
Lee Mac Posted April 17, 2010 Posted April 17, 2010 More fun with the FSO ;; Get File Information (Lee Mac) ;; Args: Filepath of file to query ;; Returns: (<Filename> <Created> <LastAccessed> <LastModified> <Size>) (defun GetFileInfo ( file ) (vl-load-com) (setq fso (vlax-create-object "Scripting.FileSystemObject")) (cond ( (zerop (vlax-invoke fso 'FileExists file))) ( (setq fObj (vlax-invoke-method fso 'GetFile file)) (setq info (mapcar (function (lambda ( property ) (vlax-get fObj property))) '(Name DateCreated DateLastAccessed DateLastModified Size))))) (vlax-release-object fso) info) (defun c:test ( / f Date Size i ) (setq Date (lambda ( d f ) (toDate (rtos (+ d 2415019) 2 15) f)) Size (lambda ( s f ) (rtos (/ s (float f)) 2 3))) (if (and (setq f (getfiled "Select File to Query" "" "" 16)) (setq i (GetFileInfo f))) (mapcar (function princ) (mapcar (function strcat) '("\nName: " "\nCreated: " "\nAccessed: " "\nModified: " "\nSize (KB): ") (mapcar (function (lambda ( foo property args ) (apply foo (cons property args)))) '(strcat Date Date Date Size) i '(nil ("DD.MO.YYYY HH:MM") ("DD.MO.YYYY HH:MM") ("DD.MO.YYYY HH:MM") (1024.)))))) (princ)) (defun toDate ( str format ) (menucmd (strcat "m=$(edtime," str "," format ")"))) Quote
chulse Posted April 19, 2010 Author Posted April 19, 2010 I'll need to play with these... Thanks! Quote
3dwannab Posted November 9, 2024 Posted November 9, 2024 (edited) On 4/14/2010 at 3:13 PM, alanjt said: DANGEROUS!!! This is something I would recommend you have to turn on. In Maxscript there's a function to check if the file is dirty, i.e. not saved with: checkForSave() Is there something similar for VLISP? I was planning on using the reactor Lee had written, but I would need this check to implement it; as you say, it's dangerous. Something like this at the end of the function: (initget "Yes No") (if (and (not (3d_CheckSavedStatus)) ;; Use fn below (eq (getkword "\nAre you sure you want to save the file? [Yes/No] <No>: ") "Yes") ) (progn (if (not (eq "" (vla-get-FullName doc))) (vla-saveas doc (vla-get-FullName doc)) ) ) ) Edited November 9, 2024 by 3dwannab updated to reference fn below Quote
3dwannab Posted November 9, 2024 Posted November 9, 2024 (edited) Here's a roll your own: ;; 3d_CheckSavedStatus ;; Returns T if the file has been saved ;; Written on 2024.11.09 by 3dwannab (defun 3d_CheckSavedStatus (/ doc) (vl-load-com) (setq doc (vla-get-ActiveDocument (vlax-get-Acad-Object))) (= :vlax-true (vla-get-Saved doc)) ) Edited November 9, 2024 by 3dwannab Quote
3dwannab Posted 21 hours ago Posted 21 hours ago On 4/14/2010 at 3:20 PM, alanjt said: I seriously do not recommend you have this set to auto on. If you open a file, just to take something from it, print, etc. you will have to remember to turn the reactor off; otherwise, you will be changing the edit date of the file. This may not be a big deal to you, but you really should be aware it. Hi alan, I think I got around the problem by checking if the file has been saved by setting a variable and clearing it when closing and also checking the DBMOD variable. Be good to know your thoughts. (vl-load-com) ;; ;; Reactor_On_Close.lsp ;; ;; Reactor to change stuff when closing a drawing. ;; ;; Another example by Lee Mac, found here: https://www.cadtutor.net/forum/topic/20069-reactor-for-dwg-close-how-to-save/?do=findComment&comment=163847 ;; ;; Author: 3dwannab ;; ;; First written: 2024.11.09 ;; Last update: 2025.09.07 ;; ;; Reactor-based routine to execute custom actions when a drawing is saved or closed. ;; On save, sets a USERS1 flag in the drawing to "SavedThisSessionCallbackBool". ;; On close, checks the USERS1 flag and DBMOD system variable to determine if actions ;; should be taken: ;; - If in model space: change background to black, deactivate plot styles, zoom extents, ;; regen viewports, and save the drawing before closing. ;; - If in paper space: deactivate viewport, zoom extents, set plot styles, and save the ;; drawing before closing. ;; Afterwards, clears the USERS1 flag. ;; ;; Also checks DBMOD flags for database, window, view, or field modifications to ensure ;; proper handling. ;; ;; TO DO ;; NA ;; ;;--------------------------------------------------------------------------- ;; OnSaveCallback ;; ;; Sets a USERS1 system variable in the active drawing to indicate that ;; the drawing has been saved during this session. This flag is later ;; used by the CloseCallBack reactor to trigger actions on closing. ;; ;; Written on 2025.09.07 by 3dwannab ;; ;; Usage: ;; Automatically called by the onsave reactor; no manual call required. ;;--------------------------------------------------------------------------- (defun OnSaveCallback (/ acDisp acDoc acObj acPref dbmodFlags dbmodVal isModelSpace minorChangeMade val) (setq acObj (vlax-get-acad-object)) (setq acDoc (vla-get-ActiveDocument acObj)) ;; set Reactor_On_Close flag in the active document (vla-SetVariable acDoc "USERS1" "SavedThisSessionCallbackBool") (princ "\nOnSaveCallback run... Reactor_On_Close set to 'SavedThisSessionCallbackBool'") ) ;;--------------------------------------------------------------------------- ;; CloseCallBack ;; ;; Checks the USERS1 system variable and the DBMOD system variable when a ;; drawing is closed. If the USERS1 flag ("SavedThisSessionCallbackBool") is ;; set and the database has meaningful changes (DBMOD flags), performs actions ;; based on whether the drawing is in model or paper space: ;; - Model space: set background to black, deactivate plot styles, zoom extents, ;; regenerate viewports, and save the drawing. ;; - Paper space: deactivate viewport, zoom extents, set plot styles, and save the drawing. ;; ;; Afterwards, clears the USERS1 flag to indicate the reactor actions have been handled. ;; ;; Written on 2025.09.07 by 3dwannab ;; ;; Usage: ;; Automatically called by the onclose reactor; no manual call required. ;;--------------------------------------------------------------------------- (defun CloseCallBack (/ acObj acDoc val) (setq acObj (vlax-get-acad-object)) (setq acDoc (vla-get-ActiveDocument acObj)) ;; get current Reactor_On_Close value (setq val (vlax-variant-value (vla-GetVariable acDoc "USERS1"))) ;; Flag for model space (setq isModelSpace (= 1 (getvar 'TILEMODE))) ;; DBMOD (System Variable) (RO) ;; 1 = Object database modified ;; 4 = Database variable modified ;; 8 = Window modified ;; 16 = View modified ;; 32 = Field modified (setq dbmodVal (getvar "DBMOD")) (setq dbmodFlags '((4 . "Database variable modified") (8 . "Window modified") (16 . "View modified") (32 . "Field modified") ) ) ;; Set minorChangeMade to T expect where DBMOD bitcode has, 1 = Object database modified (foreach flag dbmodFlags (if (/= 0 (logand dbmodVal (car flag))) (setq minorChangeMade T) ; (princ (strcat "\n" (cdr flag))) ) ) ;; if it was set to our flag, clear it (if (and (not (eq "" (vla-get-FullName acDoc))) (= val "SavedThisSessionCallbackBool") minorChangeMade ) (progn (cond ;; -------------------- ;; If in model space ;; -------------------- (isModelSpace (princ "\n[Reactor_On_Close] Model space...\n") (setq acPref (vlax-get-property acObj 'preferences)) (setq acDisp (vlax-get-property acPref 'display)) (vlax-put-property acDisp 'GraphicsWinmodelBackgrndColor 0) ;; Black bg (vla-put-ShowPlotStyles (vla-get-ActiveLayout acDoc) :vlax-false) (vla-zoomextents acObj) (vla-regen acDoc acAllViewports) (vla-saveas acDoc (vla-get-FullName acDoc)) ) ;; -------------------- ;; If in paper space ;; -------------------- (T (progn (princ "\n[Reactor_On_Close] Paper space...\n") (vla-put-ActiveSpace acDoc acModelSpace) (vla-put-mspace acDoc :vlax-false) (vla-zoomextents acObj) (vla-put-ShowPlotStyles (vla-get-ActiveLayout acDoc) :vlax-true) (vla-saveas acDoc (vla-get-FullName acDoc)) ) ) ) ; cond (vla-SetVariable acDoc "USERS1" "") ;; Clear the variable ) (princ "\nNo Reactor_On_Close flag found to clear.") ) (princ "\nCloseCallBack run.") ) ;;------------------------------------------------------- ;; c:Reactor-OnClose-on ;;------------------------------------------------------- (defun c:Reactor-OnClose-on () (if (= 'vlr-command-reactor (type onclose:reactor)) (if (vlr-added-p onclose:reactor) (princ "\n[Reactor] CloseCallBack already running\n") (progn (vlr-add onclose:reactor) (princ "\n[Reactor] CloseCallBack ON\n") ) ) (progn (setq onclose:reactor (vlr-command-reactor "onclose-reactor" '((:vlr-commandwillstart . onclose:callback)) ) ) (princ "\n[Reactor] CloseCallBack ON\n") ) ) (if (= 'vlr-command-reactor (type onsave:reactor)) (if (vlr-added-p onsave:reactor) (princ "\n[Reactor] OnSaveCallback already running\n") (progn (vlr-add onsave:reactor) (princ "\n[Reactor] OnSaveCallback ON\n") ) ) (progn (setq onsave:reactor (vlr-command-reactor "onsave-reactor" '((:vlr-commandwillstart . onsave:callback)) ) ) (princ "\n[Reactor] OnSaveCallback ON\n") ) ) (princ) ) ;;------------------------------------------------------- ;; c:Reactor-OnClose-off ;;------------------------------------------------------- (defun c:Reactor-OnClose-off () (if (= 'vlr-command-reactor (type onclose:reactor)) (progn (vlr-remove onclose:reactor) (setq onclose:reactor nil) (princ "\n[Reactor] CloseCallBack OFF\n") ) (princ "\n[Reactor] CloseCallBack not running\n") ) (if (= 'vlr-command-reactor (type onsave:reactor)) (progn (vlr-remove onsave:reactor) (setq onsave:reactor nil) (princ "\n[Reactor] OnSaveCallback OFF\n") ) (princ "\n[Reactor] OnSaveCallback not running\n") ) (princ) ) ;;------------------------------------------------------- ;; CALLBACKS ;;------------------------------------------------------- (defun onclose:callback (obj arg) (if (wcmatch (strcase (car arg)) "*CLOSE") (CloseCallBack) ) (princ) ) (defun onsave:callback (obj arg) (if (wcmatch (strcase (car arg)) "SAVE,QSAVE") (OnSaveCallback) ) (princ) ) ;;------------------------------------------------------- ;; START THE REACTORS ;;------------------------------------------------------- (if (null onclose:reactor) (setq onclose:reactor (vlr-command-reactor nil '((:vlr-commandwillstart . onclose:callback)))) ) (if (null onsave:reactor) (setq onsave:reactor (vlr-command-reactor nil '((:vlr-commandwillstart . onsave:callback)))) ) (princ "\nReactor_On_Close.lsp loaded...") Quote
BIGAL Posted 20 hours ago Posted 20 hours ago (edited) Another maybe simpler this checks for Close and Save commands. yes got help from a couple of people like Lee-mac. ; by AlanH April 2023 ;Reactor callback function (defun BeginCloseFunc (reactor lst / blocks blk efname ent2 ent3 ole olelst ssole oletit olefound ss ssvft y tabname) (setq tabname (getvar 'ctab)) ; will get "Model" etc ............ do your thing here ........ ............ can call other defuns...... (princ) ) (cond ((= (vlr-current-reaction-name) ':VLR-beginSave) (Princ "\nThis function has been triggered by a Document Save event.")) ((= (vlr-current-reaction-name) ':VLR-beginClose)(princ "\nThis function has been triggered by a Document Close event.")) ) (princ) ) (if (not _BeginCloseReactor) (setq _BeginCloseReactor (VLR-Dwg-Reactor nil '((:VLR-beginClose . BeginCloseFunc))))) (if (not _BeginSaveReactor ) (setq _BeginSaveReactor (VLR-Dwg-Reactor nil '((:VLR-beginSave . BeginCloseFunc))))) Edited 20 hours ago by BIGAL 1 Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.