Aller au contenu

Détournement de QSave pendant eTransmit


PhilOctet

Messages recommandés

Bonsoir à tous,

 

Mon p'tit programme de traitement de mes fichiers dessin AutoCAD tourne.

 

Je passe dans une phase de test avec l'environnement. Notamment, je détourne les sauvegardes afin d'y appliquer une partie de ces traitements.

 

Bref, dans la série des 'QSave', il y a la commande 'eTransmit' qui déclenche une sauvegarde. La variable 'cmdnames' nous donne la commande en cours. Mais lorsque j'arrive sur l'évênement 'BeginSave', ce n'est pas la commande 'eTransmit' qui est donné par la variable mais la commande 'QSave'.

Comment puis-récupérer la "vraie" commande déclenchée à savoir' eTransmit' ?

 

Ce que voudrait faire : L'opérateur lance la commande eTransmit qui déclenche un QSave. le programme prendre en charge la sauvegarde et relance l'eTransmit et crée enfin le zip.

 

Je pensais aussi utiliser la variable 'DBMod' mais je ne vois pas comment l'intégrer dans ma routine.

 

A moins que quelqu'un ai une meilleur idée !

 

merci et à bientôt

Lien vers le commentaire
Partager sur d’autres sites

Bonjour,

 

Mes collègues font souvent des sauvegardes de leur dessin. Ce qui est une bonne chose.

 

Je déclenche un traitement à chaque sauvegarde. En voici le code.

 

Module Module1

 

' récupère le chemin du dessins courant

Public DWGPath As String

Public DWGName As String

Public DWG As String

 

'' Executer à chaque ouverture d'un dessin (nouveau ou existant)

Public Sub OnDocumentCreated(ByVal sender As Object, ByVal e As DocumentCollectionEventArgs)

 

Dim acDoc As Document = Application.DocumentManager.MdiActiveDocument

AddHandler acDoc.BeginDocumentClose, AddressOf docBeginDocClose

 

Dim acDb As AcBdd.Database = acDoc.Database

AddHandler acDb.BeginSave, AddressOf docBeginSave

 

End Sub

 

'' Executer à chaque fermeture de fenetre de dessin

Public Sub docBeginSave()

 

Dim CmdNames As String = Application.GetSystemVariable("cmdnames")

Dim DBMod As Integer = Application.GetSystemVariable("dbmod")

Debug.Print (CmdNames & " / " & DBMod)

 

Dim acDoc As Document = AcApp.DocumentManager.MdiActiveDocument

 

' récupère le chemin du dessin courant

DWGPath = Application.GetSystemVariable("DwgPrefix")

DWGName = Application.GetSystemVariable("DwgName")

DWG = AF_ScanLAN.strLanPath(DWGPath & DWGName)

 

Call Traitements()

 

End Sub

 

Il y a surement d'autres façons de faire. Et tout aussi surement plus classe. Avez-vous une idée à me proposer ?

 

Merci de votre soutient et au plaisir de vous lire.

Lien vers le commentaire
Partager sur d’autres sites

Salut,

 

Je ne comprends pas la demande.

Je t'avais donné un exemple ici pour garantir que tous les documents ouverts au chargement de l'application et tous ceux qui seront ouverts par la suite seront abonnés à l'évènement.

 

D'autre part, j'ai du mal à lire le VB d'autant plus qu'il est présenté dans le corps du message, sans identations.

S'il te plait utilise les balises bbcode :

 

[surligneur][[/surligneur][surligneur]code[/surligneur][surligneur]][/surligneur] ici le code [surligneur][[/surligneur][surligneur]/code[/surligneur][surligneur]][/surligneur]

 

donne :

 ici  le code 

 

Accessibles avec l'icône # :

http://img94.imageshack.us/img94/8380/bbcode.png

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

Lien vers le commentaire
Partager sur d’autres sites

De ce que j'arrive à voir, tu n'utilises pas ce qui existe déjà...

 

Tu devrais pouvoir remplacer :

Dim acDoc As Document = Application.DocumentManager.MdiActiveDocument
AddHandler acDoc.BeginDocumentClose, AddressOf docBeginDocClose

Dim acDb As AcBdd.Database = acDoc.Database
AddHandler acDb.BeginSave, AddressOf docBeginSave

par :

AddHandler e.Document.Database.BeginSave, AddressOf docBeginSave

puis que tu ne semble pas utiliser docBeginDocClose.

 

 

Et, de même :

DWGPath = Application.GetSystemVariable("DwgPrefix")
DWGName = Application.GetSystemVariable("DwgName")
DWG = AF_ScanLAN.strLanPath(DWGPath & DWGName)

par :

DWG = AF_ScanLAN.strLanPath(e.FileName)

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

Lien vers le commentaire
Partager sur d’autres sites

Les procédures de traitement avec BeginSave se déclenchent lorsque qu'il le faut, même pendant l'eTransmit.

Il m'avait sembler avoir considéré tes conseils du message dans la réponse n°3 de http://cadxp.cadmag.info/XForum+viewthread-fid-42-tid-26409-page-2.html

 

Toutefois, le tout fonctionne bien. Cela pourrait être mieux soit, mais ca roule !

Aussi j'ai d'autres traitements pour la fermeture du dessin sans sauvegarde.

 

Mais dans mon cas de figure, ce n'est pas 'eTransmit' qui effectue la sauvegarde. La commande repose la question de sauvegarde sans fin jusqu'à la pression de la touche annuler. Donc la sauvegarde n'est pas effectuée par 'eTransmit' et la commande est interrompue.

 

Donc je ne peux plus genérer de 'eTransmit'. Ce qui est un drame pour mon outil.

 

Comment faire ?

Lien vers le commentaire
Partager sur d’autres sites

Si tu as une instruction SaveAs dans ton traitement, elle déclenchera indéfiniment l'évènement BeginSave (boucle sans fin).

Soit tu supprimes cette instruction du traitement,

soit tu désabonnes docBeginSave de l'évènement BeginSave avant l'instruction SaveAs et tu le réabonnes ensuite.

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

Lien vers le commentaire
Partager sur d’autres sites

C'est ce je cherche à faire. Mais, pour l'instant, que lors de l'appel à la fonction 'eTransmit'.

 

Non, je ne fais pas de sauvegarde dans mes traitements puisque c'est AutoCAD que s'en charge.

 

Je pensais pouvoir récupérer le nom de la commande 'eTransmit' dans la variable 'cmdnames'. Ce que je récupère est en fait 'QSave' puisque 'eTransmit' lance la commande 'QSave'.

 

Comment ne pas effectuer les traitements liés aux sauvegardes lors de l'appel de 'eTransmit' ?

 

Merci

 

[Edité le 20/2/2010 par PhilOctet]

Lien vers le commentaire
Partager sur d’autres sites

Non, je ne fais pas de sauvegarde dans mes traitements

C'est curieux que tu rentres dans une boucle sans fin alors :casstet:

 

Essaye ca, le traitement se limite à ouvrir une boite d'alerte signifiant que l'évènement est déclenché la boite de dialogue s'affiche et le Etransmit s'effectue ensuite sans problème :

Imports Autodesk.AutoCAD.ApplicationServices
Imports Autodesk.AutoCAD.DatabaseServices
Imports Autodesk.AutoCAD.Runtime

Namespace EventTest
   Public Class MyPlugin
       Implements IExtensionApplication
       Private docMan As DocumentCollection = Application.DocumentManager
       
       Public Sub Initialize()
           AddHandler docMan.DocumentCreated, AddressOf docMan_DocumentCreated
           For Each doc As Document In docMan
               AddHandler doc.Database.BeginSave, AddressOf Database_BeginSave
           Next
       End Sub
       
       Public Sub Terminate()
       End Sub
       
       Private Sub docMan_DocumentCreated(ByVal sender As Object, ByVal e As DocumentCollectionEventArgs)
           AddHandler e.Document.Database.BeginSave, AddressOf Database_BeginSave
       End Sub
       
       Private Sub Database_BeginSave(ByVal sender As Object, ByVal e As DatabaseIOEventArgs)
           Application.ShowAlertDialog("BeginSave")
       End Sub
   End Class
End Namespace

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

Lien vers le commentaire
Partager sur d’autres sites

Effectivement, cela va mieux. Donc le problème ne vient pas de "mes évênements".

 

Et traçant le code, j'ai découvert que AutoCAD me reposait la question en boucle à cause la ligne :

 
app.ActiveDocument.SendCommand("_.-xref _reload * " & vbLf)

Et si je met cette ligne en remarque, 'eTransmit' ne me repose plus la question.

 

Le code est celui que tu m'as généreusement offert. je ne l'ai que très peu défiguré.

 	'' Modifie le chemin des XRefs (Dwg) en chemin relatif
Public Sub Abs2RelXRefs()

	Dim doc As Document = AcApp.DocumentManager.MdiActiveDocument
	Dim db As AcBdd.Database = doc.Database
	Dim ed As Editor = doc.Editor

	' récupère le chemin du dessin courant
	DWGPath = Application.GetSystemVariable("DwgPrefix")
	DWGName = Application.GetSystemVariable("DwgName")
	DWG = AF_ScanLAN.strLanPath(DWGPath & DWGName)

	DWGPath = DWGPath.Trim(New Char() {"\"c})
	Using tr As AcBdd.Transaction = db.TransactionManager.StartTransaction()

		' Traitement des xrefs
		Dim xrg As AcBdd.XrefGraph = db.GetHostDwgXrefGraph(True)
		Dim gnc As New AcBdd.GraphNodeCollection()
		Dim i As Integer = 0
		While i < xrg.NumNodes
			gnc.Add(xrg.GetXrefNode(i))
			i += 1  'System.Math.Max(System.Threading.Interlocked.Increment(i), i - 1)
		End While

		Dim LstUnloadXRefs As New ArrayList
		Dim app As AcadApplication = Application.AcadApplication

		Try
			Dim j As Integer = 1
			While j < xrg.NumNodes
				Dim xrgn As AcBdd.XrefGraphNode = xrg.GetXrefNode(j)
				If (Not xrgn.IsNested) AndAlso (xrgn.XrefStatus <> AcBdd.XrefStatus.FileNotFound) Then

					Call SetXrefRelativePath(xrgn, xrg, gnc, tr, DWG, LstUnloadXRefs)

				End If
				j += 1 'System.Math.Max(System.Threading.Interlocked.Increment(j), j - 1)
			End While
		Catch ex As System.Exception
			ed.WriteMessage(vbLf & "Erreur: " + ex.Message)
		End Try

		app.ActiveDocument.SendCommand("_.-xref _reload * " & vbLf)
		If LstUnloadXRefs.Count > 0 Then
			Dim AllUnlXRefs As String = LstUnloadXRefs(0)
			For Idx As Int16 = 1 To LstUnloadXRefs.Count - 1
				AllUnlXRefs = AllUnlXRefs & "," & LstUnloadXRefs(Idx)
			Next
			app.ActiveDocument.SendCommand("_.-xref _unload " & AllUnlXRefs & vbLf)
		End If

		tr.Commit()
	End Using

End Sub

 

J'ai mis cette ligne parce que j'avais besoin de régénérer mes XRefs en relatif dans le gestionaire d'XRefs.

 

Et je ne peux les recharger systématiquement parce que, quelques fois, les utilisateurs déchargent leurs XRefs.

 

Il faut que nous trouvions une autre solution pour modifier visuellement cette ligne dans le gesttionnaire.

 

As-tu une idée ? merci

Lien vers le commentaire
Partager sur d’autres sites

Regarde si, suivant la version d'AutoCAD que tu utilises, tu as les méthodes Database.UnloadXrefs() et Database.ReloadXrefs() (elles existent en 2010 mais pas en 2007).

 

Si tu les as, il suffit de faire 2 ObjectIdCollection un avec toutes les xrefs traitées et un autre avec celles qui sont traitées et déchargées.

Une fois les xrefs traitées tu les recharges toutes avec ReloadXrefs() puis tu décharges celles qui étaient déchargées.

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

Lien vers le commentaire
Partager sur d’autres sites

J'ai trouvé une solution sans les méthodes Database.UnloadXrefs() et Database.ReloadXrefs() avec COM.

 

XrefGraph xrg = db.GetHostDwgXrefGraph(true);
[surligneur]List xrefs = new List();
List unloaded = new List();[/surligneur]
for (int i = 1; i {
   XrefGraphNode xrgn = xrg.GetXrefNode(i);
   if ((!xrgn.IsNested) && (xrgn.XrefStatus != XrefStatus.FileNotFound))
   {
       try
       {
           BlockTableRecord btr =
               (BlockTableRecord)tr.GetObject(xrgn.BlockTableRecordId, OpenMode.ForWrite);
           [surligneur]xrefs.Add((AcadBlock)btr.AcadObject);[/surligneur]
           [surligneur]if (xrgn.XrefStatus == XrefStatus.Unloaded)[/surligneur]
               [surligneur]unloaded.Add((AcadBlock)btr.AcadObject);[/surligneur]
           btr.PathName = GetRelativePath(folder, btr.PathName);
       }
       catch (System.Exception ex)
       {
           ed.WriteMessage("\nErreur: " + ex.Message);
       }
   }
}
[surligneur]foreach (AcadBlock xr in xrefs)
{[/surligneur]
  [surligneur] xr.Reload();[/surligneur]
[surligneur]}
foreach (AcadBlock xr in unloaded)
{[/surligneur]
  [surligneur] xr.Unload();
}[/surligneur]

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

Lien vers le commentaire
Partager sur d’autres sites

- Comment trouves-tu les infos ?

- Sur quelles documentations t'appuies-tu ?

 

En ce qui concerne les APIs DotNET, il y a de la doc dans ObjectARX2010 (.\Docs\acad_mgd.chm) et j'utilise aussi arxref(.net) pour 2007.

Et l'Intellisense de Visual Studio qui te propose une liste déroulante des méthodes propriétés et évènements des objets

 

En ce qui concerne les APIs COM il y l'Aide aux développeurs d'AutoCAD : ActiveX and VBA Reference.

 

Quelle méthode as tu essayé et sur quelle version ?

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

Lien vers le commentaire
Partager sur d’autres sites

J'ai essayé la première méthode. Mais j'ai pour projet d'essayer la deuxième et ce rapidement.

 

En ce qui concerne la doc, tu as la capacité de trouver vite ce je cherche longtemps. Peut-être parce que je ne sais pas ce que cherche ?

 

Il y a un ouvrage VB.Net pour AutoCAD 2010 sur amazone.com http:// http://www.amazon.com/s/ref=nb_sb_ss_i_7_7?url=search-alias%3Daps&field-keywords=vb.net+for+autocad&sprefix=vb.net+

 

Mais en ce moment il est en rupture de stock.

Lien vers le commentaire
Partager sur d’autres sites

J'ai oublié de te répondre à une question

Quelle méthode as tu essayé et sur quelle version ?

 

J'ai intégré la 1ère méthode et je vais essayé la 2ème.

 

J'ai la version 2010 et j'ai la chance de pouvoir des essais sur la version 2011.

 

Mais j'ai hatte de trouver un RealDWG SDK pour faire qlq dev sur des fichiers .dwg sans AutoCAD.

 

Lien vers le commentaire
Partager sur d’autres sites

  • 4 semaines après...

Bonjour,

 

Mes routines ont été déployés sur une dizaine de postes de mon entreprise qui comporte 130 AutoCAD 200x que je compte migrer en v2011.

 

Il en ressort que le traitement systématique à chaque sauvegarde pause plus de problème que cela en résoud.

 

J'utilisai un évênement BeginSave. Mais voilà, cet évenement est appelé dans de nombreuses commandes AutoCAD : eTransmit (Pb que ensemble avons résolu), Publier (commande souvent utilisée).

 

Je ne voudrais pas faire un bouton qui déclenche le traitement à la demande.

 

Donc existe-t-il un moyen qui me permettrait de lancer mon traitement à l'apel de la commande QSave ? Soit par Ctrl+S, fermer la fenêtre puis sauvegarde.

 

1er élément de réponse : Je sais qu'en AutoLisp, il est possible d'encapsuler une commande AutoCAD dans une commande personnalisée qui prend la place de la dite commande AutoCAD par l'intermédiaire d'un "undefine". Je ne sais pas le faire en VB.Net. Qu'elle est l'instruction qui me le permettrait ?

 

2ème élément de réponse : Existe-t-il un moyen de savoir qu'elle est(sont) la commande(s) en cours avec les lesquels je pourrais combiner via un "Select Case" afin de déclencher mon traitement.

 

Si je suis dans ce forum, c'est aussi pour entendre (lire) d'autres suggestions.

Lien vers le commentaire
Partager sur d’autres sites

Salut,

 

Tu peux utilise l'évènement Document.CommandWillSart()

 

public class CommandEventPlugin : IExtensionApplication
   {
       private DocumentCollection docMan = Application.DocumentManager;

       // Abonnement du DocumentManager à l'évènement "DocumentCreated"
       // Abonnement de tous les documents déjà ouverts à l'évènement "CommandWillStart"
       void IExtensionApplication.Initialize()
       {
           docMan.DocumentCreated += new DocumentCollectionEventHandler(OnDocumentCreated);
           foreach (Document doc in docMan)
           {
               doc.CommandWillStart += new CommandEventHandler(doc_CommandWillStart);
           }
       }

       void IExtensionApplication.Terminate() { }

       // Réaction à l'ouverture d'un document => abonnement à l'évènement "CommandWillStart"
       private void OnDocumentCreated(object sender, DocumentCollectionEventArgs e)
       {
           e.Document.CommandWillStart += new CommandEventHandler(doc_CommandWillStart);
       }

       // Réaction à l'évènement "CommandWillStart" 
       void doc_CommandWillStart(object sender, CommandEventArgs e)
       {
           if (e.GlobalCommandName == "QSAVE")
               Application.ShowAlertDialog("Sauvegarde lancée");
       }
   }

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é