Aller au contenu

Aide premier Lisp


Netparty

Messages recommandés

Bonjour à tous

J'ai pour habitude de vous demander de l'aide pour des Lisp, mais j'aimerai créer mon premier lisp tout seul.

Je vais commencer par quelque chose de simple :

- Au lancement du lisp je dois entrer une valeur pour l’échelle de type de ligne.

- Ensuite je clique sur les lignes que je doit modifier.

J'aimerai juste des pistes et fonction vers quoi je doit me diriger, merci de ne pas me donner la solution toute faite que je puisse chercher par moi même.

voilà le début de mon code :

(defun c:ECH_LIGNE (/ name)

   (setq Echelle ((getstring "Valeur") "\nSpécifiez la distance: "))
    (princ)

)

Quel éditeur utilisez-vous, moi j'ai installé visual studio code

Merci et bonne journée

Lien vers le commentaire
Partager sur d’autres sites

Pour l'éditeur j'utilise le simple Bloc-notes de Windows.
Avantage : super léger, rapide, simple sans fioriture
Inconvénient : n'affiche pas les erreurs de syntaxe ou de parenthèse manquante ou en trop, donc de bonnes sueurs froides quand AutoCAD ne veux pas lancer le programme, mais ça permet d'être plus rigoureux (enfin, normalement😇)
A conseiller ? pas forcément

Lien vers le commentaire
Partager sur d’autres sites

Coucou,

Visual Studio Code est bien, attention tout de même à l'encodage car il n'est pas le même que l'IDE classique d'AutoCAD. Si tu veux simplement apprendre à coder simplement pour AutoCAD, je pense que l'IDE classique d'AutoCAD convient parfaitement (LISPSYS = 0 pour AutoCAD 2020 ou plus et tu y accèdes avec la commande VLIDE).

Pour les fonctions, je te suggère de consulter régulièrement l'aide d'AutoCAD et notamment de garder en favori la page correspondante "Functions Reference (AutoLISP)" pouvant être accessible depuis le menu "AutoLISP: Reference > Functions Reference (AutoLISP)". Cette page permet d'accéder à l'ensemble des fonctions AutoLISP soit en cherchant par ordre alphabétique, soit par feature et fonctionnalité.

Dans le cas présent, je te conseille par exemple de consulter les fonctions "User Input" situé dans la "Feature list" "Utility". (cf. User Input Functions Reference (AutoLISP) )

Il y a également les sites de (gile), didier et LeeMac (anglais) qui sont des références, on ne le répétera jamais assez 🙂
Bon courage et surtout n'oublie pas, si tu veux apprendre, commence par comprendre ! Pour cela, rien ne vaut les essais directement sur AutoCAD, faire des recherches en s'aidant de l'aide AutoCAD et de tout autre document, ... La programmation c'est pas du par cœur, c'est uniquement de la logique et de la compréhension du pourquoi et comment on peut le faire. Après tout il n'y a pas une seule et unique solution à un problème, le principal c'est de bien cerner les limites du problème, les zones contraignantes et les zones de liberté.

Bisous,
Luna

Lien vers le commentaire
Partager sur d’autres sites

As-tu testé dans AutoCAD directement cette partie (copier coller dans la barre de commande) :

(setq echelle (getint "Quelle echelle :"))

Quel est le résultat attendu ?
Pour ma part, si c'est pour l'échelle de type de ligne d'un objet, tu peux faire le test et tu verras qu'AutoCAD accepte des valeurs non entières mais refuse des valeurs négatives.

Pour résoudre le problème des valeurs négatives il faut utiliser "abs" :

(setq echelle (abs (getint "Quelle echelle :")))

Pour que l'utilisateur puisse mettre des valeurs non entières il faut utiliser autre chose que "getint" à moins que ce soit un choix délibéré.

As-tu testé cette partie :

(    (setq e (entsel "\nSelectionner une ligne"))

La parenthèse du début est de trop 😉. Essaye dans AutoCAD, et tu verras 😉.

Il faut donc tester un à un chaque ligne directement dans AutoCAD quand on a un doute. C'est le réflexe Number 1!

Lien vers le commentaire
Partager sur d’autres sites

+1 avec @JPhil !

La première question que tu dois te poser c'est : qu'est-ce que je veux exactement ?
Une échelle de type de ligne peut parfaitement être un nombre réel strictement positif et pas uniquement un nombre entier. Comme le souligne @JPhil, il faut en effet prévoir les erreurs de l'utilisateur lambda. Donc il faut faire attention à connaître les zones contraignantes de ton programme (pour me citer 😉 ), et donc ici de connaître les limites des valeurs pouvant être prise en compte. La fonction (getint) permet de demander à l'utilisateur un nombre appartenant à l'ensemble Z (donc tout nombre entier) et la fonction (getreal) permet de demander à l'utilisateur un nombre appartenant à l'ensemble R (donc tout nombre réel). Une échelle de type de ligne est un nombre réel strictement positif, il te faut donc restreindre les entrées utilisateurs lors des demandes (getint) ou (getreal), selon ton choix.

Pour cela il y a la fonction (initget) qui permet, comme son nom l'indique, d'initialiser les fonctions (get...). Essaye de voir son fonctionnement pour restreindre la saisie utilisateur à un nombre entier/réel strictement positif.

Ensuite à quoi sert la parenthèse toute seule juste avant le (setq e ...) ? Car elle n'est pas utile 😉
De plus tu demandes à l'utilisateur de sélectionner un objet avec (entsel) (je te conseille de jeter un oeil au retour de cette fonction d'ailleurs via l'aide AutoCAD, car tu risques d'être surpris !), mais tu ne sembles pas utiliser cet objet ensuite puisque tu modifies uniquement la variable système LTSCALE. D'ailleurs, est-ce bien LTSCALE que tu souhaites modifier ?

Citation

LTSCALE (System Variable)

Sets the global linetype scale factor.

Type: Real
Saved in: Drawing
Initial value: 1.0000

The linetype scale factor cannot equal zero. This system variable has the same name as a command. Use the SETVAR command to access this system variable.

Citation

CELTSCALE (System Variable)

Sets the current object linetype scaling factor.

Type: Real
Saved in: Drawing
Initial value: 1.0000

Sets the linetype scaling for new objects relative to the LTSCALE command setting. A line created with CELTSCALE = 2 in a drawing with LTSCALE set to 0.5 would appear the same as a line created with CELTSCALE = 1 in a drawing with LTSCALE = 1.

Pour modifier une propriété, tu peux soit regarder les propriétés DXF d'un objet, accessible via (entget), soit regarder les propriétés ActiveX d'un objet, accessible via (dumpallproperties), soit regarder les propriétés Visual d'un objet, accessible via (vlax-dump-object).

Bref je suppose que ton programme n'est pas encore terminé et il te faut encore découvrir 2-3 petites choses avant d'y parvenir (comme par exemple la déclaration des variables locales qui me semble primordiale !), mais il ne faut pas se décourager pour autant !

Bisous,
Luna

Lien vers le commentaire
Partager sur d’autres sites

Comme le souligne @Luna, il y a 3 types d'utilisateurs :
- celui qui respecte les consignes,
- celui qui fait une erreur de saisie (oups!),
- celui qui tente de mettre n'importe quoi pour voir comment le programme réagit.

Donc, si l'utilisateur final n'est pas toi, il faut y mettre un cadre (un point sur les i si tu préfères).N'hésite pas non plus à mettre des commentaires, ça peut être utile quand on revient sur un ancien programme et qu'on ne sait plus le pourquoi du comment :

;;; étape 1, je demande un nombre entier supérieur à 0
(setq echelle (getint "Quelle echelle :"))
--> test pour voir si l'utilisateur a bien respecté la consigne, dans le cas contraire soit s'adapter soit reposer la question jusqu'à obtention du résultat souhaité
;;; fin étape 1

;;; étape 2, je demande à l'utilisateur de sélectionner une ligne et pas autre chose
(setq e (entsel "\nSelectionner une ligne"))
--> test pour voir si l'utilisateur a bien sélectionné une ligne, si négatif, reposer la question jusqu'à obtention du résultat souhaité
;;; fin étape 2

;;; étape 3, la suite du programme
....
;;; fin étape 3

;;; étape 4, la suite de la suite du programme
....
;;; fin étape 4


Y'a des indices cachés dans mes commentaires, à toi de bien les déchiffrer 😉 

Lien vers le commentaire
Partager sur d’autres sites

Je suppose que je déclare la variable pour la récupérer plus tard dans la première ligne :

(defun c:ECH_LIGNE (/ echelle) ; echelle est la variable

Pour les 3 lignes suivantes :

(setq echelle (getint "Quelle echelle :")) ; Je demande l'echelle
(setq e (entsel "\nSelectionner une ligne") ; je choisi la ligne que je dois changer
 (setvar  "CELTSCALE" echelle) ) ; j'applique la nouvelle echelle

Cela fonctionne mais comment savoir que c'est la sélection qui doit recevoir le nouveau paramètre CELTSCALE.

 

Lien vers le commentaire
Partager sur d’autres sites

Coucou @Netparty,

Ci-dessous la partie issue du site Introduction à AutoLISP de (gile) concernant la déclaration des variables :

Citation

En faisant précéder le nom de la fonction par "c:" la fonction est définie comme une commande AutoCAD® qu'il sera possible de lancer depuis la ligne de commande (ou d'un menu) en tapant directement le nom de la fonction. Dans l'autre cas, la fonction ne peut être lancée que dans une expression AutoLISP®. C'est l'équivalent d'une nouvelle fonction LISP utilisable comme les fonctions prédéfinies.

 
Sélectionnez
(defun Fonction (arg1 arg2 / var1 var2) ...)

arg1 et arg2 sont les arguments (non optionnels) de Fonction, ils doivent être spécifiés conformément aux besoins de Fonction.

(Fonction arg1) -> erreur : nombre d'arguments insuffisants
(Fonction arg1 arg2) -> erreur : type d'argument incorrect… si arg1 ou arg2 ne sont pas conformes au type d'arguments nécessaires à Fonction.

var1 et var2 sont des variables définies dans Fonction (avec setq par exemple).

Si elles sont déclarées, comme dans l'exemple, on les appelle des variables locales.

Les valeurs qui leur sont affectées dans Fonction ne le seront que pendant la durée de son exécution, elles reprendront ensuite la valeur qu'elles avaient avant l'appel à Fonction (nil ou autre).

Si au sein de Fonction, une valeur est attribuée à var3 avec setq, et qu'elle n'a pas été déclarée, on l'appelle variable globale, elle conserve sa valeur dans le dessin pendant toute la session.

Il peut être intéressant de conserver une valeur dans une variable globale pour la récupérer lors d'une autre exécution de routine, dans ce cas, une convention consiste à écrire le nom de la variable entre astérisques, il est aussi prudent de choisir un nom qui a peu de chance d'être utilisé par une autre fonction

Cela te permettra sûrement de mieux comprendre le pourquoi j'ai dit qu'il est important de connaître cela 🙂 Car chat peut causer de nombreux problèmes sur la programmation, surtout lorsqu'on a plusieurs commandes/fonctions et que certaine variables sont communes (notamment les constructions de liste via (cons) !).

Il y a 18 heures, Netparty a dit :

Cela fonctionne mais comment savoir que c'est la sélection qui doit recevoir le nouveau paramètre CELTSCALE.

Selon tes besoins, il est possible que la variable CELTSCALE n'ai pas besoin d'être mise à jour. Car d'après ta demande initiale :

Citation

Je vais commencer par quelque chose de simple :

- Au lancement du lisp je dois entrer une valeur pour l’échelle de type de ligne.

- Ensuite je clique sur les lignes que je doit modifier.

Pour moi je le comprends comme "seules les lignes sur lesquelles je clique durant la commande doivent être modifiées" et non comme "seules les lignes sur lesquelles je clique durant la commande et les nouvelles lignes crées à l'avenir doivent avoir la nouvelle échelle". Or en définissant CELTSCALE (ou LTSCALE), cela implique uniquement les nouvelles entités et non les existantes.

Cela commence à devenir complexe de te donner des pistes de recherche sans te donner l'exemple de code si tu ne regardes déjà pas les pistes que l'on te propose...

Il y a 19 heures, JPhil a dit :
(setq e (entsel "\nSelectionner une ligne"))
--> test pour voir si l'utilisateur a bien sélectionné une ligne, si négatif, reposer la question jusqu'à obtention du résultat souhaité
Il y a 19 heures, Luna a dit :

Pour modifier une propriété, tu peux soit regarder les propriétés DXF d'un objet, accessible via (entget), soit regarder les propriétés ActiveX d'un objet, accessible via (dumpallproperties), soit regarder les propriétés Visual d'un objet, accessible via (vlax-dump-object).

Commence par lire les liens des sites de cours que je t'ai donné, lit les jusqu'au bout et tu comprendras que toutes les questions que tu te/nous poses sont déjà dans ces documents. Si après les avoir lu, il y a toujours quelques incompréhensions revient nous voir on pourra t'aider plus facilement.

Bisous,
Luna

Lien vers le commentaire
Partager sur d’autres sites

Bonjour @Luna

Voici quelque modif, mais pour le test de sélection cela n'a pas l'air de fonctionner.

J'ai ajouter aussi (initget 4) pour empêcher les valeurs négative

(defun c:test ()
(initget 4) ; 4 pour interdire les valeurs négative
 
  (if 
    
       (setq e (entsel "\nSelectionner une ligne"))
  
   (progn
   (prompt "\nErreur : L'objet sélectionné n'est pas une ligne")
   (setq e (entsel "\nSelectionner une ligne"))
     
    ))


)

 

Lien vers le commentaire
Partager sur d’autres sites

(defun c:ECH_LIGNE (/ echelle e)
	(initget 7)
	(setq echelle (getreal "\nQuelle échelle : "))
	(while (and (setq e (car (entsel "\nSélectionner une ligne :"))) (wcmatch (cdr (assoc 0 (entget e))) "*LINE"))
		(setpropertyvalue e "LinetypeScale" echelle)
	)
	(princ)
)

ou

(defun c:ECH_LIGNE (/ echelle e)
	(initget 7)
	(setq echelle (getreal "\nQuelle échelle : "))
	(while (and (setq e (car (entsel "\nSélectionner une ligne :"))) (wcmatch (cdr (assoc 0 (entget e))) "*LINE"))
		(if (assoc 48 (entget e))
			(entmod (subst (cons 48 echelle) (assoc 48 (entget e)) (entget e)))
			(entmod (append (entget e) (list (cons 48 echelle))))
		)
	)
	(princ)
)

ou

(defun c:ECH_LIGNE (/ echelle e)
	(initget 7)
	(setq echelle (getreal "\nQuelle échelle : "))
	(while (and (setq e (car (entsel "\nSélectionner une ligne :"))) (wcmatch (cdr (assoc 0 (entget e))) "*LINE"))
		(vla-put-LineTypeScale (vlax-ename->vla-object e) echelle)
	)
	(princ)
)

Bisous,
Luna

Lien vers le commentaire
Partager sur d’autres sites

@Luna

Merci pour les différents codes, c'est plus clair.

A l'aide de la commande getkword je pourrais avoir un menu de choix.

(defun c:Outil_ligne ( / choix)
  
  (initget "? Echelle Epaisseur eXit")
  (setq chosen (cond ((getkword "\nChoisir [Echelle/Epaisseur] <eXit>: "))
		     ("eXit")))                                                                     
  
  (cond ((= choix "?")
	 )
	((= choix "Echelle")
	 (command"ECH_LIGNE"))
	((= choix "Epaisseur")
	 (command "EP_LIGNE"))
	((= choix "eXit")
	 )
  (princ)
  )


(defun c:ECH_LIGNE (/ echelle e)
	(initget 7)
	(setq echelle (getint "\nQuelle échelle : "))
	(while (and (setq e (car (entsel "\nSélectionner une ligne :"))) (wcmatch (cdr (assoc 0 (entget e))) "*LINE"))
		(vla-put-LineTypeScale (vlax-ename->vla-object e) echelle)
	)
	(princ)
)


(defun c:EP_LIGNE (/ echelle e)
	(initget 7)
	(setq echelle (getint "\nQuelle échelle : "))
	(while (and (setq e (car (entsel "\nSélectionner une ligne :"))) (wcmatch (cdr (assoc 0 (entget e))) "*LINE"))
		(vla-put-lineweight (vlax-ename->vla-object e) echelle)
	)
	(princ)
)

Mais comment appeler les 2 fonctions (ECH_LIGNE et EP_LIGNE)

 

 

Lien vers le commentaire
Partager sur d’autres sites

Coucou,

Tu as répondu à ta propre question en une seule ligne :

il y a 24 minutes, Netparty a dit :

Mais comment appeler les 2 fonctions (ECH_LIGNE et EP_LIGNE)

Il faut appeler les FONCTIONS pour que cela fonctionne. (retourne voir le message contenant un extrait du cours de (gile) que j'ai mis un peu plus tôt concernant la fonction (defun) !!!) Car je n'ai pas l'impression de donner de simples pistes de recherche mais plutôt des réponses, en boucle >n<
Par contre tu feras attention, ton (getkword) est récupéré par la variable 'chosen', puis ton (cond) évalue la valeur de la variable 'choix', donc j'ai bien peur que ton programme ne fonctionne tout simplement pas...

Une autre erreur dans la fonction (initget) et (getkword) : les lettres majuscules définissent les alias clavier pouvant être utilisé par l'utilisateur pour choisir son mot clé. Donc si deux réponses différentes possèdent la même lettre majuscule, seule la première réponse dans l'ordre de l'initget est considérée pour les deux réponses. Autrement dit, dans ton cas, si je réponds "E" alors le programme me renvoie 'chosen' = "Echelle", si je clique sur "Echelle" alors le programme me renvoie 'chosen' = "Echelle" et si je clique sur "Epaisseur" alors le programme me renvoie 'chosen' = "Echelle"...

Citation
Keyword Specifications

The string argument is interpreted according to the following rules:

  1. Each keyword is separated from the following keyword by one or more spaces. For example, "Width Height Depth" defines three keywords.
  2. Each keyword can contain only letters, numbers, and hyphens (-).

There are two methods for abbreviating keywords:

  • The required portion of the keyword is specified in uppercase characters, and the remainder of the keyword is specified in lowercase characters. The uppercase abbreviation can be anywhere in the keyword (for example, "LType", "eXit", or "toP").
  • The entire keyword is specified in uppercase characters, and it is followed immediately by a comma, which is followed by the required characters (for example, "LTYPE,LT"). The keyword characters in this case must include the first letter of the keyword, which means that "EXIT,X" is not valid.

The two brief examples, "LType" and "LTYPE,LT", are equivalent: if the user types LT (in either uppercase or lowercase letters), this is sufficient to identify the keyword. The user can enter characters that follow the required portion of the keyword, provided they don't conflict with the specification. In the example, the user could also enter LTY or LTYP, but L would not be sufficient.

If string shows the keyword entirely in uppercase or lowercase characters with no comma followed by a required part, AutoCAD recognizes the keyword only if the user enters all of it.

The initget function provides support for localized keywords. The following syntax for the keyword string allows input of the localized keyword while it returns the language independent keyword:

"local1 local2 localn _indep1 indep2 indepn"

where local1 through localn are the localized keywords, and indep1 through indepn are the language-independent keywords.

There must always be the same number of localized keywords as language-independent keywords, and the first language-independent keyword is prefixed by an underscore as shown in the following example:

(initget "Abc Def _Ghi Jkl")
(getkword "\nEnter an option (Abc/Def): ")

Entering A returns Ghi and entering _J returns Jkl.

Bisous,
Luna

Lien vers le commentaire
Partager sur d’autres sites

@Luna

Voilà j'ai enfin réussi à le faire fonctionner

Je continue mes recherche pour l'améliorer.

(defun c:Outil_Ligne ( / choix)
  
 (initget "? echelle epaisseur eXit")
  (setq choix (cond ((getkword "\nEnter and option [echelle/epaisseur] <eXit>: "))
		     ("eXit")))                                                                      
  
  (cond ((= choix "?")
	 )
	((= choix "echelle")
	 (ECH_LIGNE))
	((= choix "epaisseur")
	 (EP_LIGNE))
	((= choix "eXit")
	 (princ "... Terminé.")))
  (princ)
  )

(defun ECH_LIGNE (/ echelle e)
	(initget 7)
	(setq echelle (getint "\nQuelle échelle : "))
	(while (and (setq e (car (entsel "\nSélectionner une ligne :"))) (wcmatch (cdr (assoc 0 (entget e))) "*LINE"))
		(vla-put-LineTypeScale (vlax-ename->vla-object e) echelle)
	)
	(princ)
)


(defun EP_LIGNE (/ epaisseur e)
	(initget 7)
	(setq epaisseur (getint "\nQuelle epaisseur : "))
	(while (and (setq e (car (entsel "\nSélectionner une ligne :"))) (wcmatch (cdr (assoc 0 (entget e))) "*LINE"))
		(vla-put-lineweight (vlax-ename->vla-object e) epaisseur)
	)
	(princ)
)

 

Lien vers le commentaire
Partager sur d’autres sites

Coucou,

Tu peux éventuellement mettre une majuscule pour "echelle" et "epaisseur" dans les fonctions (initget) et (getkword), comme par exemple "ecHelle" et "ePaisseur", comme chat il suffit d'écrire "H" pour "echelle" et "P" pour "epaisseur".

Ensuite dans les améliorations possible c'est à chaque fois que tu fais quelque chose plusieurs fois, alors tu peux créer une fonction pour cela pour n'avoir à le définir qu'une seule fois.

Et à quoi sert l'option "?", normalement elle permet d'afficher un texte d'aide pour l'utilisation de la commande/fonction mais ici, elle semble ne servir à rien...^^"

Bisous,
Luna

  • Like 1
Lien vers le commentaire
Partager sur d’autres sites

Plutôt que d'essayer de faire un programme compliqué qui fait tout, essaye de faire un seul programme qui fait une seule tâche mais bien 😉 

Un programme lisp est une succession de petit programme lisp.

LA question qu'il faut se poser quand on veut tout intégrer dans un seul programme c'est :
- les petits programmes sont indépendants des uns des autres
- les petits programmes sont tous imbriqués dans un seul.

Exemple d'imbrication avec une seule sélection de la ligne :

(defun c:ECH_EP_LIGNE (/ echelle e)
    (initget 7)
    (setq echelle (getint "\nQuelle échelle : "))
    (setq epaisseur (getint "\nQuelle épaisseur : "))
    (while (and (setq e (car (entsel "\nSélectionner une ligne :"))) (wcmatch (cdr (assoc 0 (entget e))) "*LINE"))
        (vla-put-LineTypeScale (vlax-ename->vla-object e) echelle)
        (vla-put-lineweight (vlax-ename->vla-object e) epaisseur)
    )
    (princ)
)

 

  • Like 1
Lien vers le commentaire
Partager sur d’autres sites

il y a 33 minutes, JPhil a dit :

Plutôt que d'essayer de faire un programme compliqué qui fait tout, essaye de faire un seul programme qui fait une seule tâche mais bien 😉 

Un programme lisp est une succession de petit programme lisp.

LA question qu'il faut se poser quand on veut tout intégrer dans un seul programme c'est :
- les petits programmes sont indépendants des uns des autres
- les petits programmes sont tous imbriqués dans un seul.

Exemple d'imbrication avec une seule sélection de la ligne :

(defun c:ECH_EP_LIGNE (/ echelle e)
    (initget 7)
    (setq echelle (getint "\nQuelle échelle : "))
    (setq epaisseur (getint "\nQuelle épaisseur : "))
    (while (and (setq e (car (entsel "\nSélectionner une ligne :"))) (wcmatch (cdr (assoc 0 (entget e))) "*LINE"))
        (vla-put-LineTypeScale (vlax-ename->vla-object e) echelle)
        (vla-put-lineweight (vlax-ename->vla-object e) epaisseur)
    )
    (princ)
)

 

@JPhilMerci pour ton exemple. 

Lien vers le commentaire
Partager sur d’autres sites

Juste pour l'exemple de généralisation d'une fonction :

(defun SetObjectsProperty (msg search flag PpName value / f ent)
  (defun f (flag / ent PpName value)
    (cond
      ((= flag 0) ;; Propriétés DXF via (entget)
        (cons
          (quote (cdr (assoc 0 (entget ent))))
          (quote
            (if (assoc PpName (entget ent))
              (entmod (subst (cons PpName value) (assoc PpName (entget ent)) (entget ent)))
              (entmod (append (entget ent) (list (cons PpName value))))
            )
          )
        )
      )
      ((= flag 1) ;; Propriétés ActiveX via (dumpallproperties)
        (cons
          (quote (vla-get-ObjectName (vlax-ename->vla-object ent)))
          (quote (setpropertyvalue ent PpName value))
        )
      )
      ((= flag 2) ;;Propriétés Visual LISP via (vlax-dump-object)
        (cons
          (quote (vla-get-ObjectName (vlax-ename->vla-object ent)))
          (quote (vlax-put (vlax-ename->vla-object ent) PpName value))
        )
      )
    )
  )
  (while
    (and
      (setq ent (apply 'entsel (if msg (list msg))))
      (setq ent (car ent))
      (wcmatch (strcase (eval (car (f flag)))) (strcase search))
    )
    (eval (cdr (f flag)))
  )
)

Avec les arguments :

	msg		-> correspond au message afficher par la fonction (entsel)
	(type msg) = 'STR		| Ex. : "\nSélectionnez la ligne :", "\nSélectionner un cercle :", nil, ...
	search	-> correspond au filtre que l'on souhaite appliquer pour le type d'objet grâce à (wcmatch). Pour ne pas appliquer de filtre, mettre "*"
	(type search) = 'STR	| Ex. : "LINE", "line", "*Line", "*", "ARC,*LINE,CIRCLE", ...
	flag	-> correspond au type de propriété que l'on souhaite modifier entre DXF, ActiveX et Visual LISP
	(type flag) = 'INT		|	flag = 0, la variable 'search' sera comparée au code DXF 0 de l'objet sélectionné, la variable 'PpName' correspond au
										  code DXF de la propriété dispo dans la liste DXF (cf. (entget) pour connaître les propriétés dispo d'un objet)
								flag = 1, la variable 'search' sera comparée à la propriété Visual "ObjectName" de l'objet sélectionné, la variable
										  'PpName' correspond au nom de la propriété ActiveX (cf. (dumpallproperties) pour connaître les propriétés)
								flag = 2, la variable 'search' sera comparée à la propriété Visual "ObjectName" de l'objet sélectionné, la variable
										  'PpName' correspond au nom de la propriété Visual quotée (cf. (vlax-dump-object) pour connaître les 													  propriétés)
	PpName	-> correspond au nom de la propriété qui doit être modifiée. Selon la valeur de 'flag', le type de PpName est différent
	Si flag = 0, alors (type PpName) = 'INT	| Ex. : 8, 48, 50, 62, ...
	Si flag = 1, alors (type PpName) = 'STR	| Ex. : "LineTypeScale", "LineWeight", "LayerID", ...
	Si flag = 2, alors (type PpName) = 'SYM	| Ex. : 'LineTypeScale, 'LineWeight, 'Transparency, ...
	value	-> correspond à la nouvelle valeur que l'on souhaite appliquer à la propriété 'PpName'. Le type de 'value' est donc dépendant du type de
				valeur défini par la propriété
	(type value) = ...		| Ex. : 23.42, "Calque1", 2, ...

Un exemple d'utilisation :

(defun c:ECH_EP_LIGNE (/ choix)
  (initget "? ecHelle ePaisseur eXit")
  (setq
    txt "\nSélectionner une ligne :" ;; Pour définir un message commun pour les deux propriétés
    s "*LINE" ;; Pour définir un filtre commun pour les deux propriétés
    choix
      (cond
        ((getkword "\nEnter an option [ecHelle/ePaisseur] <eXit> : ")) ;; Demande à l'utilisateur la propriété à changer
        ("eXit")
      )
  )
  (cond
    ((= choix "?")
      (princ "...") ;; Texte d'aide à afficher !
    )
    ((= choix "ecHelle")
      (SetObjectsProperty txt s 2 'LineTypeScale (progn (initget 7) (getreal "\nQuelle échelle : ")))
    )
    ((= choix "ePaisseur")
      (SetObjectsProperty txt s 2 'LineWeight (progn (initget 7) (getint "\nQuelle épaisseur : ")))
    )
  )
  (princ)
)

Evidemment c'est uniquement à titre d'exemple, personne s'attends à sortir ce genre de fonctions durant l'apprentissage. Le but ici est de montrer qu'en créant des fonctions ayant une utilisation plus globale, on peut démultiplier leur utilisation dans d'autres programmes sans jamais avoir besoin de les modifier. Plus elles sont un fonctionnement généralisé, et plus leur domaine d'application est étendu. Donc par exemple celle-ci permet de modifier n'importe quelle propriété d'objet en bouclant la sélection avec un (while). Une généralisation de cette fonction serait bien entendu de sortir la boucle (while) de la fonction de modification de propriété car on préfère toujours mettre un nom d'objet en argument de fonction pour pouvoir l'utiliser aussi bien avec ou sans intervention utilisateur. 😉

Bisous,
Luna

Lien vers le commentaire
Partager sur d’autres sites

Bonjour  @Luna@JPhil

Je reviens sur mon petit lisp.

J'essaye de mettre une valeur par défaut j'ai essayé ceci :

(defun c:ECH_LIGNE (/ echelle e)
	(initget 7 "25")
	(setq echelle (getreal "\nQuelle échelle : <25> "))
	 
	(while (and (setq e (car (entsel "\nSélectionner une ligne :"))) (wcmatch (cdr (assoc 0 (entget e))) "*LINE"))
		(setpropertyvalue e "LinetypeScale" echelle)
	)
	(princ)
)

Il propose bien une valeur par défaut mais je la prend pas en compte car il ne considère pas la valeur comme une valeur numérique.

Que dois-je changer ?

Merci

Lien vers le commentaire
Partager sur d’autres sites

Généralement pour les valeurs par défaut, il s'agit de valeurs pouvant être sélectionner directement avec ENTER (ou SPACE). Autrement dit il ne s'agit pas d'un keyword mais plus une affectation de valeur dans le cas d'une entrée à vide. Pour que cela fonctionne, il faut non seulement autoriser l'utilisateur à faire une entrée à vide mais aussi tester si le retour de la fonction (get---) retourne 'nil', alors il faut lui affecter la valeur par défaut (ici 25).

Cela te suffit pour comprendre la démarche ou bien faut-il que je donne la réponse directement ? Pour info, si tu analyses logiquement mon explication, tu as toutes les billes pour écrire cette partie, aussi bien dans le déroulement des fonctions que le nom des fonctions à utiliser...

Bisous,
Luna

Lien vers le commentaire
Partager sur d’autres sites

il y a 15 minutes, Luna a dit :

Généralement pour les valeurs par défaut, il s'agit de valeurs pouvant être sélectionner directement avec ENTER (ou SPACE). Autrement dit il ne s'agit pas d'un keyword mais plus une affectation de valeur dans le cas d'une entrée à vide. Pour que cela fonctionne, il faut non seulement autoriser l'utilisateur à faire une entrée à vide mais aussi tester si le retour de la fonction (get---) retourne 'nil', alors il faut lui affecter la valeur par défaut (ici 25).

Cela te suffit pour comprendre la démarche ou bien faut-il que je donne la réponse directement ? Pour info, si tu analyses logiquement mon explication, tu as toutes les billes pour écrire cette partie, aussi bien dans le déroulement des fonctions que le nom des fonctions à utiliser...

Bisous,
Luna

Merci @Lunapour tes conseils

Voilà ce que j'ai modifié :

(defun c:ECH_LIGNE (/ echelle e)
	(initget  "25")
	(if(null(setq echelle (getreal "\nQuelle échelle : <25> ")))
	(setq echelle 25))
	 
	(while (and (setq e (car (entsel "\nSélectionner une ligne :"))) (wcmatch (cdr (assoc 0 (entget e))) "*LINE"))
		(setpropertyvalue e "LinetypeScale" echelle)
	)
	(princ)
)

J'ai modifier le initget mais je ne sais plus interdire les valeurs négative

Lien vers le commentaire
Partager sur d’autres sites

Théoriquement, il n'y a pas besoin de spécifier le 25 comme keyword dans le (initget). AutoCAD détecte automatiquement une valeur écrite entre "<...>" et pré-rempli le champ dans le cas ou la variable DYNMODE est activée.

Autrement, pour les valeurs négatives, je crois qu'il y a encore quelque chose que tu n'as pas bien compris à propos d'initget...Je te laisse relire l'aide ci-dessous :

Citation

Signature

(initget [bits] [keywords])
bits

Type: Integer

A bit-coded that allows or disallows certain types of user input. The bits can be added together in any combination to form a value between 0 and 255. If no bits argument is supplied, zero (no conditions) is assumed. The bit values are as follows:

1 (bit 0) -- Prevents the user from responding to the request by entering only Enter.

2 (bit 1) -- Prevents the user from responding to the request by entering zero.

4 (bit 2) -- Prevents the user from responding to the request by entering a negative value.

8 (bit 3) -- Allows the user to enter a point outside the current drawing limits. This condition applies to the next user-input function even if the AutoCAD LIMCHECK system variable is currently set.

16 (bit 4) -- (Not currently used.)

32 (bit 5) -- Uses dashed lines when drawing a rubber-band line or box. For those functions with which the user can specify a point by selecting a location in the drawing area, this bit value causes the rubber-band line or box to be dashed instead of solid. (Some display drivers use a distinctive color instead of dashed lines.) If the AutoCAD POPUPS system variable is 0, AutoCAD ignores this bit.

64 (bit 6) -- Prohibits input of a Z coordinate to the getdist function; lets an application ensure that this function returns a 2D distance.

128 (bit 7) -- Allows arbitrary input as if it is a keyword, first honoring any other control bits and listed keywords. This bit takes precedence over bit 0; if bits 7 and 0 are set and the user presses Enter, a null string is returned.

256 (bit 8 ) -- Give direct distance input precedence over arbitrary input. For external applications, arbitrary input is given precedence over direct distance input by default. Set this bit if you wish to force AutoCAD to evaluate user input as direct distance input. Note that legal point input from the keyboard always takes precedence over either direct distance or arbitrary input.

512 (bit 9) -- If set before a call to getpoint or getcorner, a temporary UCS will be established when the cursor crosses over the edge of a planar face of a solid. The temporary UCS is reset when the cursor moves off of a face. It is dynamically re-established when the cursor moves over a different face. After the point is acquired, the dynamic UCS is reset to the current UCS. This functionality is not enabled for non-planar faces such as the side of a cylinder.

1024 (bit 10) -- When calling getdist, getangle, getorient, getpoint, or getcorner, you may not want the distance, angle, orient, point, or corner to be influenced by ortho, polar, or otracking in the Z direction. Setting this bit before calls to any of these functions will temporarily disable ortho, polar, and otracking in the Z direction. This is useful when you create 2D entities such as a polyline, arc, or circle, or when you use the AutoCAD ARRAY command, which creates only a 2D array. In 2D-only commands it can be confusing and error-prone to allow 3D points to be entered using ortho Z, polar Z, or otrack Z.

Note: Future versions of AutoLISP may use additional initget control bits, so avoid setting bits that are not listed here.

Bisous,
Luna

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é