Help kill my VBA

Started by BazzaCAD, October 02, 2009, 04:27:33 PM

Previous topic - Next topic

BazzaCAD

Hi guys, I use this small VBA code to close my current DWG & open anther DWG.
Now that VBA is semi removed from Acad2010 (yes I know I can download it), I'd like to kill all my VBA code, if possible.
Does anyone have a way to open a DWG & close the calling DWG with VLisp?


Public Sub CloseCurrentOpenPath()
  Dim ad As AcadDocument
  Dim pth As String
  Dim CloseFile As String
  Dim Response As Integer
 
  Set ad = ActiveDocument

  pth = ad.GetVariable("users2")
 
  If Not ad.GetVariable("DBMOD") = 0 Then
    Response = MsgBox("Do you want to save changes to " & ad.FullName & "?", vbYesNoCancel + vbExclamation + vbDefaultButton1, "TMaCAD")
    If Response = vbYes Then
      If ad.GetVariable("WRITESTAT") = 1 Then
        ad.Save
      End If
    ElseIf Response = vbCancel Then
      Exit Sub
    End If
  End If
   
  ad.Close False
 
  If pth <> "" Then
    Application.Documents.Open pth
  End If
 
End Sub
a.k.a.
Barry Ralphs
barryDOTralphsATgmailDOTcom

Fred Tomke

Hm, have you ever thought about a .NET DLL with a LISP-function that would do that?

If you really want to solve this via LISP I can imagine to do it this way:

  • Make sure that another drawing beside the current drawing is open (otherwise after closing the current drawing Lisp cannot be executed anymore).
  • Show a modeless form. The modeless form has an active event OnDocActivated. In a label there is written: "Wait until reopening drawing has finished..." and below it there is a readonly textbox with the fullname of the drawing to reopen.
  • Close the current drawing.
  • The other drawing is going to get active. In this moment the event OnDocActivated is called. In the event function the name of the file to reopen can be read out from the textbox. And if this file can still be found (maybe a nervous colleague has deleted my file meanwhile) it will be opened.
  • I think you are using a technology to load your app automatically to each newly opened drawing (via vl-load-all or similiar). In the end of your lisp there is a line which checks if the modeless form is active. In this case close it.
Hm, I feel it is worth to test it.  ;)
Fred
Fred Tomke
Dipl.-Ing. (FH) Landespflege

[ landscaper - landscape developer - digital landscape and urban design]

Fred Tomke

Hi, it's a quarter to 3 in the night - at this time I have the best ideas!
Barry, I send you a small example. Note: load the lisp via (vl-load-all reopen.lsp").

Fred
Fred Tomke
Dipl.-Ing. (FH) Landespflege

[ landscaper - landscape developer - digital landscape and urban design]

BazzaCAD

WOW, Fred as always you da man. ;D
How do you come up with this stuff....
Ya I thought about .NET, but know you'd come through  :)
a.k.a.
Barry Ralphs
barryDOTralphsATgmailDOTcom

Fred Tomke

Barry, I'm not very familiar with any language of MSVS .NET, unfortunately, indeed. I've already worked at a wrapper written in C# .NET which provides additional LISP functions to get access to a third party product which cannot be adressed by ActiveX. With this project in mind and the fact that Autodesk suggest developers using VBA in AutoCAD to migrate to VB .NET I thought about creating several lisp functions in a .NET-dll. But it depends on the number and content of your VBA-procedures you want to migrate.

QuoteHow do you come up with this stuff....
Very easy to tell: I remembered some of my palettes which are updating automatically after the current drawing is closed because OnDocActivated is being called. And on the other hand this modeless form is a good information what your command is currently going to do :)

But there is still a doubt towards .NET: I do not know if such a procedure in VB .NET called by a lisp-function would really work because if the current drawing is being closed, the lisp context of the current drawing has been gone, too. Will the rest of the .NET code still be executed? Lisp code won't be executed anymore cause the current execution depend on the current drawing. Does it also have the same effect in .NET? I do not know. I do know that a VBA skript can be executed between different drawings because it runs outside the drawing. But has a VB .NET skript the same behaviour? Especially if the procedure was called from Lisp? I do not know. And that's why I'd prefer the AutoLisp-way.

I have to look now to my kids what they're doing in their rooms - it sounds very strange there.

Fred
Fred Tomke
Dipl.-Ing. (FH) Landespflege

[ landscaper - landscape developer - digital landscape and urban design]

Fred Tomke

#5
Hi Barry,

So, now I know much more. I created a C# project and I've found out that you cannot close the current drawing from the Lisp context even it is a Lisp function defined in C#. But if the same code runs in a command it works very well.

Here is the code. I also attached the whole C# project (MSVS 2005). For compiling anew the acmgd.dll and the acdbmdg.dll have to be linked anew before.

For those who want to test.

  • Open AutoCAD and an existing drawing.
  • call NETLOAD from command line and load ReOpen.dll from the source project
  • call lisp function (reload). An exception will occur.
  • call command reload from commandline. The drawing will be reloaded.

As you can see the lisp function and the command are doing the same.


       [LispFunction("reload")]
       public void fun_reload()
       {
           AcadClose();    
       }

       [CommandMethod("reload", CommandFlags.Session)]

       public void cmd_reload()
       {
           AcadClose();
       }


That's the function for both:


       private string AcadClose()
       {
           DocumentCollection oDocs = acadApp.DocumentManager;
           Document oDoc = oDocs.MdiActiveDocument;

           string strCurrentFile = oDoc.Name;

           if (oDoc.IsReadOnly)
           {
               oDoc.CloseAndDiscard();
           }
           else
           {
               int isModified = System.Convert.ToInt32(acadApp.GetSystemVariable("DBMOD"));

               // No need to save if not modified
               if (isModified == 0)
               {
                   oDoc.CloseAndDiscard();
               }
               else
               {
                   int intReturn = System.Convert.ToInt32(MessageBox.Show("Do you want to save changes to " + strCurrentFile + "?", "Reopen current drawing", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1));

                   switch (intReturn)
                   {
                       case 6:
                           // this may save the drawing at strange places, espeacially if it wasn't saved before
                           // oDoc.Save(); // Does not work, not implemented yet (http://discussion.autodesk.com/forums/message.jspa?messageID=6110668)
                           oDoc.CloseAndSave(strCurrentFile);
                           break;
                       case 7:
                           oDoc.CloseAndDiscard();
                           break;
                       default:
                           strCurrentFile = "";
                           break;
                   }
               }
           }

           if (strCurrentFile != "")
           {
               try
               {
                   oDocs.Open(strCurrentFile,false);
               }
               catch (InvalidCastException e)
               {
                   throw (e);    // Rethrowing exception e
               }
           }

           return strCurrentFile;
       }
   }
}


EDIT: copy the ReOpen.dll into the AutoCAD-InstallDir that it finds the correct acmgd.dll and acdbmgd.dll for the correct AutoCAD release. DO NOT COPY THE ACMGD.DLL and ACDBMGD.DLL OF THE SOURCE DIR INTO AUTOCAD INSTALLDIR (the compiler copied them to the output folder automatically)!
This it the advantage of .NET: this DLL works with AutoCAD 2008 as well as with AutoCAD 2010 (just testet).

So, I will cook some noodles now.

Fred
Fred Tomke
Dipl.-Ing. (FH) Landespflege

[ landscaper - landscape developer - digital landscape and urban design]

Kerry


Fred,
cool, I'll have a play later.

Regarding the acmgd.dll and the acdbmdg.dll.
You should set the CopyLocal property for both to false, otherwise debugging issues may arise.

Perfection is not optional.
My other home is TheSwamp

Fred Tomke

Thanks Kerry, good to know.

Fred
Fred Tomke
Dipl.-Ing. (FH) Landespflege

[ landscaper - landscape developer - digital landscape and urban design]

BazzaCAD

Thx for the help & the code Fred, I'll try to put it to good use.
a.k.a.
Barry Ralphs
barryDOTralphsATgmailDOTcom

BazzaCAD

Here's my modified version of Fred's code.
It asks you for the file name to open, open Read-Only, & if you want to close the current DWG or not (like SDI without SDI mode).
I doesn't have much error checking in it, since I do the error checking in Lisp before I run the RELOAD command.


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Windows.Forms;
using System.IO;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.EditorInput;
using acadApp = Autodesk.AutoCAD.ApplicationServices.Application;


namespace ReOpen
{
    public class ReOpen
    {

        [CommandMethod("reload", CommandFlags.Session)]

        public void cmd_reload()
        {
         Editor ed = acadApp.DocumentManager.MdiActiveDocument.Editor;

         PromptStringOptions ops = new PromptStringOptions("\nDWG name: ");
         ops.AllowSpaces = true;
         PromptResult res = ed.GetString(ops);

         PromptStringOptions ops2 = new PromptStringOptions("\nRead-Only Y/N: ");
         PromptResult res2 = ed.GetString(ops2);

         PromptStringOptions ops3 = new PromptStringOptions("\nClose current DWG Y/N: ");
         PromptResult res3 = ed.GetString(ops3);

         if (res.Status == PromptStatus.OK && res.StringResult != string.Empty)
         {
             //MessageBox.Show(res.StringResult);
             AcadClose(res.StringResult, res2.StringResult, res3.StringResult);
         }


        }


        private string AcadClose(string FileToOpen, string RO, string CloseCurrent)
        {
            DocumentCollection oDocs = acadApp.DocumentManager;
            Document oDoc = oDocs.MdiActiveDocument;

           string strCurrentFile = oDoc.Name;

           if (CloseCurrent == "Y")
           {
               if (oDoc.IsReadOnly)
               {
                   oDoc.CloseAndDiscard();
               }
               else
               {
                   int isModified = System.Convert.ToInt32(acadApp.GetSystemVariable("DBMOD"));

                   // No need to save if not modified
                   if (isModified == 0)
                   {
                       oDoc.CloseAndDiscard();
                   }
                   else
                   {
                       int intReturn = System.Convert.ToInt32(MessageBox.Show("Do you want to save changes to " + strCurrentFile + "?", "TMaCAD", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1));

                       switch (intReturn)
                       {
                           case 6:
                               // this may save the drawing at strange places, espeacially if it wasn't saved before
                               // oDoc.Save(); // Does not work, not implemented yet (http://discussion.autodesk.com/forums/message.jspa?messageID=6110668)
                               oDoc.CloseAndSave(strCurrentFile);
                               break;
                           case 7:
                               oDoc.CloseAndDiscard();
                               break;
                           default:
                               FileToOpen = "";
                               break;
                       }
                   }
               }
           }

            if (FileToOpen != "")
            {


                if (!File.Exists(FileToOpen))
                {
                    throw new System.ArgumentException("Drawing does not exist", FileToOpen);
                }
                else
                {
                    try
                    {
                        if (RO == "Y")
                        {
                            oDocs.Open(FileToOpen, true);
                        }
                        else
                        {
                            oDocs.Open(FileToOpen, false);
                        }

                    }
                    catch (InvalidCastException e)
                    {
                        throw (e);    // Rethrowing exception e
                    }
                }
            }

            return FileToOpen;
        }
    }
}
a.k.a.
Barry Ralphs
barryDOTralphsATgmailDOTcom