Aller au contenu

(defun-q S::STARTUP ...)


(gile)

Messages recommandés

NOTA : Ce sujet a été reconstitué après une fausse manipulation de part

 

Salut

 

Un sujet qui fait suite à celui là mais un peu plus avancé (d'où le choix de ce forum).

 

Dans le sujet sus-cité, il est question de chargement automatique des expressions et routines AutoLISP via les fichiers acad.lsp, acaddoc.lsp et MNL.

Ces fichiers étant chargés avant l'initialisation complète du document, ils ne peuvent, à priori, contenir d'expressions LISP utilisant la fonction command qui n'est pleinement opérationnelle qu'après l'initialisation complète du dessin.

 

On peut définir une fonction nommée S::STARTUP dans un de ces fichiers qui ne sera exécutée qu'une fois le dessin initialisé. Cette fonction pourra donc contenir des appels de la fonction command qui est parfois difficilement contournable (commandes NETLOAD, UNDEFINE ...)

 

Habituellement, la fonction S::STARTUP est définie avec defun-q plutôt qu'avec defun.

 

defun-q est fournie essentiellement dans un soucis de compatibilité avec les versions d'AutoLISP antérieures. Depuis l'arrivée de Visual LISP (R14), la fonction defun provoque la compilation de la fonction définie et génère un objet de type USUBR (ou SUBR). Dans les versions antérieures la fonction était définie sous forme de liste. defun-q permet de retrouver l'ancien comportement de defun.

 

Commande: (defun hello1 () (princ "Hello word") (princ))

HELLO1

 

Commande: (defun-q hello2 () (princ "Hello word") (princ))

HELLO2

 

Commande: !hello1

#

 

Commande: !hello2

(nil (PRINC "Hello word") (PRINC))

Définir une fonction sous forme de liste peut avoir certains avantages*, notamment celui de pouvoir aisément redéfinir la fonction en modifiant sa liste. C'est pour cela qu'on l'utilise pour S::STARTUP.

 

Exemple de ce que pourrait contenir un fichier acaddoc.lsp.

Une fonction c:-fenetres qui est une redéfinition de la commande -FENETRES. Elle change le calque courant durant son exécution et restaure la calque courant initial.

 

La fonction S::STARTUP est ensuite redéfinie (ou définie si elle n'existait pas) en lui ajoutant les expressions :

(command "_.undefine" "-fenetres") (princ)

 

;; Redéfinition de la commande -FENETRES
;; Si elle est appelée depuis l'espace papier, le calque courant est remplacé par le
;; calque "VPORTS". S'il n'existe pas, ce calque est créé (gris et non imprimable).

(defun c:-fenetres (/ *error* clay)
 (defun *error* (msg)
   (or	(= msg "Fonction annulée")
(princ (strcat "\nErreur: " msg))
   )
   (setvar "CLAYER" clay)
   (princ)
 )
 (setq clay (getvar "CLAYER"))
 (if (= 1 (getvar "CVPORT"))
   (progn
     (if (null (tblsearch "LAYER" "VPORTS"))
(entmake '((0 . "LAYER")
	   (100 . "AcDbSymbolTableRecord")
	   (100 . "AcDbLayerTableRecord")
	   (2 . "VPORTS")
	   (70 . 0)
	   (62 . 253)
	   (290 . 0)
	  )
)
     )
     (setvar "CLAYER" "VPORTS")
     (command "_.vports")
     (while (/= 0 (getvar "CMDACTIVE"))
(command pause)
     )
     (setvar "CLAYER" clay)
   )
   (command "_.vports")
 )
 (princ)
)

;; S::STARTUP
;; Ajout de l'expression (command "_.undefine" "-fenetres") à S::STRARTUP
;; La fonction est définie si elle ne l'était pas déjà.
(if S::STARTUP
 (setq	S::STARTUP
 (append S::STARTUP
	 '((command "_.undefine" "-fenetres") (princ))
 )
 )
 (defun-q S::STARTUP
   ()
   (command "_.undefine" "-fenetres")
   (princ)
 )
)

 

* On trouve une très judicieuse utilisation de defun-q dans la routine ai_sysvar (C:\ProgramFiles\AutoCAD 200X\Support\acad200Xdoc.lsp)

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Lien vers le commentaire
Partager sur d’autres sites

Réponse à une question de lili2006 :

Surement très intéressant,...

MAIS, j'ai bien peur, une fois de plus, de ne pas te suivre entièrement,... :(

Un ch'ti éclaircissement serait le bienvenue pour moi, ;)

Merci d'avance, :P

 

Il est possible de redéfinir les commandes natives AutoCAD pour en modifier le comportement. On utilise pour ça une commande définie en LISP du même nom que la commande native qui sera appelée dans AutoCAD et la commande _undefine (NONDEF).

 

La commande native restera accessible en LISP ou à la ligne de commande en faisant précéder son nom par un point.

 

La commande _redefine (REDEF) restaure la commande native.

 

NOTA : l'effet de la commande _undefine est actif pendant toute la session, il est donc impératif que le LISP qui redéfinit la commande soit chargé à chaque ouverture de document.

 

Dans l'exemple donné, le but est que les fenêtres créées dans les présentations avec la commande -fenetres en ligne de commande ou avec les boutons de la barre d'outils "Fenêtres" qui utilisent cette commande soient automatiquement placées sur un calque (VPORTS, gris, non imprimable).

 

On définit donc une commande en LISP nommée c:-fenetres, qui aura ce comportement :

 

(defun c:-fenetres (/ *error* clay)

 ;; Redéfinir de la fonction *error* pour restaurer le calque courant si l'utilisateur fait ECHAP
 (defun *error* (msg)
   (or	(= msg "Fonction annulée")
(princ (strcat "\nErreur: " msg))
   )
   (setvar "CLAYER" clay)
   (princ)
 )

 ;; stocker la valeur du calque courant
 (setq clay (getvar "CLAYER")) 

 ;; Si l'espace courant est l'EP...
 (if (= 1 (getvar "CVPORT"))
   (progn

     ;; ... si le calque VPORTS n'existe pas, le créer
     (if (null (tblsearch "LAYER" "VPORTS"))
(entmake '((0 . "LAYER")
	   (100 . "AcDbSymbolTableRecord")
	   (100 . "AcDbLayerTableRecord")
	   (2 . "VPORTS")
	   (70 . 0)
	   (62 . 253)
	   (290 . 0)
	  )
)
     )

     ;; Rendre VPORTS courant
     (setvar "CLAYER" "VPORTS")

     ;; lancer la commande _.vports (-fenetres en ligne de commande) native
     (command "_.vports")

     ;; laisser la main à l'utilisateur (ou aux options spécifiées dans une macro)
     ;; jusqu'à la fin de la commande
     (while (/= 0 (getvar "CMDACTIVE"))
(command pause)
     )

     ;; restaurer le calque courant
     (setvar "CLAYER" clay)
   )

   ;; Si l'espace courant est l'EO, lancer la commande native
   (command "_.vports")
 )
 (princ)
)

 

(on appelle ensuite la commande _undefine pour supprimer la définition native de la commande AutoCAD

 

(command "_.undefine" "-fenetres")

 

Si on veut que ceci soit fait à chaque ouverture de document, il faut inclure cette expression dans la fonction S::STARTUP qui sera placée dans un fichier de chargement automatique.

 

Comme il est possible d'avoir plusieurs fichiers de chargement automatique : acaddoc.lsp et différents MNL liés à différents fichiers de menu (CUI), et qu'une seule fonction S::STARTUP doit être définie, il est prudent dans chacun de ces fichiers qui nécessiterait une appel à S::STARTUP de redéfinir la fonction si elle existe déjà ou de la définir si elle n'existe pas encore.

 

C'est là que l'utilisation de defun-q à la place de defun prend tout son intérêt.

 

(if S::STARTUP
 ;; si la fonction S::STARTUP existe (elle est non nil), ajouter (append) la liste des expressions
 (setq	S::STARTUP
 (append S::STARTUP
	 '((command "_.undefine" "-fenetres") (princ))
 )
 )

 ;; si la fonction S::STARTUP n'existe pas (elle est nil), la définir avec defun-q
 (defun-q S::STARTUP
   ()
   (command "_.undefine" "-fenetres")
   (princ)
 )
)

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Lien vers le commentaire
Partager sur d’autres sites

Réponse à une quetion de lili2006 :

Ok ! Merci pour ce complément d'information et cet exemple (que je comprend mieux maintenant), plus qu'utile,...

Je vais tester ça dès que j'ai un moment,...

Juste une petite question (peut-être l'a-tu déjà évoqué,...)

Pourquoi "defun-q" plutôt que "defun" dans ce cas de figure ,

Merci d'avance et merci pour cette "astuce",... :P

 

Parce que la fonction définie avec defun-q l'est sous forme de liste (au lieu d'une fonction compilée). On peu donc aisément la redéfinir (modifier sa définition) avec les fonctions LISP de manipulation des listes (notamment append pour ajouter des instructions à la définition de départ).

 

Reprenons l'exemple ci dessus, le code est ajouté au fichier acaddoc.lsp, et sera donc chargé à chaque ouverture de document.

Si on interroge la valeur de S::STRARTUP en ligne de commande :

 

Commande: !S::STARTUP

(nil (COMMAND "_.undefine" "-fenetres") (PRINC))

 

On obtient bien une liste.

 

Imaginons qu'on ait un CUI partiel : "toto.CUI" avec un fichier MNL associé : "toto.mnl" et qu'on veuille, quand ce CUI est chargé que les dessins s'ouvrent en zoom étendu*.

Il suffit de modifier la fonction S::STARTUP dans le fichier MNL.

Les fichiers MNL étant chargés après les fichiers acaddoc.lsp, on peut se contenter de modifier la fonction S::STARTUP avec append**.

 

(setq S::STARTUP
      (append S::STARTUP
       '((command "_.zoom" "_extents") (princ))
      )
)

 

Résultat : si "toto.Cui" est chargé, les dessin s'ouvrent avec la commande -fenetres redéfinie et en zoom étendu. S'il n'est pas chargé, seule la commande fenêtre est redéfinie.

 

* Ceci n'est qu'un exemple pour illustrer le propos, inutile de s'attarder sur sa pertinence.

**Par prudence on pourrait aussi utiliser le type d'expression :

(if S::STARTUP (setq S::STARTUP (append ...)) (defun-q S::STARTUP ...))

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Lien vers le commentaire
Partager sur d’autres sites

Créer un compte ou se connecter pour commenter

Vous devez être membre afin de pouvoir déposer un commentaire

Créer un compte

Créez un compte sur notre communauté. C’est facile !

Créer un nouveau compte

Se connecter

Vous avez déjà un compte ? Connectez-vous ici.

Connectez-vous maintenant
×
×
  • Créer...

Information importante

Nous avons placé des cookies sur votre appareil pour aider à améliorer ce site. Vous pouvez choisir d’ajuster vos paramètres de cookie, sinon nous supposerons que vous êtes d’accord pour continuer. Politique de confidentialité