Flobott Posté(e) le 26 octobre 2022 Posté(e) le 26 octobre 2022 Bonjour à toutes et tous. Je me lance dans la découverte des DCL. Et ayant réussi mon premier test avec deux fichiers distincts .lsp et .dcl. J'arrive à avoir une boîte de dialogue avec mon message et mon petit bouton OK DCL1 : dialog { label = "TEST EDCL1"; spacer; : text { label = "Toto est dans la place !"; alignment = centered; } spacer; ok_only; }//Premier (defun C:DCL1 (/ Dcl_Id) (setq Dcl_Id (load_dialog "DCL1.dcl")) (new_dialog "DCL1" Dcl_Id) (start_dialog) (unload_dialog Dcl_Id) (princ) );fin de defun C:DCL1 Étape suivant, on doit pouvoir imbriquer les deux et je suis arrivé à cela avec une erreur que je n'arrive pas à résoudre. erreur: type d'argument incorrect: stringp nil (defun C:EcritureEDCL1 (/ NonFichierEDCL1 FichierEDCL1) (setq NonFichierEDCL1 (vl-filename-mktemp "tmpEDCL1.dcl") ;filename -> non de fichier. FichierEDCL1 (open NonFichierEDCL1 "W") ;(open "fichier" mode) -> ouvrir le fichier / "r" (read) pour lecture / "w" (write) pour écriture / "a" (append) pour complément. ) (write-line ;Écriture d'une ligne de texte à l'écran texte ou dans un fichier externe. (strcat ;Concaténation de plusieurs chaînes de caractères (STRING). "EDCL1 : dialog { " ;Lance la boite de dialogue DCL du nom de EDCL1. "label = \"TEST EDCL1\"; " ;Dédinition du titre de la boite de dialogue. "spacer; " ;Creation d'un espace avant le texte. ": text { " ;Affiche un texte. "label = \"Toto est dans la place !\"; " ;Définition du texte. "alignment = centered; " ;Qui est aligne au centre. "} " ;Fin du texte. "spacer; " ;Creation d'un espace apres le texte. "ok_only; " ;Creation du bouton OK (Seul). "}//EDCL1 " ;Fin du DCL. );fin strcat FichierEDCL1 ;Ouverture du fichier. ); fin write-line (setq FichierEDCL1 (close FichierEDCL1)) ;(close [descripfichier]) -> fermer le fichier. );fin defun EcritureEDCL1 (defun C:EDCL1 (/ DCL1_ID) (vl-load-com) (if FichierEDCL1(close FichierEDCL1)) ;Si fichier ouvert -> fermer le fichier. (if NonFichierEDCL1(vl-file-delete NonFichierEDCL1)) ;Si fichier temporaire existant -> le supprimer. (C:EcritureEDCL1) ;Appel le lisp d'ecriture DCL et le lance en ecriture. (setq DCL1_ID (load_dialog tmpEDCL1.dcl)) ;Appel de la boîte de dialogue DCL temporaire. (if (not (new_dialog "EDCL1" DCL1_ID)) ;Si pas d'initialisation de la boîte de dialogue. (exit) ;Alors on sort. ) (start_dialog) ;Lance l'affichage de la boite de dialogue DCL. (unload_dialog DCL1_ID) ;Décharge le fichier de la boite de dialogue DCL. (vl-file-delete tmpEDCL1) ;Supprime le fichier temporaire DCL. (princ) ;Affiche une ligne vide pour la finition. );fin de defun c:EDCL1 Je pense que c'est dans la partie d'écriture du DCL que cela ne va pas. Je n'arrive pas a comprendre ou mon code échoue. En vous remerciant d'avance pour votre lecture et futures réponses. Citer AutoCad c'est comme mon cerveau, je ne l'utilise qu'à 10% Oo
(gile) Posté(e) le 26 octobre 2022 Posté(e) le 26 octobre 2022 il y a 13 minutes, Flobott a dit : erreur: type d'argument incorrect: stringp nil À quel endroit du code l'erreur survient-elle ? Pour le savoir, dans l'éditeur Visual LISP menu Débogage > cocher Arrêt sur erreur, relancer la routine, à l'arrêt menu Débogage > Source de la dernière interruption. Voir ce screencast. Citer Gilles Chanteau - gileCAD - GitHub Développements sur mesure pour AutoCAD
Olivier Eckmann Posté(e) le 26 octobre 2022 Posté(e) le 26 octobre 2022 Vu de loin, il y a 2 soucis au minimum. - Dans la fonction principale, il manque les guillemets après le load_dialog (mais c'est un faux problème => voir remarque suivante) - ta fonction d'écriture du DCL temporaire crée un nouveau fichier et le remplit avec tes instructions DCL, donc il faut que cette fonction renvoie le nom de ce fichier pour pouvoir l'utiliser dans ton load_dialog Olivier Citer
Flobott Posté(e) le 26 octobre 2022 Auteur Posté(e) le 26 octobre 2022 Merci Gile, j'avais déjà utilisé cette méthode qui ma permis de résoudre certains autre soucis, mais depuis cette partie cela ne me cible plus rien. il y a une heure, (gile) a dit : À quel endroit du code l'erreur survient-elle ? Pour le savoir, dans l'éditeur Visual LISP menu Débogage > cocher Arrêt sur erreur, relancer la routine, à l'arrêt menu Débogage > Source de la dernière interruption. Voir ce screencast. Sans sucés sur cette partie là (Visual lisp m'affiche un message lors du Ctr-F9) , avec cette méthodes j'obtiens ceci : voir image. il y a une heure, Olivier Eckmann a dit : Vu de loin, il y a 2 soucis au minimum. - Dans la fonction principale, il manque les guillemets après le load_dialog (mais c'est un faux problème => voir remarque suivante) - ta fonction d'écriture du DCL temporaire crée un nouveau fichier et le remplit avec tes instructions DCL, donc il faut que cette fonction renvoie le nom de ce fichier pour pouvoir l'utiliser dans ton load_dialog Merci Olivier, Remplacement de (setq DCL1_ID (load_dialog tmpEDCL1.dcl)) Par (setq DCL1_ID (load_dialog NonFichierEDCL1)) et je réinitialise les variables / NonFichierEDCL1 FichierEDCL1 dans la fonction principale et non dans la partie écriture du DCL. Et j'obtiens cela : (defun C:EcritureEDCL1 (/ ) (setq NonFichierEDCL1 (vl-filename-mktemp "tmpEDCL1.dcl") ;filename -> non de fichier. FichierEDCL1 (open NonFichierEDCL1 "W") ;(open "fichier" mode) -> ouvrir le fichier / "r" (read) pour lecture / "w" (write) pour écriture / "a" (append) pour complément. ) (write-line ;Écriture d'une ligne de texte à l'écran texte ou dans un fichier externe. (strcat ;Concaténation de plusieurs chaînes de caractères (STRING). "EDCL1 : dialog { " ;Lance la boite de dialogue DCL du nom de EDCL1. "label = \"TEST EDCL1\"; " ;Dédinition du titre de la boite de dialogue. "spacer; " ;Creation d'un espace avant le texte. ": text { " ;Affiche un texte. "label = \"Toto est dans la place !\"; " ;Définition du texte. "alignment = centered; " ;Qui est aligne au centre. "} " ;Fin du texte. "spacer; " ;Creation d'un espace apres le texte. "ok_only; " ;Creation du bouton OK (Seul). "}//EDCL1 " ;Fin du DCL. );fin strcat FichierEDCL1 ;Ouverture du fichier. ); fin write-line (setq FichierEDCL1 (close FichierEDCL1)) ;(close [descripfichier]) -> fermer le fichier. );fin defun EcritureEDCL1 (defun C:EDCL1 (/ DCL1_ID NonFichierEDCL1 FichierEDCL1) (vl-load-com) (if FichierEDCL1(close FichierEDCL1)) ;Si fichier ouvert -> fermer le fichier. (if NonFichierEDCL1(vl-file-delete NonFichierEDCL1)) ;Si fichier temporaire existant -> le supprimer. (C:EcritureEDCL1) ;Appel le lisp d'ecriture DCL et le lance en ecriture. (setq DCL1_ID (load_dialog NonFichierEDCL1)) ;Appel de la boîte de dialogue DCL temporaire. (if (not (new_dialog "EDCL1" DCL1_ID)) ;Si pas d'initialisation de la boîte de dialogue. (exit) ;Alors on sort. ) (start_dialog) ;Lance l'affichage de la boite de dialogue DCL. (unload_dialog DCL1_ID) ;Décharge le fichier de la boite de dialogue DCL. (vl-file-delete tmpEDCL1) ;Supprime le fichier temporaire DCL. (princ) ;Affiche une ligne vide pour la finition. );fin de defun c:EDCL1 Et cela fonctionne 🙂 Merci pour l'aide a la réflexion. Citer AutoCad c'est comme mon cerveau, je ne l'utilise qu'à 10% Oo
Luna Posté(e) le 26 octobre 2022 Posté(e) le 26 octobre 2022 Pour rejoindre les propos de @Olivier Eckmann, la fonction (vl-filename-mktemp) renvoie le nom d'un fichier temporaire à partir d'une chaîne de base et d'une extension mais il le nom du fichier créé ne correspond que très rarement à la chaîne de caractères passée en argument !! En réalité le fichier temporaire créé ne conserve qu'un nombre limité de caractères (4-5 je crois) puis ajoute des digit si un fichier du même nom existe déjà. Autrement dit, tu pars avec l'hypothèse que ton fichier possède précisément le nom que tu as spécifié via (vl-filename-mktemp) dans ta fonction (load_dialog), outre l'oubli des guillemets. Donc ton fichier n'est pas trouvé je pense. De plus, je pense qu'il est beaucoup plus pratique d'avoir une seule fonction pour gérer aussi bien la création du fichier temporaire avec l'écriture DCL que l'initialisation et ouverture/fermeture du DCL. Ainsi cela permet de travailler avec les mêmes variables tout du long sans devoir en créer de nouvelles à chaque fois (et aussi souvent car l'initialisation de la boîte de dialogue est toujours la même pour un même fichier DCL). Cela permet ainsi d'avoir une FONCTION pour faire appel à une boîte de dialogue dont son fichier DCL est temporaire et renvoyer les résultats attendus après les saisies utilisateurs DCL dans d'autres PROGRAMMES (commandes et/ou fonctions). PS: Pardon je n'avais pas fais attention mais....tu n'as créé que des COMMANDES ici (avec le c : au niveau des (defun) ). Donc la ligne (C:EcritureEDCL1) ne fonctionne pas ! Utilise une fonction pour commencer ! Bisous, Luna Citer
Flobott Posté(e) le 26 octobre 2022 Auteur Posté(e) le 26 octobre 2022 Nos postes se sont croisé ^^ merci pour ta réponse Luna il y a 10 minutes, Luna a dit : PS: Pardon je n'avais pas fais attention mais....tu n'as créé que des COMMANDES ici (avec le c : au niveau des (defun) ). Donc la ligne (C:EcritureEDCL1) ne fonctionne pas ! Utilise une fonction pour commencer ! J'ai pour habitude d'utiliser des commande C:XXX -> (C:XXX), ce n'est peut être pas très classique mais je n'ai jamais vue la différence d'un appel de fonction XXX -> (xxx) il y a 10 minutes, Luna a dit : De plus, je pense qu'il est beaucoup plus pratique d'avoir une seule fonction pour gérer aussi bien la création du fichier temporaire avec l'écriture DCL que l'initialisation et ouverture/fermeture du DCL. Ainsi cela permet de travailler avec les mêmes variables tout du long sans devoir en créer de nouvelles à chaque fois (et aussi souvent car l'initialisation de la boîte de dialogue est toujours la même pour un même fichier DCL). Cela permet ainsi d'avoir une FONCTION pour faire appel à une boîte de dialogue dont son fichier DCL est temporaire et renvoyer les résultats attendus après les saisies utilisateurs DCL dans d'autres PROGRAMMES (commandes et/ou fonctions). Peut-tu m'en donner un exemple, je t'avoue ne pas bien saisir cette partie ? Citer AutoCad c'est comme mon cerveau, je ne l'utilise qu'à 10% Oo
Luna Posté(e) le 26 octobre 2022 Posté(e) le 26 octobre 2022 Tu peux t'inspirer de la fonction (ListBox) de @(gile) par exemple. Cette fonction permet de faire appel à une boîte de dialogue au cours d'un programme et elle gère elle-même l'écriture du fichier DCL, son initialisation, son ouverture, le traitement des interactions DCL au cours de la boîte de dialogue, puis fermeture de la boîte de dialogue, traitement des résultats, suppression du fichier DCL et renvoie les résultats. Ainsi, pas besoin de 2 programmes distincts (un pour créer le fichier, un autre pour ouvrir la boîte de dialogue) alors qu'ils devront dans tous les cas fonctionner ensembles ! Dans ton cas, si tu as séparé l'écriture de l'ouverture, l'as-tu fait délibérément ? Si oui, cela signifie que tu as prévu des cas de figures qui nécessite de pouvoir créer le fichier DCL temporaire EDCL1 sans l'ouvrir de la même manière que le ferait ta commande c:EDCL1. Quels seraient selon toi ces cas de figures ? Car s'il n'y a pas de raison de les séparer, cela peut être une raison suffisante pour les réunir en une seule fonction 😉 Bisous, Luna Citer
Olivier Eckmann Posté(e) le 26 octobre 2022 Posté(e) le 26 octobre 2022 Bonjour, Même si ça fonctionne ce n'est pas très "propre" : - éviter au maximum les variables globales. Une fonction doit renvoyer les valeurs calculées plutôt que d'initialiser des variables globales. - les fonctions commençant par C:XXX sont destinées à être appelées directement en ligne de commande. Les fonctions qui ne sont appelées qu'à l'intérieur d'autres fonctions ne "devraient" pas commencer par "C:" . Même si cela fonctionne, c'est une habitude très répandue et respectée parmi les développeurs lisp. - la dernière commande (vl-file-delete tmpEDCL1) ne doit pas faire grand chose, car la variable tmpEDCL1 n'est jamais initialisée par aucun des 2 lisp. - les 2 premières lignes ne servent à rien, car si tu as bien programmé ta fonction d'écriture du DCL, le (close FichierEDCL1)) a déjà fermé le fichier. Inutile de le fermer de nouveau dans l'autre Lisp. Et le delete du fichier temporaire doit se faire à la fin et pas au début. De toute manière le make-tmp en créera un nouveau. Olivier Citer
Flobott Posté(e) le 26 octobre 2022 Auteur Posté(e) le 26 octobre 2022 Il y a 2 heures, Luna a dit : Tu peux t'inspirer de la fonction (ListBox) de @(gile) par exemple. Cette fonction permet de faire appel à une boîte de dialogue au cours d'un programme et elle gère elle-même l'écriture du fichier DCL, son initialisation, son ouverture, le traitement des interactions DCL au cours de la boîte de dialogue, puis fermeture de la boîte de dialogue, traitement des résultats, suppression du fichier DCL et renvoie les résultats. Ainsi, pas besoin de 2 programmes distincts (un pour créer le fichier, un autre pour ouvrir la boîte de dialogue) alors qu'ils devront dans tous les cas fonctionner ensembles ! Merci pour l'exemple, je n'y manquerai pas en poussant et en regroupant mon code. Il y a 2 heures, Luna a dit : Dans ton cas, si tu as séparé l'écriture de l'ouverture, l'as-tu fait délibérément ? Si oui, cela signifie que tu as prévu des cas de figures qui nécessite de pouvoir créer le fichier DCL temporaire EDCL1 sans l'ouvrir de la même manière que le ferait ta commande c:EDCL1. Quels seraient selon toi ces cas de figures ? Car s'il n'y a pas de raison de les séparer, cela peut être une raison suffisante pour les réunir en une seule fonction 😉 J'ai séparé l'écriture de l'ouverture pour mieux comprendre les deux, j'ai dans l'idée d'ajouter une interface DCL à un de mes lisps ou j'aurais plusieurs écritures. Dans un premier temps, maintenant que je visualise mieux comment cela fonctionne, je vais déjà tester les différents types de bouton. Et ensuite essayé de mélanger les boutons, les textes ... j'ai même cru voir des interfaces graphiques en DCL ^^ C'est la découverte pour moi cette partie en DCL et cela me fait découvrir de nouvelle chose en lisp. Il y a 2 heures, Olivier Eckmann a dit : - les fonctions commençant par C:XXX sont destinées à être appelées directement en ligne de commande. Les fonctions qui ne sont appelées qu'à l'intérieur d'autres fonctions ne "devraient" pas commencer par "C:" . Même si cela fonctionne, c'est une habitude très répandue et respectée parmi les développeurs lisp. - la dernière commande (vl-file-delete tmpEDCL1) ne doit pas faire grand chose, car la variable tmpEDCL1 n'est jamais initialisée par aucun des 2 lisp. - les 2 premières lignes ne servent à rien, car si tu as bien programmé ta fonction d'écriture du DCL, le (close FichierEDCL1)) a déjà fermé le fichier. Inutile de le fermer de nouveau dans l'autre Lisp. Et le delete du fichier temporaire doit se faire à la fin et pas au début. De toute manière le make-tmp en créera un nouveau. En tenant compte de vos remarques, j'arrive à cela. Merci pour le coup de pouce 😉 Citer AutoCad c'est comme mon cerveau, je ne l'utilise qu'à 10% Oo
Messages recommandés